FreeRDP
Loading...
Searching...
No Matches
glyph.c
1
20#include <freerdp/config.h>
21
22#include <stdio.h>
23
24#include <winpr/crt.h>
25#include <winpr/assert.h>
26#include <winpr/cast.h>
27
28#include <freerdp/freerdp.h>
29#include <winpr/stream.h>
30
31#include <freerdp/log.h>
32
33#include "glyph.h"
34#include "cache.h"
35
36#define TAG FREERDP_TAG("cache.glyph")
37
38static rdpGlyph* glyph_cache_get(rdpGlyphCache* glyphCache, UINT32 id, UINT32 index);
39static BOOL glyph_cache_put(rdpGlyphCache* glyphCache, UINT32 id, UINT32 index, rdpGlyph* glyph);
40
41static const void* glyph_cache_fragment_get(rdpGlyphCache* glyphCache, UINT32 index, UINT32* size);
42static BOOL glyph_cache_fragment_put(rdpGlyphCache* glyphCache, UINT32 index, UINT32 size,
43 const void* fragment);
44
45static UINT32 update_glyph_offset(const BYTE* data, size_t length, UINT32 index, INT32* x, INT32* y,
46 UINT32 ulCharInc, UINT32 flAccel)
47{
48 if ((ulCharInc == 0) && (!(flAccel & SO_CHAR_INC_EQUAL_BM_BASE)))
49 {
50 if (index >= length)
51 {
52 WLog_WARN(TAG, "glyph offset index out of bound %" PRIu32 " [max %" PRIuz "]", index,
53 length);
54 return index;
55 }
56
57 UINT32 offset = data[index++];
58
59 if (offset & 0x80)
60 {
61
62 if (index + 1 < length)
63 {
64 offset = data[index++];
65 offset |= ((UINT32)data[index++]) << 8;
66 }
67 else
68 WLog_WARN(TAG, "glyph index out of bound %" PRIu32 " [max %" PRIuz "]", index,
69 length);
70 }
71
72 if (flAccel & SO_VERTICAL)
73 *y += WINPR_ASSERTING_INT_CAST(int32_t, offset);
74
75 if (flAccel & SO_HORIZONTAL)
76 *x += WINPR_ASSERTING_INT_CAST(int32_t, offset);
77 }
78
79 return index;
80}
81
82static BOOL update_process_glyph(rdpContext* context, const BYTE* data, UINT32 cacheIndex, INT32* x,
83 const INT32* y, UINT32 cacheId, UINT32 flAccel, BOOL fOpRedundant,
84 const RDP_RECT* bound)
85{
86 INT32 sx = 0;
87 INT32 sy = 0;
88
89 if (!context || !data || !x || !y || !context->graphics || !context->cache ||
90 !context->cache->glyph)
91 return FALSE;
92
93 rdpGlyphCache* glyph_cache = context->cache->glyph;
94 rdpGlyph* glyph = glyph_cache_get(glyph_cache, cacheId, cacheIndex);
95
96 if (!glyph)
97 return FALSE;
98
99 INT32 dx = glyph->x + *x;
100 INT32 dy = glyph->y + *y;
101
102 if (dx < bound->x)
103 {
104 sx = bound->x - dx;
105 dx = bound->x;
106 }
107
108 if (dy < bound->y)
109 {
110 sy = bound->y - dy;
111 dy = bound->y;
112 }
113
114 if ((dx <= (bound->x + bound->width)) && (dy <= (bound->y + bound->height)))
115 {
116 INT32 dw = WINPR_ASSERTING_INT_CAST(int32_t, glyph->cx) - sx;
117 INT32 dh = WINPR_ASSERTING_INT_CAST(int32_t, glyph->cy) - sy;
118
119 if ((dw + dx) > (bound->x + bound->width))
120 dw = (bound->x + bound->width) - (dw + dx);
121
122 if ((dh + dy) > (bound->y + bound->height))
123 dh = (bound->y + bound->height) - (dh + dy);
124
125 if ((dh > 0) && (dw > 0))
126 {
127 if (!glyph->Draw(context, glyph, dx, dy, dw, dh, sx, sy, fOpRedundant))
128 return FALSE;
129 }
130 }
131
132 if (flAccel & SO_CHAR_INC_EQUAL_BM_BASE)
133 *x += WINPR_ASSERTING_INT_CAST(int32_t, glyph->cx);
134
135 return TRUE;
136}
137
138static BOOL update_process_glyph_fragments(rdpContext* context, const BYTE* data, UINT32 length,
139 UINT32 cacheId, UINT32 ulCharInc, UINT32 flAccel,
140 UINT32 bgcolor, UINT32 fgcolor, INT32 x, INT32 y,
141 INT32 bkX, INT32 bkY, INT32 bkWidth, INT32 bkHeight,
142 INT32 opX, INT32 opY, INT32 opWidth, INT32 opHeight,
143 BOOL fOpRedundant)
144{
145 UINT32 id = 0;
146 UINT32 size = 0;
147 UINT32 index = 0;
148 const BYTE* fragments = nullptr;
149 RDP_RECT bound = WINPR_C_ARRAY_INIT;
150 BOOL rc = FALSE;
151
152 if (!context || !data || !context->graphics || !context->cache || !context->cache->glyph)
153 return FALSE;
154
155 rdpGraphics* graphics = context->graphics;
156 WINPR_ASSERT(graphics);
157
158 WINPR_ASSERT(context->cache);
159 rdpGlyphCache* glyph_cache = context->cache->glyph;
160 WINPR_ASSERT(glyph_cache);
161
162 {
163 rdpGlyph* glyph = graphics->Glyph_Prototype;
164 if (!glyph)
165 goto fail;
166
167 /* Limit op rectangle to visible screen. */
168 if (opX < 0)
169 {
170 opWidth += opX;
171 opX = 0;
172 }
173
174 if (opY < 0)
175 {
176 opHeight += opY;
177 opY = 0;
178 }
179
180 if (opWidth < 0)
181 opWidth = 0;
182
183 if (opHeight < 0)
184 opHeight = 0;
185
186 /* Limit bk rectangle to visible screen. */
187 if (bkX < 0)
188 {
189 bkWidth += bkX;
190 bkX = 0;
191 }
192
193 if (bkY < 0)
194 {
195 bkHeight += bkY;
196 bkY = 0;
197 }
198
199 if (bkWidth < 0)
200 bkWidth = 0;
201
202 if (bkHeight < 0)
203 bkHeight = 0;
204
205 {
206 const UINT32 w = freerdp_settings_get_uint32(context->settings, FreeRDP_DesktopWidth);
207 if (opX + opWidth > (INT64)w)
208 {
218 opWidth = WINPR_ASSERTING_INT_CAST(int, w) - opX;
219 }
220
221 if (bkX + bkWidth > (INT64)w)
222 {
232 bkWidth = WINPR_ASSERTING_INT_CAST(int, w) - bkX;
233 }
234 }
235
236 bound.x = WINPR_ASSERTING_INT_CAST(INT16, bkX);
237 bound.y = WINPR_ASSERTING_INT_CAST(INT16, bkY);
238 bound.width = WINPR_ASSERTING_INT_CAST(INT16, bkWidth);
239 bound.height = WINPR_ASSERTING_INT_CAST(INT16, bkHeight);
240
241 if (!glyph->BeginDraw(context, opX, opY, opWidth, opHeight, bgcolor, fgcolor, fOpRedundant))
242 goto fail;
243
244 if (!IFCALLRESULT(TRUE, glyph->SetBounds, context, bkX, bkY, bkWidth, bkHeight))
245 goto fail;
246
247 while (index < length)
248 {
249 const UINT32 op = data[index++];
250
251 switch (op)
252 {
253 case GLYPH_FRAGMENT_USE:
254 if (index + 1 > length)
255 goto fail;
256
257 id = data[index++];
258 fragments = (const BYTE*)glyph_cache_fragment_get(glyph_cache, id, &size);
259
260 if (fragments == nullptr)
261 goto fail;
262
263 for (UINT32 n = 0; n < size;)
264 {
265 const UINT32 fop = fragments[n++];
266 n = update_glyph_offset(fragments, size, n, &x, &y, ulCharInc, flAccel);
267
268 if (!update_process_glyph(context, fragments, fop, &x, &y, cacheId, flAccel,
269 fOpRedundant, &bound))
270 goto fail;
271 }
272
273 break;
274
275 case GLYPH_FRAGMENT_ADD:
276 if (index + 2 > length)
277 goto fail;
278
279 id = data[index++];
280 size = data[index++];
281 glyph_cache_fragment_put(glyph_cache, id, size, data);
282 break;
283
284 default:
285 index = update_glyph_offset(data, length, index, &x, &y, ulCharInc, flAccel);
286
287 if (!update_process_glyph(context, data, op, &x, &y, cacheId, flAccel,
288 fOpRedundant, &bound))
289 goto fail;
290
291 break;
292 }
293 }
294
295 if (!glyph->EndDraw(context, opX, opY, opWidth, opHeight, bgcolor, fgcolor))
296 goto fail;
297 }
298
299 rc = TRUE;
300
301fail:
302 return rc;
303}
304
305static BOOL update_gdi_glyph_index(rdpContext* context, GLYPH_INDEX_ORDER* glyphIndex)
306{
307 INT32 bkWidth = 0;
308 INT32 bkHeight = 0;
309 INT32 opWidth = 0;
310 INT32 opHeight = 0;
311
312 if (!context || !glyphIndex || !context->cache)
313 return FALSE;
314
315 if (glyphIndex->bkRight > glyphIndex->bkLeft)
316 bkWidth = glyphIndex->bkRight - glyphIndex->bkLeft + 1;
317
318 if (glyphIndex->opRight > glyphIndex->opLeft)
319 opWidth = glyphIndex->opRight - glyphIndex->opLeft + 1;
320
321 if (glyphIndex->bkBottom > glyphIndex->bkTop)
322 bkHeight = glyphIndex->bkBottom - glyphIndex->bkTop + 1;
323
324 if (glyphIndex->opBottom > glyphIndex->opTop)
325 opHeight = glyphIndex->opBottom - glyphIndex->opTop + 1;
326
327 return update_process_glyph_fragments(
328 context, glyphIndex->data, glyphIndex->cbData, glyphIndex->cacheId, glyphIndex->ulCharInc,
329 glyphIndex->flAccel, glyphIndex->backColor, glyphIndex->foreColor, glyphIndex->x,
330 glyphIndex->y, glyphIndex->bkLeft, glyphIndex->bkTop, bkWidth, bkHeight, glyphIndex->opLeft,
331 glyphIndex->opTop, opWidth, opHeight,
332 WINPR_ASSERTING_INT_CAST(int32_t, glyphIndex->fOpRedundant));
333}
334
335static BOOL update_gdi_fast_index(rdpContext* context, const FAST_INDEX_ORDER* fastIndex)
336{
337 INT32 opWidth = 0;
338 INT32 opHeight = 0;
339 INT32 bkWidth = 0;
340 INT32 bkHeight = 0;
341 BOOL rc = FALSE;
342
343 if (!context || !fastIndex || !context->cache)
344 return FALSE;
345
346 INT32 opLeft = fastIndex->opLeft;
347 INT32 opTop = fastIndex->opTop;
348 INT32 opRight = fastIndex->opRight;
349 INT32 opBottom = fastIndex->opBottom;
350 INT32 x = fastIndex->x;
351 INT32 y = fastIndex->y;
352
353 if (opBottom == -32768)
354 {
355 BYTE flags = (BYTE)(opTop & 0x0F);
356
357 if (flags & 0x01)
358 opBottom = fastIndex->bkBottom;
359
360 if (flags & 0x02)
361 opRight = fastIndex->bkRight;
362
363 if (flags & 0x04)
364 opTop = fastIndex->bkTop;
365
366 if (flags & 0x08)
367 opLeft = fastIndex->bkLeft;
368 }
369
370 if (opLeft == 0)
371 opLeft = fastIndex->bkLeft;
372
373 if (opRight == 0)
374 opRight = fastIndex->bkRight;
375
376 /* Server can send a massive number (32766) which appears to be
377 * undocumented special behavior for "Erase all the way right".
378 * X11 has nondeterministic results asking for a draw that wide. */
379 if (opRight > (INT64)freerdp_settings_get_uint32(context->settings, FreeRDP_DesktopWidth))
380 opRight = (int)freerdp_settings_get_uint32(context->settings, FreeRDP_DesktopWidth);
381
382 if (x == -32768)
383 x = fastIndex->bkLeft;
384
385 if (y == -32768)
386 y = fastIndex->bkTop;
387
388 if (fastIndex->bkRight > fastIndex->bkLeft)
389 bkWidth = fastIndex->bkRight - fastIndex->bkLeft + 1;
390
391 if (fastIndex->bkBottom > fastIndex->bkTop)
392 bkHeight = fastIndex->bkBottom - fastIndex->bkTop + 1;
393
394 if (opRight > opLeft)
395 opWidth = opRight - opLeft + 1;
396
397 if (opBottom > opTop)
398 opHeight = opBottom - opTop + 1;
399
400 if (!update_process_glyph_fragments(
401 context, fastIndex->data, fastIndex->cbData, fastIndex->cacheId, fastIndex->ulCharInc,
402 fastIndex->flAccel, fastIndex->backColor, fastIndex->foreColor, x, y, fastIndex->bkLeft,
403 fastIndex->bkTop, bkWidth, bkHeight, opLeft, opTop, opWidth, opHeight, FALSE))
404 goto fail;
405
406 rc = TRUE;
407fail:
408 return rc;
409}
410
411static BOOL update_gdi_fast_glyph(rdpContext* context, const FAST_GLYPH_ORDER* fastGlyph)
412{
413 INT32 x = 0;
414 INT32 y = 0;
415 BYTE text_data[4] = WINPR_C_ARRAY_INIT;
416 INT32 opLeft = 0;
417 INT32 opTop = 0;
418 INT32 opRight = 0;
419 INT32 opBottom = 0;
420 INT32 opWidth = 0;
421 INT32 opHeight = 0;
422 INT32 bkWidth = 0;
423 INT32 bkHeight = 0;
424 rdpCache* cache = nullptr;
425
426 if (!context || !fastGlyph || !context->cache)
427 return FALSE;
428
429 cache = context->cache;
430 opLeft = fastGlyph->opLeft;
431 opTop = fastGlyph->opTop;
432 opRight = fastGlyph->opRight;
433 opBottom = fastGlyph->opBottom;
434 x = fastGlyph->x;
435 y = fastGlyph->y;
436
437 if (opBottom == -32768)
438 {
439 BYTE flags = (BYTE)(opTop & 0x0F);
440
441 if (flags & 0x01)
442 opBottom = fastGlyph->bkBottom;
443
444 if (flags & 0x02)
445 opRight = fastGlyph->bkRight;
446
447 if (flags & 0x04)
448 opTop = fastGlyph->bkTop;
449
450 if (flags & 0x08)
451 opLeft = fastGlyph->bkLeft;
452 }
453
454 if (opLeft == 0)
455 opLeft = fastGlyph->bkLeft;
456
457 if (opRight == 0)
458 opRight = fastGlyph->bkRight;
459
460 /* See update_gdi_fast_index opRight comment. */
461 if (opRight > (INT64)freerdp_settings_get_uint32(context->settings, FreeRDP_DesktopWidth))
462 opRight = (int)freerdp_settings_get_uint32(context->settings, FreeRDP_DesktopWidth);
463
464 if (x == -32768)
465 x = fastGlyph->bkLeft;
466
467 if (y == -32768)
468 y = fastGlyph->bkTop;
469
470 if ((fastGlyph->cbData > 1) && (fastGlyph->glyphData.aj))
471 {
472 /* got option font that needs to go into cache */
473 rdpGlyph* glyph = nullptr;
474 const GLYPH_DATA_V2* glyphData = &fastGlyph->glyphData;
475
476 glyph = Glyph_Alloc(context, glyphData->x, glyphData->y, glyphData->cx, glyphData->cy,
477 glyphData->cb, glyphData->aj);
478
479 if (!glyph)
480 return FALSE;
481
482 if (!glyph_cache_put(cache->glyph, fastGlyph->cacheId, fastGlyph->data[0], glyph))
483 {
484 glyph->Free(context, glyph);
485 return FALSE;
486 }
487 }
488
489 text_data[0] = fastGlyph->data[0];
490 text_data[1] = 0;
491
492 if (fastGlyph->bkRight > fastGlyph->bkLeft)
493 bkWidth = fastGlyph->bkRight - fastGlyph->bkLeft + 1;
494
495 if (fastGlyph->bkBottom > fastGlyph->bkTop)
496 bkHeight = fastGlyph->bkBottom - fastGlyph->bkTop + 1;
497
498 if (opRight > opLeft)
499 opWidth = opRight - opLeft + 1;
500
501 if (opBottom > opTop)
502 opHeight = opBottom - opTop + 1;
503
504 return update_process_glyph_fragments(
505 context, text_data, sizeof(text_data), fastGlyph->cacheId, fastGlyph->ulCharInc,
506 fastGlyph->flAccel, fastGlyph->backColor, fastGlyph->foreColor, x, y, fastGlyph->bkLeft,
507 fastGlyph->bkTop, bkWidth, bkHeight, opLeft, opTop, opWidth, opHeight, FALSE);
508}
509
510static BOOL update_gdi_cache_glyph(rdpContext* context, const CACHE_GLYPH_ORDER* cacheGlyph)
511{
512 if (!context || !cacheGlyph || !context->cache)
513 return FALSE;
514
515 rdpCache* cache = context->cache;
516
517 for (size_t i = 0; i < cacheGlyph->cGlyphs; i++)
518 {
519 const GLYPH_DATA* glyph_data = &cacheGlyph->glyphData[i];
520 rdpGlyph* glyph = Glyph_Alloc(context, glyph_data->x, glyph_data->y, glyph_data->cx,
521 glyph_data->cy, glyph_data->cb, glyph_data->aj);
522 if (!glyph)
523 return FALSE;
524
525 if (!glyph_cache_put(cache->glyph, cacheGlyph->cacheId, glyph_data->cacheIndex, glyph))
526 {
527 glyph->Free(context, glyph);
528 return FALSE;
529 }
530 }
531
532 return TRUE;
533}
534
535static BOOL update_gdi_cache_glyph_v2(rdpContext* context, const CACHE_GLYPH_V2_ORDER* cacheGlyphV2)
536{
537 if (!context || !cacheGlyphV2 || !context->cache)
538 return FALSE;
539
540 rdpCache* cache = context->cache;
541
542 for (size_t i = 0; i < cacheGlyphV2->cGlyphs; i++)
543 {
544 const GLYPH_DATA_V2* glyphData = &cacheGlyphV2->glyphData[i];
545 rdpGlyph* glyph = Glyph_Alloc(context, glyphData->x, glyphData->y, glyphData->cx,
546 glyphData->cy, glyphData->cb, glyphData->aj);
547
548 if (!glyph)
549 return FALSE;
550
551 if (!glyph_cache_put(cache->glyph, cacheGlyphV2->cacheId, glyphData->cacheIndex, glyph))
552 {
553 glyph->Free(context, glyph);
554 return FALSE;
555 }
556 }
557
558 return TRUE;
559}
560
561rdpGlyph* glyph_cache_get(rdpGlyphCache* glyphCache, UINT32 id, UINT32 index)
562{
563 WINPR_ASSERT(glyphCache);
564
565 WLog_Print(glyphCache->log, WLOG_DEBUG, "GlyphCacheGet: id: %" PRIu32 " index: %" PRIu32 "", id,
566 index);
567
568 if (id >= ARRAYSIZE(glyphCache->glyphCache))
569 {
570 WLog_ERR(TAG, "invalid glyph cache id: %" PRIu32 "", id);
571 return nullptr;
572 }
573
574 GLYPH_CACHE* cache = &glyphCache->glyphCache[id];
575 if (index >= cache->number)
576 {
577 WLog_ERR(TAG, "index %" PRIu32 " out of range for cache id: %" PRIu32 "", index, id);
578 return nullptr;
579 }
580
581 rdpGlyph* glyph = cache->entries[index];
582 if (!glyph)
583 WLog_ERR(TAG, "no glyph found at cache index: %" PRIu32 " in cache id: %" PRIu32 "", index,
584 id);
585
586 return glyph;
587}
588
589BOOL glyph_cache_put(rdpGlyphCache* glyphCache, UINT32 id, UINT32 index, rdpGlyph* glyph)
590{
591 WINPR_ASSERT(glyphCache);
592
593 if (id >= ARRAYSIZE(glyphCache->glyphCache))
594 {
595 WLog_ERR(TAG, "invalid glyph cache id: %" PRIu32 "", id);
596 return FALSE;
597 }
598
599 GLYPH_CACHE* cache = &glyphCache->glyphCache[id];
600 if (index >= cache->number)
601 {
602 WLog_ERR(TAG, "invalid glyph cache index: %" PRIu32 " in cache id: %" PRIu32 "", index, id);
603 return FALSE;
604 }
605
606 WLog_Print(glyphCache->log, WLOG_DEBUG, "GlyphCachePut: id: %" PRIu32 " index: %" PRIu32 "", id,
607 index);
608 rdpGlyph* prevGlyph = cache->entries[index];
609
610 if (prevGlyph)
611 {
612 WINPR_ASSERT(prevGlyph->Free);
613 prevGlyph->Free(glyphCache->context, prevGlyph);
614 }
615
616 cache->entries[index] = glyph;
617 return TRUE;
618}
619
620const void* glyph_cache_fragment_get(rdpGlyphCache* glyphCache, UINT32 index, UINT32* size)
621{
622 void* fragment = nullptr;
623
624 WINPR_ASSERT(glyphCache);
625 WINPR_ASSERT(glyphCache->fragCache.entries);
626
627 if (index > 255)
628 {
629 WLog_ERR(TAG, "invalid glyph cache fragment index: %" PRIu32 "", index);
630 return nullptr;
631 }
632
633 fragment = glyphCache->fragCache.entries[index].fragment;
634 *size = (BYTE)glyphCache->fragCache.entries[index].size;
635 WLog_Print(glyphCache->log, WLOG_DEBUG,
636 "GlyphCacheFragmentGet: index: %" PRIu32 " size: %" PRIu32 "", index, *size);
637
638 if (!fragment)
639 WLog_ERR(TAG, "invalid glyph fragment at index:%" PRIu32 "", index);
640
641 return fragment;
642}
643
644BOOL glyph_cache_fragment_put(rdpGlyphCache* glyphCache, UINT32 index, UINT32 size,
645 const void* fragment)
646{
647 WINPR_ASSERT(glyphCache);
648 WINPR_ASSERT(glyphCache->fragCache.entries);
649
650 if (index > 255)
651 {
652 WLog_ERR(TAG, "invalid glyph cache fragment index: %" PRIu32 "", index);
653 return FALSE;
654 }
655
656 if (size == 0)
657 return FALSE;
658
659 void* copy = malloc(size);
660
661 if (!copy)
662 return FALSE;
663
664 WLog_Print(glyphCache->log, WLOG_DEBUG,
665 "GlyphCacheFragmentPut: index: %" PRIu32 " size: %" PRIu32 "", index, size);
666 CopyMemory(copy, fragment, size);
667
668 void* prevFragment = glyphCache->fragCache.entries[index].fragment;
669 glyphCache->fragCache.entries[index].fragment = copy;
670 glyphCache->fragCache.entries[index].size = size;
671 free(prevFragment);
672 return TRUE;
673}
674
675void glyph_cache_register_callbacks(rdpUpdate* update)
676{
677 WINPR_ASSERT(update);
678 WINPR_ASSERT(update->context);
679 WINPR_ASSERT(update->primary);
680 WINPR_ASSERT(update->secondary);
681
682 if (!freerdp_settings_get_bool(update->context->settings, FreeRDP_DeactivateClientDecoding))
683 {
684 update->primary->GlyphIndex = update_gdi_glyph_index;
685 update->primary->FastIndex = update_gdi_fast_index;
686 update->primary->FastGlyph = update_gdi_fast_glyph;
687 update->secondary->CacheGlyph = update_gdi_cache_glyph;
688 update->secondary->CacheGlyphV2 = update_gdi_cache_glyph_v2;
689 }
690}
691
692rdpGlyphCache* glyph_cache_new(rdpContext* context)
693{
694 rdpGlyphCache* glyphCache = nullptr;
695 rdpSettings* settings = nullptr;
696
697 WINPR_ASSERT(context);
698
699 settings = context->settings;
700 WINPR_ASSERT(settings);
701
702 glyphCache = (rdpGlyphCache*)calloc(1, sizeof(rdpGlyphCache));
703
704 if (!glyphCache)
705 return nullptr;
706
707 glyphCache->log = WLog_Get("com.freerdp.cache.glyph");
708 glyphCache->context = context;
709
710 for (size_t i = 0; i < 10; i++)
711 {
712 const GLYPH_CACHE_DEFINITION* currentGlyph =
713 freerdp_settings_get_pointer_array(settings, FreeRDP_GlyphCache, i);
714 GLYPH_CACHE* currentCache = &glyphCache->glyphCache[i];
715 currentCache->number = currentGlyph->cacheEntries;
716 currentCache->maxCellSize = currentGlyph->cacheMaximumCellSize;
717 currentCache->entries = (rdpGlyph**)calloc(currentCache->number, sizeof(rdpGlyph*));
718
719 if (!currentCache->entries)
720 goto fail;
721 }
722
723 return glyphCache;
724fail:
725 WINPR_PRAGMA_DIAG_PUSH
726 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
727 glyph_cache_free(glyphCache);
728 WINPR_PRAGMA_DIAG_POP
729 return nullptr;
730}
731
732void glyph_cache_free(rdpGlyphCache* glyphCache)
733{
734 if (glyphCache)
735 {
736 GLYPH_CACHE* cache = glyphCache->glyphCache;
737
738 for (size_t i = 0; i < 10; i++)
739 {
740 rdpGlyph** entries = cache[i].entries;
741
742 if (!entries)
743 continue;
744
745 for (size_t j = 0; j < cache[i].number; j++)
746 {
747 rdpGlyph* glyph = entries[j];
748
749 if (glyph)
750 {
751 glyph->Free(glyphCache->context, glyph);
752 entries[j] = nullptr;
753 }
754 }
755
756 free((void*)entries);
757 cache[i].entries = nullptr;
758 }
759
760 for (size_t i = 0; i < ARRAYSIZE(glyphCache->fragCache.entries); i++)
761 {
762 free(glyphCache->fragCache.entries[i].fragment);
763 glyphCache->fragCache.entries[i].fragment = nullptr;
764 }
765
766 free(glyphCache);
767 }
768}
769
770CACHE_GLYPH_ORDER* copy_cache_glyph_order(rdpContext* context, const CACHE_GLYPH_ORDER* glyph)
771{
772 CACHE_GLYPH_ORDER* dst = nullptr;
773
774 WINPR_ASSERT(context);
775
776 dst = calloc(1, sizeof(CACHE_GLYPH_ORDER));
777
778 if (!dst || !glyph)
779 goto fail;
780
781 *dst = *glyph;
782
783 for (size_t x = 0; x < glyph->cGlyphs; x++)
784 {
785 const GLYPH_DATA* src = &glyph->glyphData[x];
786 GLYPH_DATA* data = &dst->glyphData[x];
787
788 if (src->aj)
789 {
790 const size_t size = src->cb;
791 data->aj = malloc(size);
792
793 if (!data->aj)
794 goto fail;
795
796 memcpy(data->aj, src->aj, size);
797 }
798 }
799
800 if (glyph->unicodeCharacters)
801 {
802 if (glyph->cGlyphs == 0)
803 goto fail;
804
805 dst->unicodeCharacters = calloc(glyph->cGlyphs, sizeof(WCHAR));
806
807 if (!dst->unicodeCharacters)
808 goto fail;
809
810 memcpy(dst->unicodeCharacters, glyph->unicodeCharacters, sizeof(WCHAR) * glyph->cGlyphs);
811 }
812
813 return dst;
814fail:
815 free_cache_glyph_order(context, dst);
816 return nullptr;
817}
818
819void free_cache_glyph_order(WINPR_ATTR_UNUSED rdpContext* context, CACHE_GLYPH_ORDER* glyph)
820{
821 if (glyph)
822 {
823 for (size_t x = 0; x < ARRAYSIZE(glyph->glyphData); x++)
824 free(glyph->glyphData[x].aj);
825
826 free(glyph->unicodeCharacters);
827 }
828
829 free(glyph);
830}
831
832CACHE_GLYPH_V2_ORDER* copy_cache_glyph_v2_order(rdpContext* context,
833 const CACHE_GLYPH_V2_ORDER* glyph)
834{
835 CACHE_GLYPH_V2_ORDER* dst = nullptr;
836
837 WINPR_ASSERT(context);
838
839 dst = calloc(1, sizeof(CACHE_GLYPH_V2_ORDER));
840
841 if (!dst || !glyph)
842 goto fail;
843
844 *dst = *glyph;
845
846 for (size_t x = 0; x < glyph->cGlyphs; x++)
847 {
848 const GLYPH_DATA_V2* src = &glyph->glyphData[x];
849 GLYPH_DATA_V2* data = &dst->glyphData[x];
850
851 if (src->aj)
852 {
853 const size_t size = src->cb;
854 data->aj = malloc(size);
855
856 if (!data->aj)
857 goto fail;
858
859 memcpy(data->aj, src->aj, size);
860 }
861 }
862
863 if (glyph->unicodeCharacters)
864 {
865 if (glyph->cGlyphs == 0)
866 goto fail;
867
868 dst->unicodeCharacters = calloc(glyph->cGlyphs, sizeof(WCHAR));
869
870 if (!dst->unicodeCharacters)
871 goto fail;
872
873 memcpy(dst->unicodeCharacters, glyph->unicodeCharacters, sizeof(WCHAR) * glyph->cGlyphs);
874 }
875
876 return dst;
877fail:
878 free_cache_glyph_v2_order(context, dst);
879 return nullptr;
880}
881
882void free_cache_glyph_v2_order(WINPR_ATTR_UNUSED rdpContext* context, CACHE_GLYPH_V2_ORDER* glyph)
883{
884 if (glyph)
885 {
886 for (size_t x = 0; x < ARRAYSIZE(glyph->glyphData); x++)
887 free(glyph->glyphData[x].aj);
888
889 free(glyph->unicodeCharacters);
890 }
891
892 free(glyph);
893}
WINPR_ATTR_NODISCARD FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.