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 if (size > length - index)
282 goto fail;
283 glyph_cache_fragment_put(glyph_cache, id, size, data);
284 break;
285
286 default:
287 index = update_glyph_offset(data, length, index, &x, &y, ulCharInc, flAccel);
288
289 if (!update_process_glyph(context, data, op, &x, &y, cacheId, flAccel,
290 fOpRedundant, &bound))
291 goto fail;
292
293 break;
294 }
295 }
296
297 if (!glyph->EndDraw(context, opX, opY, opWidth, opHeight, bgcolor, fgcolor))
298 goto fail;
299 }
300
301 rc = TRUE;
302
303fail:
304 return rc;
305}
306
307static BOOL update_gdi_glyph_index(rdpContext* context, GLYPH_INDEX_ORDER* glyphIndex)
308{
309 INT32 bkWidth = 0;
310 INT32 bkHeight = 0;
311 INT32 opWidth = 0;
312 INT32 opHeight = 0;
313
314 if (!context || !glyphIndex || !context->cache)
315 return FALSE;
316
317 if (glyphIndex->bkRight > glyphIndex->bkLeft)
318 bkWidth = glyphIndex->bkRight - glyphIndex->bkLeft + 1;
319
320 if (glyphIndex->opRight > glyphIndex->opLeft)
321 opWidth = glyphIndex->opRight - glyphIndex->opLeft + 1;
322
323 if (glyphIndex->bkBottom > glyphIndex->bkTop)
324 bkHeight = glyphIndex->bkBottom - glyphIndex->bkTop + 1;
325
326 if (glyphIndex->opBottom > glyphIndex->opTop)
327 opHeight = glyphIndex->opBottom - glyphIndex->opTop + 1;
328
329 return update_process_glyph_fragments(
330 context, glyphIndex->data, glyphIndex->cbData, glyphIndex->cacheId, glyphIndex->ulCharInc,
331 glyphIndex->flAccel, glyphIndex->backColor, glyphIndex->foreColor, glyphIndex->x,
332 glyphIndex->y, glyphIndex->bkLeft, glyphIndex->bkTop, bkWidth, bkHeight, glyphIndex->opLeft,
333 glyphIndex->opTop, opWidth, opHeight,
334 WINPR_ASSERTING_INT_CAST(int32_t, glyphIndex->fOpRedundant));
335}
336
337static BOOL update_gdi_fast_index(rdpContext* context, const FAST_INDEX_ORDER* fastIndex)
338{
339 INT32 opWidth = 0;
340 INT32 opHeight = 0;
341 INT32 bkWidth = 0;
342 INT32 bkHeight = 0;
343 BOOL rc = FALSE;
344
345 if (!context || !fastIndex || !context->cache)
346 return FALSE;
347
348 INT32 opLeft = fastIndex->opLeft;
349 INT32 opTop = fastIndex->opTop;
350 INT32 opRight = fastIndex->opRight;
351 INT32 opBottom = fastIndex->opBottom;
352 INT32 x = fastIndex->x;
353 INT32 y = fastIndex->y;
354
355 if (opBottom == -32768)
356 {
357 BYTE flags = (BYTE)(opTop & 0x0F);
358
359 if (flags & 0x01)
360 opBottom = fastIndex->bkBottom;
361
362 if (flags & 0x02)
363 opRight = fastIndex->bkRight;
364
365 if (flags & 0x04)
366 opTop = fastIndex->bkTop;
367
368 if (flags & 0x08)
369 opLeft = fastIndex->bkLeft;
370 }
371
372 if (opLeft == 0)
373 opLeft = fastIndex->bkLeft;
374
375 if (opRight == 0)
376 opRight = fastIndex->bkRight;
377
378 /* Server can send a massive number (32766) which appears to be
379 * undocumented special behavior for "Erase all the way right".
380 * X11 has nondeterministic results asking for a draw that wide. */
381 if (opRight > (INT64)freerdp_settings_get_uint32(context->settings, FreeRDP_DesktopWidth))
382 opRight = (int)freerdp_settings_get_uint32(context->settings, FreeRDP_DesktopWidth);
383
384 if (x == -32768)
385 x = fastIndex->bkLeft;
386
387 if (y == -32768)
388 y = fastIndex->bkTop;
389
390 if (fastIndex->bkRight > fastIndex->bkLeft)
391 bkWidth = fastIndex->bkRight - fastIndex->bkLeft + 1;
392
393 if (fastIndex->bkBottom > fastIndex->bkTop)
394 bkHeight = fastIndex->bkBottom - fastIndex->bkTop + 1;
395
396 if (opRight > opLeft)
397 opWidth = opRight - opLeft + 1;
398
399 if (opBottom > opTop)
400 opHeight = opBottom - opTop + 1;
401
402 if (!update_process_glyph_fragments(
403 context, fastIndex->data, fastIndex->cbData, fastIndex->cacheId, fastIndex->ulCharInc,
404 fastIndex->flAccel, fastIndex->backColor, fastIndex->foreColor, x, y, fastIndex->bkLeft,
405 fastIndex->bkTop, bkWidth, bkHeight, opLeft, opTop, opWidth, opHeight, FALSE))
406 goto fail;
407
408 rc = TRUE;
409fail:
410 return rc;
411}
412
413static BOOL update_gdi_fast_glyph(rdpContext* context, const FAST_GLYPH_ORDER* fastGlyph)
414{
415 INT32 x = 0;
416 INT32 y = 0;
417 BYTE text_data[4] = WINPR_C_ARRAY_INIT;
418 INT32 opLeft = 0;
419 INT32 opTop = 0;
420 INT32 opRight = 0;
421 INT32 opBottom = 0;
422 INT32 opWidth = 0;
423 INT32 opHeight = 0;
424 INT32 bkWidth = 0;
425 INT32 bkHeight = 0;
426 rdpCache* cache = nullptr;
427
428 if (!context || !fastGlyph || !context->cache)
429 return FALSE;
430
431 cache = context->cache;
432 opLeft = fastGlyph->opLeft;
433 opTop = fastGlyph->opTop;
434 opRight = fastGlyph->opRight;
435 opBottom = fastGlyph->opBottom;
436 x = fastGlyph->x;
437 y = fastGlyph->y;
438
439 if (opBottom == -32768)
440 {
441 BYTE flags = (BYTE)(opTop & 0x0F);
442
443 if (flags & 0x01)
444 opBottom = fastGlyph->bkBottom;
445
446 if (flags & 0x02)
447 opRight = fastGlyph->bkRight;
448
449 if (flags & 0x04)
450 opTop = fastGlyph->bkTop;
451
452 if (flags & 0x08)
453 opLeft = fastGlyph->bkLeft;
454 }
455
456 if (opLeft == 0)
457 opLeft = fastGlyph->bkLeft;
458
459 if (opRight == 0)
460 opRight = fastGlyph->bkRight;
461
462 /* See update_gdi_fast_index opRight comment. */
463 if (opRight > (INT64)freerdp_settings_get_uint32(context->settings, FreeRDP_DesktopWidth))
464 opRight = (int)freerdp_settings_get_uint32(context->settings, FreeRDP_DesktopWidth);
465
466 if (x == -32768)
467 x = fastGlyph->bkLeft;
468
469 if (y == -32768)
470 y = fastGlyph->bkTop;
471
472 if ((fastGlyph->cbData > 1) && (fastGlyph->glyphData.aj))
473 {
474 /* got option font that needs to go into cache */
475 rdpGlyph* glyph = nullptr;
476 const GLYPH_DATA_V2* glyphData = &fastGlyph->glyphData;
477
478 glyph = Glyph_Alloc(context, glyphData->x, glyphData->y, glyphData->cx, glyphData->cy,
479 glyphData->cb, glyphData->aj);
480
481 if (!glyph)
482 return FALSE;
483
484 if (!glyph_cache_put(cache->glyph, fastGlyph->cacheId, fastGlyph->data[0], glyph))
485 {
486 glyph->Free(context, glyph);
487 return FALSE;
488 }
489 }
490
491 text_data[0] = fastGlyph->data[0];
492 text_data[1] = 0;
493
494 if (fastGlyph->bkRight > fastGlyph->bkLeft)
495 bkWidth = fastGlyph->bkRight - fastGlyph->bkLeft + 1;
496
497 if (fastGlyph->bkBottom > fastGlyph->bkTop)
498 bkHeight = fastGlyph->bkBottom - fastGlyph->bkTop + 1;
499
500 if (opRight > opLeft)
501 opWidth = opRight - opLeft + 1;
502
503 if (opBottom > opTop)
504 opHeight = opBottom - opTop + 1;
505
506 return update_process_glyph_fragments(
507 context, text_data, sizeof(text_data), fastGlyph->cacheId, fastGlyph->ulCharInc,
508 fastGlyph->flAccel, fastGlyph->backColor, fastGlyph->foreColor, x, y, fastGlyph->bkLeft,
509 fastGlyph->bkTop, bkWidth, bkHeight, opLeft, opTop, opWidth, opHeight, FALSE);
510}
511
512static BOOL update_gdi_cache_glyph(rdpContext* context, const CACHE_GLYPH_ORDER* cacheGlyph)
513{
514 if (!context || !cacheGlyph || !context->cache)
515 return FALSE;
516
517 rdpCache* cache = context->cache;
518
519 for (size_t i = 0; i < cacheGlyph->cGlyphs; i++)
520 {
521 const GLYPH_DATA* glyph_data = &cacheGlyph->glyphData[i];
522 rdpGlyph* glyph = Glyph_Alloc(context, glyph_data->x, glyph_data->y, glyph_data->cx,
523 glyph_data->cy, glyph_data->cb, glyph_data->aj);
524 if (!glyph)
525 return FALSE;
526
527 if (!glyph_cache_put(cache->glyph, cacheGlyph->cacheId, glyph_data->cacheIndex, glyph))
528 {
529 glyph->Free(context, glyph);
530 return FALSE;
531 }
532 }
533
534 return TRUE;
535}
536
537static BOOL update_gdi_cache_glyph_v2(rdpContext* context, const CACHE_GLYPH_V2_ORDER* cacheGlyphV2)
538{
539 if (!context || !cacheGlyphV2 || !context->cache)
540 return FALSE;
541
542 rdpCache* cache = context->cache;
543
544 for (size_t i = 0; i < cacheGlyphV2->cGlyphs; i++)
545 {
546 const GLYPH_DATA_V2* glyphData = &cacheGlyphV2->glyphData[i];
547 rdpGlyph* glyph = Glyph_Alloc(context, glyphData->x, glyphData->y, glyphData->cx,
548 glyphData->cy, glyphData->cb, glyphData->aj);
549
550 if (!glyph)
551 return FALSE;
552
553 if (!glyph_cache_put(cache->glyph, cacheGlyphV2->cacheId, glyphData->cacheIndex, glyph))
554 {
555 glyph->Free(context, glyph);
556 return FALSE;
557 }
558 }
559
560 return TRUE;
561}
562
563rdpGlyph* glyph_cache_get(rdpGlyphCache* glyphCache, UINT32 id, UINT32 index)
564{
565 WINPR_ASSERT(glyphCache);
566
567 WLog_Print(glyphCache->log, WLOG_DEBUG, "GlyphCacheGet: id: %" PRIu32 " index: %" PRIu32 "", id,
568 index);
569
570 if (id >= ARRAYSIZE(glyphCache->glyphCache))
571 {
572 WLog_ERR(TAG, "invalid glyph cache id: %" PRIu32 "", id);
573 return nullptr;
574 }
575
576 GLYPH_CACHE* cache = &glyphCache->glyphCache[id];
577 if (index >= cache->number)
578 {
579 WLog_ERR(TAG, "index %" PRIu32 " out of range for cache id: %" PRIu32 "", index, id);
580 return nullptr;
581 }
582
583 rdpGlyph* glyph = cache->entries[index];
584 if (!glyph)
585 WLog_ERR(TAG, "no glyph found at cache index: %" PRIu32 " in cache id: %" PRIu32 "", index,
586 id);
587
588 return glyph;
589}
590
591BOOL glyph_cache_put(rdpGlyphCache* glyphCache, UINT32 id, UINT32 index, rdpGlyph* glyph)
592{
593 WINPR_ASSERT(glyphCache);
594
595 if (id >= ARRAYSIZE(glyphCache->glyphCache))
596 {
597 WLog_ERR(TAG, "invalid glyph cache id: %" PRIu32 "", id);
598 return FALSE;
599 }
600
601 GLYPH_CACHE* cache = &glyphCache->glyphCache[id];
602 if (index >= cache->number)
603 {
604 WLog_ERR(TAG, "invalid glyph cache index: %" PRIu32 " in cache id: %" PRIu32 "", index, id);
605 return FALSE;
606 }
607
608 WLog_Print(glyphCache->log, WLOG_DEBUG, "GlyphCachePut: id: %" PRIu32 " index: %" PRIu32 "", id,
609 index);
610 rdpGlyph* prevGlyph = cache->entries[index];
611
612 if (prevGlyph)
613 {
614 WINPR_ASSERT(prevGlyph->Free);
615 prevGlyph->Free(glyphCache->context, prevGlyph);
616 }
617
618 cache->entries[index] = glyph;
619 return TRUE;
620}
621
622const void* glyph_cache_fragment_get(rdpGlyphCache* glyphCache, UINT32 index, UINT32* size)
623{
624 void* fragment = nullptr;
625
626 WINPR_ASSERT(glyphCache);
627 WINPR_ASSERT(glyphCache->fragCache.entries);
628
629 if (index > 255)
630 {
631 WLog_ERR(TAG, "invalid glyph cache fragment index: %" PRIu32 "", index);
632 return nullptr;
633 }
634
635 fragment = glyphCache->fragCache.entries[index].fragment;
636 *size = (BYTE)glyphCache->fragCache.entries[index].size;
637 WLog_Print(glyphCache->log, WLOG_DEBUG,
638 "GlyphCacheFragmentGet: index: %" PRIu32 " size: %" PRIu32 "", index, *size);
639
640 if (!fragment)
641 WLog_ERR(TAG, "invalid glyph fragment at index:%" PRIu32 "", index);
642
643 return fragment;
644}
645
646BOOL glyph_cache_fragment_put(rdpGlyphCache* glyphCache, UINT32 index, UINT32 size,
647 const void* fragment)
648{
649 WINPR_ASSERT(glyphCache);
650 WINPR_ASSERT(glyphCache->fragCache.entries);
651
652 if (index > 255)
653 {
654 WLog_ERR(TAG, "invalid glyph cache fragment index: %" PRIu32 "", index);
655 return FALSE;
656 }
657
658 if (size == 0)
659 return FALSE;
660
661 void* copy = malloc(size);
662
663 if (!copy)
664 return FALSE;
665
666 WLog_Print(glyphCache->log, WLOG_DEBUG,
667 "GlyphCacheFragmentPut: index: %" PRIu32 " size: %" PRIu32 "", index, size);
668 CopyMemory(copy, fragment, size);
669
670 void* prevFragment = glyphCache->fragCache.entries[index].fragment;
671 glyphCache->fragCache.entries[index].fragment = copy;
672 glyphCache->fragCache.entries[index].size = size;
673 free(prevFragment);
674 return TRUE;
675}
676
677void glyph_cache_register_callbacks(rdpUpdate* update)
678{
679 WINPR_ASSERT(update);
680 WINPR_ASSERT(update->context);
681 WINPR_ASSERT(update->primary);
682 WINPR_ASSERT(update->secondary);
683
684 if (!freerdp_settings_get_bool(update->context->settings, FreeRDP_DeactivateClientDecoding))
685 {
686 update->primary->GlyphIndex = update_gdi_glyph_index;
687 update->primary->FastIndex = update_gdi_fast_index;
688 update->primary->FastGlyph = update_gdi_fast_glyph;
689 update->secondary->CacheGlyph = update_gdi_cache_glyph;
690 update->secondary->CacheGlyphV2 = update_gdi_cache_glyph_v2;
691 }
692}
693
694rdpGlyphCache* glyph_cache_new(rdpContext* context)
695{
696 rdpGlyphCache* glyphCache = nullptr;
697 rdpSettings* settings = nullptr;
698
699 WINPR_ASSERT(context);
700
701 settings = context->settings;
702 WINPR_ASSERT(settings);
703
704 glyphCache = (rdpGlyphCache*)calloc(1, sizeof(rdpGlyphCache));
705
706 if (!glyphCache)
707 return nullptr;
708
709 glyphCache->log = WLog_Get("com.freerdp.cache.glyph");
710 glyphCache->context = context;
711
712 for (size_t i = 0; i < 10; i++)
713 {
714 const GLYPH_CACHE_DEFINITION* currentGlyph =
715 freerdp_settings_get_pointer_array(settings, FreeRDP_GlyphCache, i);
716 GLYPH_CACHE* currentCache = &glyphCache->glyphCache[i];
717 currentCache->number = currentGlyph->cacheEntries;
718 currentCache->maxCellSize = currentGlyph->cacheMaximumCellSize;
719 currentCache->entries = (rdpGlyph**)calloc(currentCache->number, sizeof(rdpGlyph*));
720
721 if (!currentCache->entries)
722 goto fail;
723 }
724
725 return glyphCache;
726fail:
727 WINPR_PRAGMA_DIAG_PUSH
728 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
729 glyph_cache_free(glyphCache);
730 WINPR_PRAGMA_DIAG_POP
731 return nullptr;
732}
733
734void glyph_cache_free(rdpGlyphCache* glyphCache)
735{
736 if (glyphCache)
737 {
738 GLYPH_CACHE* cache = glyphCache->glyphCache;
739
740 for (size_t i = 0; i < 10; i++)
741 {
742 rdpGlyph** entries = cache[i].entries;
743
744 if (!entries)
745 continue;
746
747 for (size_t j = 0; j < cache[i].number; j++)
748 {
749 rdpGlyph* glyph = entries[j];
750
751 if (glyph)
752 {
753 glyph->Free(glyphCache->context, glyph);
754 entries[j] = nullptr;
755 }
756 }
757
758 free((void*)entries);
759 cache[i].entries = nullptr;
760 }
761
762 for (size_t i = 0; i < ARRAYSIZE(glyphCache->fragCache.entries); i++)
763 {
764 free(glyphCache->fragCache.entries[i].fragment);
765 glyphCache->fragCache.entries[i].fragment = nullptr;
766 }
767
768 free(glyphCache);
769 }
770}
771
772CACHE_GLYPH_ORDER* copy_cache_glyph_order(rdpContext* context, const CACHE_GLYPH_ORDER* glyph)
773{
774 CACHE_GLYPH_ORDER* dst = nullptr;
775
776 WINPR_ASSERT(context);
777
778 dst = calloc(1, sizeof(CACHE_GLYPH_ORDER));
779
780 if (!dst || !glyph)
781 goto fail;
782
783 *dst = *glyph;
784
785 for (size_t x = 0; x < glyph->cGlyphs; x++)
786 {
787 const GLYPH_DATA* src = &glyph->glyphData[x];
788 GLYPH_DATA* data = &dst->glyphData[x];
789
790 if (src->aj)
791 {
792 const size_t size = src->cb;
793 data->aj = malloc(size);
794
795 if (!data->aj)
796 goto fail;
797
798 memcpy(data->aj, src->aj, size);
799 }
800 }
801
802 if (glyph->unicodeCharacters)
803 {
804 if (glyph->cGlyphs == 0)
805 goto fail;
806
807 dst->unicodeCharacters = calloc(glyph->cGlyphs, sizeof(WCHAR));
808
809 if (!dst->unicodeCharacters)
810 goto fail;
811
812 memcpy(dst->unicodeCharacters, glyph->unicodeCharacters, sizeof(WCHAR) * glyph->cGlyphs);
813 }
814
815 return dst;
816fail:
817 free_cache_glyph_order(context, dst);
818 return nullptr;
819}
820
821void free_cache_glyph_order(WINPR_ATTR_UNUSED rdpContext* context, CACHE_GLYPH_ORDER* glyph)
822{
823 if (glyph)
824 {
825 for (size_t x = 0; x < ARRAYSIZE(glyph->glyphData); x++)
826 free(glyph->glyphData[x].aj);
827
828 free(glyph->unicodeCharacters);
829 }
830
831 free(glyph);
832}
833
834CACHE_GLYPH_V2_ORDER* copy_cache_glyph_v2_order(rdpContext* context,
835 const CACHE_GLYPH_V2_ORDER* glyph)
836{
837 CACHE_GLYPH_V2_ORDER* dst = nullptr;
838
839 WINPR_ASSERT(context);
840
841 dst = calloc(1, sizeof(CACHE_GLYPH_V2_ORDER));
842
843 if (!dst || !glyph)
844 goto fail;
845
846 *dst = *glyph;
847
848 for (size_t x = 0; x < glyph->cGlyphs; x++)
849 {
850 const GLYPH_DATA_V2* src = &glyph->glyphData[x];
851 GLYPH_DATA_V2* data = &dst->glyphData[x];
852
853 if (src->aj)
854 {
855 const size_t size = src->cb;
856 data->aj = malloc(size);
857
858 if (!data->aj)
859 goto fail;
860
861 memcpy(data->aj, src->aj, size);
862 }
863 }
864
865 if (glyph->unicodeCharacters)
866 {
867 if (glyph->cGlyphs == 0)
868 goto fail;
869
870 dst->unicodeCharacters = calloc(glyph->cGlyphs, sizeof(WCHAR));
871
872 if (!dst->unicodeCharacters)
873 goto fail;
874
875 memcpy(dst->unicodeCharacters, glyph->unicodeCharacters, sizeof(WCHAR) * glyph->cGlyphs);
876 }
877
878 return dst;
879fail:
880 free_cache_glyph_v2_order(context, dst);
881 return nullptr;
882}
883
884void free_cache_glyph_v2_order(WINPR_ATTR_UNUSED rdpContext* context, CACHE_GLYPH_V2_ORDER* glyph)
885{
886 if (glyph)
887 {
888 for (size_t x = 0; x < ARRAYSIZE(glyph->glyphData); x++)
889 free(glyph->glyphData[x].aj);
890
891 free(glyph->unicodeCharacters);
892 }
893
894 free(glyph);
895}
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.