From a0d6c2028fe045668ebc1c5d9378b2056bf3004c Mon Sep 17 00:00:00 2001 From: Simon Date: Tue, 18 Jul 2023 14:44:31 +0200 Subject: [PATCH 1/5] Try to fix marker size --- src/bezier.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bezier.jl b/src/bezier.jl index d9074dcb7dd..3a5f1f9cb49 100644 --- a/src/bezier.jl +++ b/src/bezier.jl @@ -510,8 +510,8 @@ function render_path(path, bitmap_size_px = 256) outline_ref = make_outline(path_transformed) # Adjust bitmap size to match path aspect - w = ceil(Int, bitmap_size_px * aspect[1]) - h = ceil(Int, bitmap_size_px * aspect[2]) + w = floor(Int, bitmap_size_px * aspect[1]) + h = floor(Int, bitmap_size_px * aspect[2]) pitch = w * 1 # 8 bit gray pixelbuffer = zeros(UInt8, h * pitch) bitmap_ref = Ref{FT_Bitmap}() From 4e3be2cf9aa1e12747008a131a7d351dc6102d7e Mon Sep 17 00:00:00 2001 From: ffreyer Date: Wed, 19 Jul 2023 14:44:08 +0200 Subject: [PATCH 2/5] fix markersize --- ReferenceTests/src/tests/primitives.jl | 11 +++++++++++ src/bezier.jl | 5 +++-- src/utilities/texture_atlas.jl | 12 +++++++++--- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/ReferenceTests/src/tests/primitives.jl b/ReferenceTests/src/tests/primitives.jl index 4327bf8ab7e..679c13e3f2c 100644 --- a/ReferenceTests/src/tests/primitives.jl +++ b/ReferenceTests/src/tests/primitives.jl @@ -248,6 +248,17 @@ end for (i, marker) in enumerate(markers) scatter!(Point2f.(1:5, i), marker = marker, markersize = range(10, 30, length = 5), color = :black) scatter!(Point2f.(1:5, i), markersize = 4, color = :white) + + # # Debug - show bbox outline + # if !(marker isa Char) + # scene = Makie.get_scene(ax) + # bb = Makie.bbox(Makie.DEFAULT_MARKER_MAP[marker]) + # w, h = widths(bb) + # ox, oy = origin(bb) + # xy = map(pv -> Makie.project(pv, Vec2f(widths(pixelarea(scene)[])), Point2f(5, i)), scene.camera.projectionview) + # bb = map(xy -> Rect2f(xy .+ 30 * Vec2f(ox, oy), 30 * Vec2f(w, h)), xy) + # lines!(bb, linewidth = 1, color = :orange, space = :pixel, linestyle = :dash) + # end end f diff --git a/src/bezier.jl b/src/bezier.jl index 3a5f1f9cb49..e319ee0b392 100644 --- a/src/bezier.jl +++ b/src/bezier.jl @@ -510,8 +510,9 @@ function render_path(path, bitmap_size_px = 256) outline_ref = make_outline(path_transformed) # Adjust bitmap size to match path aspect - w = floor(Int, bitmap_size_px * aspect[1]) - h = floor(Int, bitmap_size_px * aspect[2]) + w = ceil(Int, bitmap_size_px * aspect[1]) + h = ceil(Int, bitmap_size_px * aspect[2]) + pitch = w * 1 # 8 bit gray pixelbuffer = zeros(UInt8, h * pitch) bitmap_ref = Ref{FT_Bitmap}() diff --git a/src/utilities/texture_atlas.jl b/src/utilities/texture_atlas.jl index bc413a87273..e871e4545b7 100644 --- a/src/utilities/texture_atlas.jl +++ b/src/utilities/texture_atlas.jl @@ -485,8 +485,9 @@ function bezierpath_pad_scale_factor(atlas::TextureAtlas, bp) end function marker_scale_factor(atlas::TextureAtlas, path::BezierPath) - # padded_width = (unpadded_target_width + unpadded_target_width * pad_per_unit) - return (1f0 .+ bezierpath_pad_scale_factor(atlas, path)) .* widths(Makie.bbox(path)) + # TODO: Why is it like this? + pad_scale = bezierpath_pad_scale_factor(atlas, path) + return (1 ./ pad_scale .+ 1) .* minimum(pad_scale) .* maximum(widths(Makie.bbox(path))) end function rescale_marker(atlas::TextureAtlas, pathmarker::BezierPath, font, markersize) @@ -510,8 +511,13 @@ function rescale_marker(atlas::TextureAtlas, char::Char, font, markersize) end function offset_bezierpath(atlas::TextureAtlas, bp::BezierPath, markersize::Vec2, markeroffset::Vec2) + # TODO: explain bb = bbox(bp) - pad_offset = origin(bb) .- 0.5f0 .* bezierpath_pad_scale_factor(atlas, bp) .* widths(bb) + wh = widths(bb) + pad_scale = bezierpath_pad_scale_factor(atlas, bp) + # this moves the original bezierpath origin to... something with pixel rounding applied? + o = origin(bb) .+ 0.5f0 * wh .- 0.5f0 * minimum(pad_scale) * maximum(wh) ./ pad_scale + pad_offset = o .- 0.5f0 .* minimum(pad_scale) .* maximum(wh) return markersize .* pad_offset end From 6efc1924137c0f02358c55c30ba8cbee940a5369 Mon Sep 17 00:00:00 2001 From: ffreyer Date: Wed, 19 Jul 2023 16:26:09 +0200 Subject: [PATCH 3/5] simplify and explain --- src/utilities/texture_atlas.jl | 38 ++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/src/utilities/texture_atlas.jl b/src/utilities/texture_atlas.jl index e871e4545b7..b503ffc1e09 100644 --- a/src/utilities/texture_atlas.jl +++ b/src/utilities/texture_atlas.jl @@ -481,13 +481,15 @@ function bezierpath_pad_scale_factor(atlas::TextureAtlas, bp) full_pixel_size_in_atlas = uv_width * Vec2f(size(atlas)) # left + right pad - cutoff from pixel centering full_pad = 2f0 * atlas.glyph_padding - 1 - return full_pad ./ (full_pixel_size_in_atlas .- full_pad) + # size without padding + unpadded_pixel_size = full_pixel_size_in_atlas .- full_pad + # See offset_bezierpath + return full_pixel_size_in_atlas ./ maximum(unpadded_pixel_size) end function marker_scale_factor(atlas::TextureAtlas, path::BezierPath) - # TODO: Why is it like this? - pad_scale = bezierpath_pad_scale_factor(atlas, path) - return (1 ./ pad_scale .+ 1) .* minimum(pad_scale) .* maximum(widths(Makie.bbox(path))) + # See offset_bezierpath + return bezierpath_pad_scale_factor(atlas, path) * maximum(widths(bbox(path))) end function rescale_marker(atlas::TextureAtlas, pathmarker::BezierPath, font, markersize) @@ -511,14 +513,28 @@ function rescale_marker(atlas::TextureAtlas, char::Char, font, markersize) end function offset_bezierpath(atlas::TextureAtlas, bp::BezierPath, markersize::Vec2, markeroffset::Vec2) - # TODO: explain + # - wh = widths(bbox(bp)) is the untouched size of the given bezierpath + # - full_pixel_size_in_atlas is the size of the signed distance field in the + # texture atlas. This includes glyph padding + # - px_size is the size of signed distance field without padding + # To correct scaling on glow, stroke and AA widths in GLMakie we need to + # keep the aspect ratio of the aspect ratio (somewhat) correct when + # generating the sdf. This results in direct proportionality only for the + # longer dimension of wh and px_size. The shorter side becomes inaccurate + # due to integer rounding issues. + # 1. To calculate the width we can use the ratio of the proportional sides + # scale = maximum(wh) / maximum(px_size) + # to scale the padded_size we need to display + # scale * full_pixel_size_in_atlas + # (Part of this is moved to bezierpath_pad_scale_factor) + # 2. To calculate the offset we can simple move to the center of the bezier + # path and consider that the center of the final marker. (From the center + # scaling should be equal in ±x and ±y direction respectively.) + bb = bbox(bp) - wh = widths(bb) - pad_scale = bezierpath_pad_scale_factor(atlas, bp) - # this moves the original bezierpath origin to... something with pixel rounding applied? - o = origin(bb) .+ 0.5f0 * wh .- 0.5f0 * minimum(pad_scale) * maximum(wh) ./ pad_scale - pad_offset = o .- 0.5f0 .* minimum(pad_scale) .* maximum(wh) - return markersize .* pad_offset + scaled_size = bezierpath_pad_scale_factor(atlas, bp) * maximum(widths(bb)) + return markersize * (origin(bb) .+ 0.5f0 * widths(bb) .- 0.5f0 .* scaled_size) + end function offset_bezierpath(atlas::TextureAtlas, bp, scale, offset) From 0e291f47f553b1fb1a756cdf1b9a645aad8d2b52 Mon Sep 17 00:00:00 2001 From: ffreyer Date: Wed, 19 Jul 2023 20:49:40 +0200 Subject: [PATCH 4/5] avoid scaling due to rounding in downsampling --- src/bezier.jl | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/bezier.jl b/src/bezier.jl index e319ee0b392..ca6cf185cac 100644 --- a/src/bezier.jl +++ b/src/bezier.jl @@ -502,16 +502,23 @@ function render_path(path, bitmap_size_px = 256) # freetype has no ClosePath and EllipticalArc, so those need to be replaced path_replaced = replace_nonfreetype_commands(path) - aspect = widths(bbox(path)) / maximum(widths(bbox(path))) - path_unit_rect = fit_to_bbox(path_replaced, Rect2f(Point2f(0), aspect)) + # Minimal size that becomes integer when mutliplying by 64 (target size for + # atlas). This adds padding to avoid blurring/scaling factors from rounding + # during sdf generation + path_size = widths(bbox(path)) / maximum(widths(bbox(path))) + w = ceil(Int, 64 * path_size[1]) + h = ceil(Int, 64 * path_size[2]) + path_size = Vec2f(w, h) / 64f0 + + path_unit_rect = fit_to_bbox(path_replaced, Rect2f(Point2f(0), path_size)) path_transformed = Makie.scale(path_unit_rect, scale_factor) outline_ref = make_outline(path_transformed) - # Adjust bitmap size to match path aspect - w = ceil(Int, bitmap_size_px * aspect[1]) - h = ceil(Int, bitmap_size_px * aspect[2]) + # Adjust bitmap size to match path size + w = ceil(Int, bitmap_size_px * path_size[1]) + h = ceil(Int, bitmap_size_px * path_size[2]) pitch = w * 1 # 8 bit gray pixelbuffer = zeros(UInt8, h * pitch) From 77cc78d7002151442c1ee620307ad6b53576c3fe Mon Sep 17 00:00:00 2001 From: SimonDanisch Date: Thu, 20 Jul 2023 12:11:32 +0200 Subject: [PATCH 5/5] update texture atlas --- src/utilities/texture_atlas.jl | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/utilities/texture_atlas.jl b/src/utilities/texture_atlas.jl index b503ffc1e09..1db50d598db 100644 --- a/src/utilities/texture_atlas.jl +++ b/src/utilities/texture_atlas.jl @@ -70,7 +70,7 @@ function Base.show(io::IO, atlas::TextureAtlas) println(io, " font_render_callback: ", length(atlas.font_render_callback)) end -const SERIALIZATION_FORMAT_VERSION = "v2" +const SERIALIZATION_FORMAT_VERSION = "v3" # basically a singleton for the textureatlas function get_cache_path(resolution::Int, pix_per_glyph::Int) @@ -489,7 +489,7 @@ end function marker_scale_factor(atlas::TextureAtlas, path::BezierPath) # See offset_bezierpath - return bezierpath_pad_scale_factor(atlas, path) * maximum(widths(bbox(path))) + return bezierpath_pad_scale_factor(atlas, path) * maximum(widths(bbox(path))) end function rescale_marker(atlas::TextureAtlas, pathmarker::BezierPath, font, markersize) @@ -514,13 +514,13 @@ end function offset_bezierpath(atlas::TextureAtlas, bp::BezierPath, markersize::Vec2, markeroffset::Vec2) # - wh = widths(bbox(bp)) is the untouched size of the given bezierpath - # - full_pixel_size_in_atlas is the size of the signed distance field in the + # - full_pixel_size_in_atlas is the size of the signed distance field in the # texture atlas. This includes glyph padding # - px_size is the size of signed distance field without padding - # To correct scaling on glow, stroke and AA widths in GLMakie we need to - # keep the aspect ratio of the aspect ratio (somewhat) correct when - # generating the sdf. This results in direct proportionality only for the - # longer dimension of wh and px_size. The shorter side becomes inaccurate + # To correct scaling on glow, stroke and AA widths in GLMakie we need to + # keep the aspect ratio of the aspect ratio (somewhat) correct when + # generating the sdf. This results in direct proportionality only for the + # longer dimension of wh and px_size. The shorter side becomes inaccurate # due to integer rounding issues. # 1. To calculate the width we can use the ratio of the proportional sides # scale = maximum(wh) / maximum(px_size) @@ -530,9 +530,9 @@ function offset_bezierpath(atlas::TextureAtlas, bp::BezierPath, markersize::Vec2 # 2. To calculate the offset we can simple move to the center of the bezier # path and consider that the center of the final marker. (From the center # scaling should be equal in ±x and ±y direction respectively.) - + bb = bbox(bp) - scaled_size = bezierpath_pad_scale_factor(atlas, bp) * maximum(widths(bb)) + scaled_size = bezierpath_pad_scale_factor(atlas, bp) * maximum(widths(bb)) return markersize * (origin(bb) .+ 0.5f0 * widths(bb) .- 0.5f0 .* scaled_size) end