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