Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rectangle update #338

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 0 additions & 4 deletions src/cairo_backends.jl
Expand Up @@ -615,10 +615,6 @@ function draw(img::Image, form::Form)
end
end

function draw(img::Image, prim::RectanglePrimitive)
rectangle(img, prim.corner, prim.width, prim.height)
fillstroke(img)
end

function draw(img::Image, prim::PolygonPrimitive)
length(prim.points) <= 1 && return
Expand Down
117 changes: 39 additions & 78 deletions src/form.jl
Expand Up @@ -135,84 +135,6 @@ resolve(box::AbsoluteBox, units::UnitBox, t::Transform, p::ComplexPolygonPrimiti
form_string(::ComplexPolygon) = "CP"


# Rectangle
# ---------

struct RectanglePrimitive{P <: Vec, M1 <: Measure, M2 <: Measure} <: FormPrimitive
corner::P
width::M1
height::M2
end

const Rectangle{P<:RectanglePrimitive} = Form{P}

"""
rectangle()

Define a rectangle that fills the current context completely.
"""
function rectangle()
prim = RectanglePrimitive((0.0w, 0.0h), 1.0w, 1.0h)
return Rectangle{typeof(prim)}([prim])
end

"""
rectangle(x0, y0, width, height)

Define a rectangle of size `width`x`height` with its top left corner at the point (`x`, `y`).
"""
function rectangle(x0, y0, width, height, tag=empty_tag)
corner = (x_measure(x0), y_measure(y0))
width = x_measure(width)
height = y_measure(height)
prim = RectanglePrimitive(corner, width, height)
return Rectangle{typeof(prim)}([prim], tag)
end

"""
rectangle(x0s::AbstractArray, y0s::AbstractArray, widths::AbstractArray, heights::AbstractArray)

Arguments can be passed in arrays in order to perform multiple drawing operations at once.
"""
rectangle(x0s::AbstractArray, y0s::AbstractArray,
widths::AbstractArray, heights::AbstractArray, tag=empty_tag) =
@makeform (x0 in x0s, y0 in y0s, width in widths, height in heights),
RectanglePrimitive{Vec2, Measure, Measure}((x_measure(x0), y_measure(y0)),
x_measure(width), y_measure(height)) tag


function resolve(box::AbsoluteBox, units::UnitBox, t::Transform,
p::RectanglePrimitive)
corner = resolve(box, units, t, p.corner)
width = resolve(box, units, t, p.width)
height = resolve(box, units, t, p.height)

if isxflipped(units) && hasunits(Length{:cx}, p.corner[1])
# if coordinates are flipped we end up with the corner on the other end
# of the rectangle, which is fix here
x = corner[1] - width
else
x = corner[1]
end

if isyflipped(units) && hasunits(Length{:cy}, p.corner[2])
y = corner[2] - height
else
y = corner[2]
end

return RectanglePrimitive{AbsoluteVec2, AbsoluteLength, AbsoluteLength}(
(x, y), width, height)
end

boundingbox(form::RectanglePrimitive, linewidth::Measure,
font::AbstractString, fontsize::Measure) =
BoundingBox(form.corner.x - linewidth,
form.corner.y - linewidth,
form.width + 2*linewidth,
form.height + 2*linewidth)

form_string(::Rectangle) = "R"

# Circle
# ------
Expand Down Expand Up @@ -801,6 +723,45 @@ end



"""
rectangle()

Define a rectangle that fills the current context completely.
"""
rectangle() = rectangle(0.0w, 0.0h, 1.0w, 1.0h)


"""
rectangle(x0, y0, width, height)

Define a rectangle of size `width`x`height` with a corner at the point (`x`, `y`).
`width` and `height` (from the corner point) can be positive or negative.
"""
function rectangle(x0, y0, width, height, tag=empty_tag)
x, y = x_measure(x0), y_measure(y0)
w, h = x_measure(width), y_measure(height)
points = Tuple{Measure, Measure}[(x,y), (x+w,y), (x+w,y+h), (x,y+h)]
return Form([PolygonPrimitive(points)], tag)
end


"""
rectangle(x0s::AbstractArray, y0s::AbstractArray, widths::AbstractArray, heights::AbstractArray)

Arguments can be passed in arrays in order to perform multiple drawing operations at once.
"""
function rectangle(x0s::AbstractArray, y0s::AbstractArray, widths::AbstractArray, heights::AbstractArray, tag=empty_tag)
VecType = Tuple{Measure, Measure}
PrimType = PolygonPrimitive{VecType}
polyprims = PrimType[]
for (x0,y0,width,height) in cyclezip(x0s, y0s, widths, heights)
p = rectangle(x0, y0, width, height)
push!(polyprims, PrimType(p.primitives[1].points))
end
return Form{PrimType}(polyprims, tag)
end





15 changes: 0 additions & 15 deletions src/pgf_backend.jl
Expand Up @@ -341,21 +341,6 @@ function draw(img::PGF, prim::LinePrimitive, idx::Int)
write(img.buf, ";\n")
end

function draw(img::PGF, prim::RectanglePrimitive, idx::Int)
width = max(prim.width.value, 0.01)
height = max(prim.height.value, 0.01)

modifiers, props = get_vector_properties(img, idx)
img.visible || return

write(img.buf, join(modifiers))
@printf(img.buf, "\\path [%s] ", join(props, ","));
@printf(img.buf, "(%s,%s) rectangle +(%s,%s);\n",
svg_fmt_float(prim.corner[1].value),
svg_fmt_float(prim.corner[2].value),
svg_fmt_float(width),
svg_fmt_float(height))
end

function draw(img::PGF, prim::PolygonPrimitive, idx::Int)
n = length(prim.points)
Expand Down
33 changes: 0 additions & 33 deletions src/svg.jl
Expand Up @@ -737,39 +737,6 @@ function draw(img::SVG, form::Form{T}) where T
end
end

function draw(img::SVG, prim::RectanglePrimitive, idx::Int)
# SVG will hide rectangles with zero height or width. We'd prefer to have
# zero width/height rectangles stroked, so this is a work-around.
width = max(prim.width, 0.01mm)
height = max(prim.height, 0.01mm)

x0 = prim.corner[1] + width/2
y0 = prim.corner[2] + height/2
translated_path = [(-width/2,-height/2), ( width/2,-height/2),
( width/2, height/2), (-width/2, height/2)]

indent(img)

img.indentation += 1
print(img.out, "<g transform=\"translate(")
svg_print_float(img.out, x0.value)
print(img.out, ",")
svg_print_float(img.out, y0.value)
print(img.out, ")\"")
print_vector_properties(img, idx)
print(img.out, ">\n")
indent(img)

print(img.out, "<path d=\"")
print_svg_path(img.out, translated_path)
write(img.out, " z\"")
print(img.out, " class=\"primitive\"")
print(img.out, "/>\n")

img.indentation -= 1
indent(img)
print(img.out, "</g>\n")
end

function draw(img::SVG, prim::PolygonPrimitive, idx::Int)
n = length(prim.points)
Expand Down
3 changes: 1 addition & 2 deletions test/examples/golden_rect.jl
Expand Up @@ -5,9 +5,8 @@ using Compose
using Base.MathConstants

function golden_rect(n::Int)
poly_points = [(0, 0), (1, 0), (1, 1), (0, 1)]
if n == 0 return context() end
c = compose(context(), polygon(poly_points), fill(LCHab(90, 80, 70-20n)), stroke("black"))
c = compose(context(), rectangle(), fill(LCHab(90, 80, 70-20n)), stroke("black"))
compose(c, (context(0,0,1/φ,1/φ, rotation=Rotation(-π/2,1,0)), golden_rect(n-1)))
end

Expand Down
4 changes: 3 additions & 1 deletion test/examples/transformations.jl
Expand Up @@ -9,7 +9,9 @@ img = compose(context(),
(context(0,0,0.5,0.5), xgon(0.2,0.2,0.1,3,0.3),
(context(mirror=Mirror(-π/4, 0.4,0.4)), xgon(0.2,0.2,0.1,3,0.3)) ),
(context(0.5,0,0.5,0.5), xgon(0.5,0.5,0.2,3,0.3), fill("silver"),
(context(shear=Shear(0.8, 0, 0.5,0.5)), xgon(0.5,0.5,0.2,3,0.3), fill(nothing), stroke("black")) )
(context(shear=Shear(0.8, 0, 0.5,0.5)), xgon(0.5,0.5,0.2,3,0.3), fill(nothing), stroke("black")) ),
(context(0.0,0.5,0.5,0.5), rectangle(0.3,0.4,0.4,0.2), fill(nothing), stroke("silver"),
(context(rotation=Rotation(π/6)), rectangle(0.3,0.4,0.4,0.2), stroke("black")) )
)

draw.(imgs, [img])
Expand Down
8 changes: 4 additions & 4 deletions test/misc.jl
Expand Up @@ -13,7 +13,7 @@ import Cairo
# compact printing
show(IOContext(io, :compact=>true), tomato_bisque)
str = String(take!(io))
@test str == "Context(Context(R,f),Context(C,f))"
@test str == "Context(Context(SP,f),Context(C,f))"

# full printing
show(io, context())
Expand Down Expand Up @@ -78,9 +78,9 @@ bm = bitmap("fake", rand(UInt8,10), 0, 1, 0.8, 0.7, :image)
@test isa(Compose.polygon(), Compose.Polygon)
@test isa(Compose.polygon([(1,2),(3,5),(4,2)]), Compose.Polygon)

@test isa(Compose.rectangle(), Compose.Rectangle)
@test isa(Compose.rectangle(0,1,0.3,0.8), Compose.Rectangle)
@test isa(Compose.rectangle(rand(5),rand(5),rand(5),rand(5)), Compose.Rectangle)
@test isa(Compose.rectangle(), Compose.Polygon)
@test isa(Compose.rectangle(0,1,0.3,0.8), Compose.Polygon)
@test isa(Compose.rectangle(rand(5),rand(5),rand(5),rand(5)), Compose.Polygon)

@test isa(Compose.circle(), Compose.Circle)
@test isa(Compose.circle(3.2,1.4,0.8), Compose.Circle)
Expand Down