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