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