Skip to content

Commit e7e7e03

Browse files
authored
Merge pull request #290 from GPrimola/extended_draw_rounded_rectangle
Support draw rounded rectangles with varying corners.
2 parents 4beaed5 + f63d4e4 commit e7e7e03

File tree

2 files changed

+93
-0
lines changed

2 files changed

+93
-0
lines changed

lib/scenic/script.ex

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ defmodule Scenic.Script do
184184
@op_draw_ellipse 0x09
185185
@op_draw_text 0x0A
186186
@op_draw_sprites 0x0B
187+
@op_draw_rrectv 0x0C
187188
@op_draw_script 0x0F
188189

189190
@op_begin_path 0x20
@@ -273,6 +274,10 @@ defmodule Scenic.Script do
273274
x3 :: number, y3 :: number, fill_stroke()}}
274275
| {:draw_rect, {width :: number, height :: number, fill_stroke()}}
275276
| {:draw_rrect, {width :: number, height :: number, radius :: number, fill_stroke()}}
277+
| {:draw_rrectv,
278+
{width :: number, height :: number, upperLeftRadius :: number,
279+
upperRightRadius :: number, lowerRightRadius :: number, lowerLeftRadius :: number,
280+
fill_stroke()}}
276281
| {:draw_sector, {radius :: number, radians :: number, fill_stroke()}}
277282
| {:draw_arc, {radius :: number, radians :: number, fill_stroke()}}
278283
| {:draw_circle, {radius :: number, fill_stroke()}}
@@ -535,6 +540,41 @@ defmodule Scenic.Script do
535540
[{:draw_rrect, {width, height, radius, flag}} | ops]
536541
end
537542

543+
@doc """
544+
Draw a rounded rectangle defined by height, width, radius1, radius2, radius3 and radius4. Can be filled or stroked.
545+
546+
Radii values will be set as follow:
547+
548+
- Upper left corner: radius1
549+
- Upper right corner: radius2
550+
- Lower right corner: radius3
551+
- Lower left corner: radius4
552+
553+
Creates a new path and draws it.
554+
"""
555+
@spec draw_variable_rounded_rectangle(
556+
ops :: t(),
557+
width :: number,
558+
height :: number,
559+
r1 :: number,
560+
r2 :: number,
561+
r3 :: number,
562+
r4 :: number,
563+
fill_stroke_flags :: fill_stroke()
564+
) :: ops :: t()
565+
def draw_variable_rounded_rectangle(ops, width, height, r1, r2, r3, r4, flag) do
566+
upper_left_radius = smallest([r1, width / 2, height / 2])
567+
upper_right_radius = smallest([r2, width / 2, height / 2])
568+
lower_right_radius = smallest([r3, width / 2, height / 2])
569+
lower_left_radius = smallest([r4, width / 2, height / 2])
570+
571+
[
572+
{:draw_rrectv,
573+
{width, height, upper_left_radius, upper_right_radius, lower_right_radius, lower_left_radius, flag}}
574+
| ops
575+
]
576+
end
577+
538578
@doc """
539579
Draw a sector defined by radius and an angle. Can be filled or stroked.
540580
@@ -1510,6 +1550,19 @@ defmodule Scenic.Script do
15101550
]
15111551
end
15121552

1553+
defp serialize_op({:draw_rrectv, {w, h, ulR, urR, lrR, llR, flag}}) do
1554+
<<
1555+
@op_draw_rrectv::16-big,
1556+
to_flag(flag)::16-big,
1557+
w::float-32-big,
1558+
h::float-32-big,
1559+
ulR::float-32-big,
1560+
urR::float-32-big,
1561+
lrR::float-32-big,
1562+
llR::float-32-big
1563+
>>
1564+
end
1565+
15131566
defp serialize_op({:script, id}) do
15141567
[
15151568
<<
@@ -2261,6 +2314,20 @@ defmodule Scenic.Script do
22612314
{{:draw_sprites, {id, cmds}}, bin}
22622315
end
22632316

2317+
defp deserialize_op(<<
2318+
@op_draw_rrectv::16-big,
2319+
flag::16-big,
2320+
w::float-32-big,
2321+
h::float-32-big,
2322+
ulR::float-32-big,
2323+
urR::float-32-big,
2324+
lrR::float-32-big,
2325+
llR::float-32-big,
2326+
bin::binary
2327+
>>) do
2328+
{{:draw_rrectv, {w, h, ulR, urR, lrR, llR, from_flag(flag)}}, bin}
2329+
end
2330+
22642331
defp deserialize_op(<<
22652332
@op_draw_script::16-big,
22662333
id_size::16,

test/scenic/script_test.exs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,32 @@ defmodule Scenic.ScriptTest do
118118
[{:draw_rrect, {13.0, 12.0, 6.0, :stroke}}]
119119
end
120120

121+
test "draw_variable_rounded_rectangle varying all corners works" do
122+
expected = [{:draw_rrectv, {10.0, 11.0, 2.0, 3.0, 4.0, 5.0, :fill}}]
123+
assert Script.draw_variable_rounded_rectangle([], 10, 11, 2, 3, 4, 5, :fill) == expected
124+
assert expected == Script.serialize(expected) |> Script.deserialize()
125+
126+
assert Script.draw_variable_rounded_rectangle([], 10, 11, 2, 3, 4, 5, :stroke) ==
127+
[{:draw_rrectv, {10.0, 11.0, 2.0, 3.0, 4.0, 5.0, :stroke}}]
128+
129+
assert Script.draw_variable_rounded_rectangle([], 10, 11, 2, 3, 4, 5, :fill_stroke) ==
130+
[{:draw_rrectv, {10.0, 11.0, 2.0, 3.0, 4.0, 5.0, :fill_stroke}}]
131+
end
132+
133+
test "draw_variable_rounded_rectangle varying all corners shrinks radius if too big" do
134+
assert Script.draw_variable_rounded_rectangle([], 10, 12, 30, 40, 50, 4, :fill) ==
135+
[{:draw_rrectv, {10.0, 12.0, 5.0, 5.0, 5.0, 4.0, :fill}}]
136+
137+
assert Script.draw_variable_rounded_rectangle([], 13, 12, 30, 40, 5, 60, :stroke) ==
138+
[{:draw_rrectv, {13.0, 12.0, 6.0, 6.0, 5.0, 6.0, :stroke}}]
139+
140+
assert Script.draw_variable_rounded_rectangle([], 13, 12, 30, 4, 50, 60, :stroke) ==
141+
[{:draw_rrectv, {13.0, 12.0, 6.0, 4.0, 6.0, 6.0, :stroke}}]
142+
143+
assert Script.draw_variable_rounded_rectangle([], 13, 12, 3, 40, 50, 60, :stroke) ==
144+
[{:draw_rrectv, {13.0, 12.0, 3.0, 6.0, 6.0, 6.0, :stroke}}]
145+
end
146+
121147
test "draw_sector works" do
122148
expected = [{:draw_sector, {10.0, 3.0, :fill}}]
123149
assert Script.draw_sector([], 10, 3, :fill) == expected

0 commit comments

Comments
 (0)