@@ -250,14 +250,39 @@ end
250250
251251Base. show (io:: IO , line:: Line ) = print (io, Line, ' (' , length (line. glyphs), " glyphs, " , length (line. segments), " segments)" )
252252
253+ struct ParsedText
254+ lines:: Vector{Line}
255+ spacings:: Vector{Float64}
256+ geometry:: Optional{Box2}
257+ end
258+
259+ function ParsedText (text:: Text , fonts)
260+ lines = parse_lines (text, fonts)
261+ spacings = compute_line_spacings (lines, text. options)
262+ geometry = compute_text_geometry (text, lines, spacings)
263+ return ParsedText (lines, spacings, geometry)
264+ end
265+
266+ function compute_line_spacings (lines, options:: TextOptions )
267+ spacings = Float64[0.0 ]
268+ for i in eachindex (lines)[begin : (end - 1 )]
269+ prev = lines[i]
270+ next = lines[i + 1 ]
271+ height = ascender (next) - descender (prev)
272+ spacing = height * options. line_spacing
273+ push! (spacings, spacing)
274+ end
275+ return spacings
276+ end
277+
253278function segment_geometry (line:: Line , segment:: LineSegment )
254279 isempty (segment. indices) && return nothing
255280 ymin = descender (segment)
256281 ymax = ascender (segment)
257282 xmin, _ = line. positions[first (segment. indices)]
258283 width = sum (first, @view line. advances[segment. indices]; init = 0.0 )
259284 xmax = xmin + width
260- Box (Point2 (xmin, ymin), Point2 (xmax, ymax))
285+ return Box (Point2 (xmin, ymin), Point2 (xmax, ymax))
261286end
262287
263288function line_geometry (line:: Line )
@@ -267,7 +292,7 @@ function line_geometry(line::Line)
267292 ymax = ascender (line)
268293 width = sum (first, line. advances; init = 0.0 )
269294 xmax = xmin + width
270- Box (Point2 (xmin, ymin), Point2 (xmax, ymax))
295+ return Box (Point2 (xmin, ymin), Point2 (xmax, ymax))
271296end
272297
273298function has_outlines (line:: Line , segment:: LineSegment )
@@ -277,29 +302,28 @@ function has_outlines(line::Line, segment::LineSegment)
277302 outlines = line. outlines[glyph]
278303 ! isempty (outlines) && return true
279304 end
280- false
305+ return false
281306end
282307
283308ascender (line:: Line ) = maximum (ascender, line. segments; init = 0.0 )
284309descender (line:: Line ) = maximum (descender, line. segments; init = 0.0 )
285310
286- function split_lines (text:: Text )
311+ function split_text_into_lines (text:: Text )
287312 newlines = findall (== (' \n ' ), text. chars)
288313 push! (newlines, 1 + lastindex (text. chars))
289314 lines = SplitLine[]
290315 prev = 0
291316 for i in newlines
292317 range = (prev + 1 ): (i - 1 )
293318 prev = i
294- isempty (range) && continue
295319 push! (lines, SplitLine (text. chars[range], range. start, text. style_changes))
296320 end
297- lines
321+ return lines
298322end
299323
300- function lines (text:: Text , fonts:: AbstractVector{Pair{OpenTypeFont, FontOptions}} )
324+ function parse_lines (text:: Text , fonts:: AbstractVector{Pair{OpenTypeFont, FontOptions}} )
301325 lines = Line[]
302- for line in split_lines (text)
326+ for line in split_text_into_lines (text)
303327 glyph_indices = Dict {Pair{GlyphID, OpenTypeFont}, Int64} ()
304328 line_glyphs, line_positions, line_advances = GlyphID[], Vec2[], Vec2[]
305329 outlines = Vector{GlyphOutline}[]
@@ -327,7 +351,7 @@ function lines(text::Text, fonts::AbstractVector{Pair{OpenTypeFont, FontOptions}
327351 end
328352 push! (lines, Line (line_glyphs, line_positions, line_advances, segments, outlines))
329353 end
330- lines
354+ return lines
331355end
332356
333357function compute_positions (offsets, start, scale)
@@ -336,19 +360,15 @@ function compute_positions(offsets, start, scale)
336360 push! (positions, start .+ offset. origin .* scale)
337361 start = start .+ offset. advance .* scale
338362 end
339- positions
363+ return positions
340364end
341365
342- text_geometry (text:: Text , fonts) = text_geometry (text, lines (text, fonts))
343-
344- function text_geometry (text:: Text , lines:: AbstractVector{Line} )
366+ function compute_text_geometry (text:: Text , lines:: AbstractVector{Line} , spacings:: Vector{Float64} )
345367 result = nothing
346- for line in lines
368+ for ( line, spacing) in zip ( lines, spacings)
347369 geometry = line_geometry (line)
348- if ! isnothing (result)
349- geometry -= Vec2 (0.0 , text. options. line_spacing * result. height)
350- end
351- result = isnothing (result) ? geometry : boundingelement (result, geometry)
370+ geometry === nothing && continue
371+ result = result == nothing ? geometry : boundingelement (result, @set geometry -= Vec2 (0 , spacing))
352372 end
353- result
373+ return result
354374end
0 commit comments