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