| 290 | } |
| 291 | |
| 292 | static std::vector<std::vector<GlyphInfo*>> ApplyLayoutToGlyphInfos( |
| 293 | const TextLayout& layout, std::vector<GlyphInfo>* glyphInfos, tgfx::Rect* bounds, |
| 294 | float* firstLineMiniAscent) { |
| 295 | float maxWidth, maxY; |
| 296 | if (layout.boxRect.isEmpty()) { |
| 297 | maxWidth = std::numeric_limits<float>::infinity(); |
| 298 | maxY = std::numeric_limits<float>::infinity(); |
| 299 | } else { |
| 300 | maxWidth = layout.boxRect.width(); |
| 301 | maxY = layout.boxRect.bottom; |
| 302 | } |
| 303 | |
| 304 | std::vector<std::vector<GlyphInfo*>> lineList = {}; |
| 305 | auto glyphCount = glyphInfos->size(); |
| 306 | size_t index = 0; |
| 307 | int lineIndex = 0; |
| 308 | auto baseLine = layout.firstBaseLine; |
| 309 | while (index < glyphCount) { |
| 310 | if (baseLine > maxY) { |
| 311 | break; |
| 312 | } |
| 313 | auto lineGlyphStart = index; |
| 314 | auto lineWidth = 0.0f; |
| 315 | auto nextLineIndex = |
| 316 | CalculateNextLineIndex(*glyphInfos, index, 1.0f, maxWidth, layout.tracking, &lineWidth); |
| 317 | auto hasLineBreaker = (*glyphInfos)[nextLineIndex - 1].name[0] == '\n'; // 换行符 |
| 318 | auto lineGlyphEnd = nextLineIndex - (hasLineBreaker ? 1 : 0); |
| 319 | index = nextLineIndex; |
| 320 | bool isLastLine = (index == glyphCount); |
| 321 | auto drawX = CalculateDrawX(layout.justification, lineWidth, isLastLine || hasLineBreaker, |
| 322 | layout.boxRect); |
| 323 | auto drawY = baseLine - layout.baselineShift; |
| 324 | float letterSpacing = CalculateLetterSpacing(layout.justification, layout.tracking, lineWidth, |
| 325 | lineGlyphEnd - lineGlyphStart, |
| 326 | isLastLine || hasLineBreaker, layout.boxRect); |
| 327 | std::vector<GlyphInfo*> glyphLine = {}; |
| 328 | for (size_t i = lineGlyphStart; i < lineGlyphEnd; i++) { |
| 329 | auto& glyph = (*glyphInfos)[i]; |
| 330 | glyph.position.x = drawX; |
| 331 | glyph.position.y = drawY; |
| 332 | glyph.bounds.offset(drawX, drawY); |
| 333 | glyphLine.push_back(&glyph); |
| 334 | bounds->join(glyph.bounds); |
| 335 | drawX += glyph.advance + letterSpacing; |
| 336 | } |
| 337 | if (!glyphLine.empty()) { |
| 338 | lineList.push_back(glyphLine); |
| 339 | } else { |
| 340 | auto emptyLineBounds = tgfx::Rect::MakeLTRB( |
| 341 | drawX, drawY + layout.fontTop, drawX + EMPTY_LINE_WIDTH, drawY + layout.fontBottom); |
| 342 | bounds->join(emptyLineBounds); |
| 343 | } |
| 344 | |
| 345 | if (firstLineMiniAscent && lineIndex == 0) { |
| 346 | *firstLineMiniAscent = glyphLine.empty() ? layout.fontTop : FindMiniAscent(glyphLine); |
| 347 | } |
| 348 | |
| 349 | baseLine += layout.lineGap; |
no test coverage detected