Skip to content

Commit

Permalink
Apply font size value per segment
Browse files Browse the repository at this point in the history
  • Loading branch information
serenity4 committed Aug 25, 2024
1 parent 429a81d commit cf82986
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 16 deletions.
25 changes: 17 additions & 8 deletions src/text.jl
Original file line number Diff line number Diff line change
Expand Up @@ -200,11 +200,18 @@ struct GlyphStyle
color::Optional{RGBA{Float32}}
underline::Bool
strikethrough::Bool
size::Float64
end

GlyphStyle(style::CharacterStyle) = GlyphStyle(style.color, style.underline, style.strikethrough)
GlyphStyle(style::CharacterStyle, size = 0.0) = GlyphStyle(style.color, style.underline, style.strikethrough, size)
function GlyphStyle(run::TextRun)
style = GlyphStyle(run.style)
@set style.size = glyph_size(run)
end
GlyphStyle() = GlyphStyle(CharacterStyle())

glyph_size(run::TextRun) = something(run.style.size, run.options.font_size.value) / run.font.units_per_em

struct LineSegment
indices::UnitRange{Int64}
font::OpenTypeFont
Expand Down Expand Up @@ -254,18 +261,19 @@ function lines(text::Text, fonts::AbstractVector{Pair{OpenTypeFont, FontOptions}
outlines = Vector{GlyphOutline}[]
segments = LineSegment[]
runs = compute_runs(line, fonts)
last_advance = nothing
for run in runs
glyphs, offsets = shape(run.font, line.chars, run.options.shaping_options)
push!(segments, LineSegment(run.range, run.font, run.options, GlyphStyle(run.style)))
start = isempty(line_positions) ? zero(Point2) : line_positions[end]
scale = run.options.font_size.value::Float64 / run.font.units_per_em
append!(line_positions, compute_positions(offsets, start, scale))
glyphs, offsets = shape(run.font, @view(line.chars[run.range]), run.options.shaping_options)
segment = LineSegment(run.range, run.font, run.options, GlyphStyle(run))
push!(segments, segment)
start = isempty(line_positions) ? zero(Point2) : line_positions[end] .+ last_advance
append!(line_positions, compute_positions(offsets, start, segment.style.size))
last_advance = offsets[end].advance .* segment.style.size
for glyph in glyphs
i = get!(glyph_indices, glyph => run.font) do
g = run.font[glyph]
isnothing(g) && return 0
geometry = curves(g)
geometry .*= scale
push!(outlines, geometry)
lastindex(outlines)
end
Expand All @@ -288,11 +296,12 @@ end

function boundingelement(line::Line, segment::LineSegment)
res = nothing
(; size) = segment.style
for i in segment.indices
glyph = line.glyphs[i]
iszero(glyph) && continue
position = line.positions[i]
outlines = line.outlines[glyph]
outlines = line.outlines[glyph] .* size
geometry = boundingelement(outlines) + position
res = isnothing(res) ? geometry : boundingelement(res, geometry)
end
Expand Down
28 changes: 20 additions & 8 deletions test/text.jl
Original file line number Diff line number Diff line change
Expand Up @@ -84,15 +84,27 @@
line = only(lines(t, [font => options]))
@test length(line.segments) == 8
a, b, c, d, e, f, g, h = line.segments
@test a.style == GlyphStyle()
test_style_equals(x, y) = for prop in fieldnames(GlyphStyle); prop :size && @test getproperty(x, prop) == getproperty(y, prop); end
test_style_equals(a.style, GlyphStyle())
# TODO: Add weight to `GlyphStyle`.
@test b.style == GlyphStyle(nothing, false, false)
@test c.style == GlyphStyle()
@test d.style == GlyphStyle(RGBA(1f0, 0f0, 0f0, 1f0), false, false)
test_style_equals(b.style, GlyphStyle(nothing, false, false, 0.0))
test_style_equals(c.style, GlyphStyle())
test_style_equals(d.style, GlyphStyle(RGBA(1f0, 0f0, 0f0, 1f0), false, false, 0.0))
# TODO: Add slant to `GlyphStyle`.
@test e.style == GlyphStyle(RGBA(1f0, 0f0, 0f0, 1f0), false, false)
@test f.style == GlyphStyle()
test_style_equals(e.style, GlyphStyle(RGBA(1f0, 0f0, 0f0, 1f0), false, false, 0.0))
test_style_equals(f.style, GlyphStyle())
# TODO: Add slant to `GlyphStyle`.
@test g.style == GlyphStyle(nothing, false, false)
@test h.style == GlyphStyle()
test_style_equals(g.style, GlyphStyle(nothing, false, false, 0.0))
test_style_equals(h.style, GlyphStyle())

file = google_font_files["spacemono"][1]
font = OpenTypeFont(file);
t = Text(styled"{size=20:Some{size=100: big }text.}", TextOptions())
line = only(lines(t, [font => options]))
@test length(line.segments) == 3
a, b, c = line.segments
@test a.style.size === c.style.size
small = a.style.size
large = b.style.size
@test large 5small
end;

0 comments on commit cf82986

Please sign in to comment.