Skip to content

Commit 97ccdb6

Browse files
aplavinffreyer
andauthored
Implement text glow rendering in CairoMakie (#5542)
* Implement text glow rendering in CairoMakie Fixes #4625 * Update CHANGELOG.md --------- Co-authored-by: Frederic Freyer <frederic481994@hotmail.de>
1 parent 37400e1 commit 97ccdb6

2 files changed

Lines changed: 35 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## Unreleased
44

5+
- Added text glow to CairoMakie [#5542](https://github.com/MakieOrg/Makie.jl/pull/5542)
56
- Allow to set low or high bound of the colorrange and let the other side stay adaptive [#5555](https://github.com/MakieOrg/Makie.jl/pull/5555)
67
- Barplot `bar_labels` now support `RichText` (e.g. subscript/superscript) both directly and via `label_formatter` [#5578](https://github.com/MakieOrg/Makie.jl/pull/5578)
78
- CairoMakie now batches glyphs from the same text string into a single PDF/SVG text object, so that text can be selected and edited as a unit in vector editors like Inkscape and Illustrator [#5561](https://github.com/MakieOrg/Makie.jl/pull/5561)

CairoMakie/src/scatter.jl

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ function draw_atomic(scene::Scene, screen::Screen, plot::Text)
4747
inputs = [
4848
:text_blocks, :font_per_char, :glyphindices, :marker_offset, :text_rotation,
4949
:text_scales, :text_strokewidth, :text_strokecolor, :markerspace,
50-
:text_color,
50+
:text_color, :glowwidth, :glowcolor,
5151
:positions_in_markerspace, :projectionview, :eye_to_clip, :cam_view, :resolution,
5252
:transform_marker, :size_model, :unclipped_indices,
5353
]
@@ -154,6 +154,9 @@ function draw_text(ctx, attr::NamedTuple)
154154
text_color = attr.text_color
155155
markerspace = attr.markerspace
156156
valid_indices = attr.unclipped_indices
157+
glowwidth = attr.glowwidth
158+
glowcolor = attr.glowcolor
159+
glow_r, glow_g, glow_b, glow_a = rgbatuple(glowcolor)
157160
size_model = attr.size_model
158161
cam = (
159162
resolution = attr.resolution,
@@ -170,6 +173,36 @@ function draw_text(ctx, attr::NamedTuple)
170173
glyph_pos = positions[block_idx]
171174
local batch_font, batch_color, batch_mat, batch_strokewidth, batch_strokecolor
172175

176+
# Glow pass: build combined glyph path once, stroke with decreasing widths
177+
if glowwidth > 0 && glow_a > 0
178+
Cairo.save(ctx)
179+
for glyph_idx in glyph_indices
180+
glyph_idx in valid_indices || continue
181+
glyph = glyphindices[glyph_idx]
182+
glyph == 0 && continue
183+
gp3 = glyph_pos .+ size_model * marker_offset[glyph_idx]
184+
any(isnan, gp3) && continue
185+
scale = Makie.sv_getindex(text_scales, glyph_idx)
186+
rotation = Makie.sv_getindex(text_rotation, glyph_idx)
187+
pos, mat, _ = project_marker(cam, markerspace, Point3d(gp3), scale, rotation, size_model)
188+
cairoface = set_ft_font(ctx, font_per_char[glyph_idx])
189+
set_font_matrix(ctx, mat)
190+
glyph_path(ctx, glyph, pos...)
191+
cairo_font_face_destroy(cairoface)
192+
end
193+
n_layers = max(1, round(Int, glowwidth))
194+
Cairo.set_source_rgba(ctx, glow_r, glow_g, glow_b, glow_a / n_layers)
195+
Cairo.set_line_join(ctx, Cairo.CAIRO_LINE_JOIN_ROUND)
196+
Cairo.set_line_cap(ctx, Cairo.CAIRO_LINE_CAP_ROUND)
197+
for i in n_layers:-1:2
198+
Cairo.set_line_width(ctx, 2.0 * glowwidth * i / n_layers)
199+
Cairo.stroke_preserve(ctx)
200+
end
201+
Cairo.set_line_width(ctx, 2.0 * glowwidth / n_layers)
202+
Cairo.stroke(ctx)
203+
Cairo.restore(ctx)
204+
end
205+
173206
for glyph_idx in glyph_indices
174207
glyph_idx in valid_indices || continue
175208

0 commit comments

Comments
 (0)