@@ -147,7 +147,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
147
147
{
148
148
LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
149
149
150
- if (!sDisplayFont ) // do not display texts
150
+ if (!sDisplayFont ) // do not display texts
151
151
{
152
152
return static_cast <S32>(wstr.length ());
153
153
}
@@ -181,23 +181,27 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
181
181
182
182
gGL .loadUIIdentity ();
183
183
184
- LLVector2 origin (floorf (sCurOrigin .mX * sScaleX ), floorf (sCurOrigin .mY * sScaleY ));
184
+ LLVector2 origin (floorf (sCurOrigin .mX * sScaleX ), floorf (sCurOrigin .mY * sScaleY ));
185
185
186
186
// Depth translation, so that floating text appears 'in-world'
187
187
// and is correctly occluded.
188
- gGL .translatef (0 .f ,0 .f ,sCurDepth );
188
+ gGL .translatef (0 .f , 0 .f , sCurDepth );
189
189
190
190
S32 chars_drawn = 0 ;
191
- S32 i;
192
- S32 length;
191
+ S32 length = (S32)wstr.length () - begin_offset;
193
192
194
- if (- 1 == max_chars )
193
+ if (max_chars < 0 )
195
194
{
196
- max_chars = length = (S32)wstr. length () - begin_offset ;
195
+ max_chars = length;
197
196
}
198
- else
197
+ else if (max_chars < length)
199
198
{
200
- length = llmin ((S32)wstr.length () - begin_offset, max_chars );
199
+ length = max_chars;
200
+ }
201
+
202
+ if (length < 1 )
203
+ {
204
+ return 0 ;
201
205
}
202
206
203
207
F32 cur_x, cur_y, cur_render_x, cur_render_y;
@@ -270,7 +274,9 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
270
274
271
275
const LLFontGlyphInfo* next_glyph = NULL ;
272
276
277
+ // Maximum number of queued glyphs
273
278
static constexpr U32 GLYPH_BATCH_SIZE = 30 ;
279
+ // Each glyph uses 2 triangles == 6 vertices/uvs/colors
274
280
static thread_local LLVector4a vertices[GLYPH_BATCH_SIZE * 6 ];
275
281
static thread_local LLVector2 uvs[GLYPH_BATCH_SIZE * 6 ];
276
282
static thread_local LLColor4U colors[GLYPH_BATCH_SIZE * 6 ];
@@ -280,11 +286,10 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
280
286
// for the chat console)... HB
281
287
LLColor4U emoji_color (255 , 255 , 255 , text_color.mV [VALPHA]);
282
288
283
- std::pair<EFontGlyphType, S32> bitmap_entry = std::make_pair (EFontGlyphType::Grayscale, -1 );
284
289
U32 glyph_count = 0 ;
285
- auto draw_queued_glyphs = [&]()
290
+ auto render_queued_glyphs = [&](U32 max_glyph_count = 0 )
286
291
{
287
- if (glyph_count)
292
+ if (glyph_count > max_glyph_count )
288
293
{
289
294
gGL .begin (LLRender::TRIANGLES);
290
295
{
@@ -295,30 +300,33 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
295
300
}
296
301
};
297
302
298
- for (i = begin_offset; i < begin_offset + length; i++)
303
+ llwchar last_wch = 0 ;
304
+ U32 glyph_per_char = 0 ; // This value can be 1, 2 or 6 depending on shadow
305
+ // It will be set after the first call of drawGlyph
306
+ for (S32 i = 0 ; i < length; i++)
299
307
{
300
- llwchar wch = wstr[i];
308
+ llwchar wch = wstr[begin_offset + i];
301
309
302
310
const LLFontGlyphInfo* fgi = next_glyph;
303
311
next_glyph = NULL ;
304
312
if (!fgi)
305
313
{
306
- fgi = mFontFreetype ->getGlyphInfo (wch, (! use_color) ? EFontGlyphType::Grayscale : EFontGlyphType::Color );
314
+ fgi = mFontFreetype ->getGlyphInfo (wch, use_color ? EFontGlyphType::Color : EFontGlyphType::Grayscale );
307
315
}
308
316
if (!fgi)
309
317
{
310
318
LL_ERRS () << " Missing Glyph Info" << LL_ENDL;
311
319
break ;
312
320
}
321
+
313
322
// Per-glyph bitmap texture.
314
- std::pair<EFontGlyphType, S32> next_bitmap_entry = fgi->mBitmapEntry ;
315
- if (next_bitmap_entry != bitmap_entry )
323
+ const std::pair<EFontGlyphType, S32>& bitmap_entry = fgi->mBitmapEntry ;
324
+ if (wch != last_wch || i == 0 )
316
325
{
317
326
// Actually draw the queued glyphs before switching their texture;
318
327
// otherwise the queued glyphs will be taken from wrong textures.
319
- draw_queued_glyphs ();
328
+ render_queued_glyphs ();
320
329
321
- bitmap_entry = next_bitmap_entry;
322
330
LLImageGL* font_image = font_bitmap_cache->getImageGL (bitmap_entry.first , bitmap_entry.second );
323
331
gGL .getTexUnit (0 )->bind (font_image);
324
332
}
@@ -341,24 +349,35 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
341
349
(F32)ll_round (cur_render_x + (F32)fgi->mXBearing ) + (F32)fgi->mWidth ,
342
350
(F32)ll_round (cur_render_y + (F32)fgi->mYBearing ) - (F32)fgi->mHeight );
343
351
344
- draw_queued_glyphs ();
352
+ // Prevent the buffer overflow
353
+ render_queued_glyphs (GLYPH_BATCH_SIZE - glyph_per_char);
345
354
346
355
const LLColor4U& col =
347
356
bitmap_entry.first == EFontGlyphType::Grayscale ? text_color
348
357
: emoji_color;
358
+ // This function emplaces data to arrays vertices, uvs, colors
359
+ // and increases glyph_count on 1, 2 or 6 depending on shadow
349
360
drawGlyph (glyph_count, vertices, uvs, colors, screen_rect, uv_rect,
350
361
col, style_to_add, shadow, drop_shadow_strength);
362
+ llassert (glyph_count <= GLYPH_BATCH_SIZE);
363
+ if (!glyph_per_char)
364
+ {
365
+ glyph_per_char = glyph_count;
366
+ }
351
367
352
368
chars_drawn++;
353
369
cur_x += fgi->mXAdvance ;
354
370
cur_y += fgi->mYAdvance ;
355
371
356
- llwchar next_char = wstr[i+1 ];
357
- if (next_char && (next_char < LAST_CHARACTER))
372
+ if (i + 1 < length)
358
373
{
359
- // Kern this puppy.
360
- next_glyph = mFontFreetype ->getGlyphInfo (next_char, (!use_color) ? EFontGlyphType::Grayscale : EFontGlyphType::Color);
361
- cur_x += mFontFreetype ->getXKerning (fgi, next_glyph);
374
+ llwchar next_char = wstr[begin_offset + i + 1 ];
375
+ if (next_char && (next_char < LAST_CHARACTER))
376
+ {
377
+ // Kern this puppy.
378
+ next_glyph = mFontFreetype ->getGlyphInfo (next_char, use_color ? EFontGlyphType::Color : EFontGlyphType::Grayscale);
379
+ cur_x += mFontFreetype ->getXKerning (fgi, next_glyph);
380
+ }
362
381
}
363
382
364
383
// Round after kerning.
@@ -372,7 +391,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
372
391
cur_render_y = cur_y;
373
392
}
374
393
375
- draw_queued_glyphs ();
394
+ render_queued_glyphs ();
376
395
377
396
if (right_x)
378
397
{
0 commit comments