2 * FreeRDP: A Remote Desktop Protocol Client
5 * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
20 #include <freerdp/freerdp.h>
21 #include <freerdp/utils/stream.h>
22 #include <freerdp/utils/memory.h>
24 #include <freerdp/cache/glyph.h>
26 void update_process_glyph(rdpContext* context, uint8* data, int* index,
27 int* x, int* y, uint32 cacheId, uint32 ulCharInc, uint32 flAccel)
32 rdpGraphics* graphics;
33 rdpGlyphCache* glyph_cache;
35 graphics = context->graphics;
36 glyph_cache = context->cache->glyph;
38 cacheIndex = data[*index];
40 glyph = glyph_cache_get(glyph_cache, cacheId, cacheIndex);
42 if ((ulCharInc == 0) && (!(flAccel & SO_CHAR_INC_EQUAL_BM_BASE)))
45 offset = data[*index];
49 offset = data[*index + 1] | (data[*index + 2] << 8);
54 if (flAccel & SO_VERTICAL)
62 Glyph_Draw(context, glyph, glyph->x + *x, glyph->y + *y);
64 if (flAccel & SO_CHAR_INC_EQUAL_BM_BASE)
69 void update_process_glyph_fragments(rdpContext* context, uint8* data, uint32 length,
70 uint32 cacheId, uint32 ulCharInc, uint32 flAccel, uint32 bgcolor, uint32 fgcolor, int x, int y,
71 int bkX, int bkY, int bkWidth, int bkHeight, int opX, int opY, int opWidth, int opHeight)
78 rdpGraphics* graphics;
79 rdpGlyphCache* glyph_cache;
81 graphics = context->graphics;
82 glyph_cache = context->cache->glyph;
84 if (opWidth > 0 && opHeight > 0)
85 Glyph_BeginDraw(context, opX, opY, opWidth, opHeight, bgcolor, fgcolor);
87 Glyph_BeginDraw(context, 0, 0, 0, 0, bgcolor, fgcolor);
89 while (index < (int) length)
93 case GLYPH_FRAGMENT_USE:
95 if (index + 2 > (int) length)
97 /* at least one byte need to follow */
102 id = data[index + 1];
103 fragments = (uint8*) glyph_cache_fragment_get(glyph_cache, id, &size);
105 if (fragments != NULL)
107 if ((ulCharInc == 0) && (!(flAccel & SO_CHAR_INC_EQUAL_BM_BASE)))
109 if (flAccel & SO_VERTICAL)
110 y += data[index + 2];
112 x += data[index + 2];
115 for (n = 0; n < (int) size; n++)
117 update_process_glyph(context, fragments, &n, &x, &y, cacheId, ulCharInc, flAccel);
121 index += (index + 2 < (int) length) ? 3 : 2;
123 data = &(data[index]);
128 case GLYPH_FRAGMENT_ADD:
130 if (index + 3 > (int) length)
132 /* at least two bytes need to follow */
137 id = data[index + 1];
138 size = data[index + 2];
140 fragments = (uint8*) xmalloc(size);
141 memcpy(fragments, data, size);
142 glyph_cache_fragment_put(glyph_cache, id, size, fragments);
146 data = &(data[index]);
152 update_process_glyph(context, data, &index, &x, &y, cacheId, ulCharInc, flAccel);
158 if (opWidth > 0 && opHeight > 0)
159 Glyph_EndDraw(context, opX, opY, opWidth, opHeight, bgcolor, fgcolor);
161 Glyph_EndDraw(context, bkX, bkY, bkWidth, bkHeight, bgcolor, fgcolor);
164 void update_gdi_glyph_index(rdpContext* context, GLYPH_INDEX_ORDER* glyph_index)
166 rdpGlyphCache* glyph_cache;
168 glyph_cache = context->cache->glyph;
169 update_process_glyph_fragments(context, glyph_index->data, glyph_index->cbData,
170 glyph_index->cacheId, glyph_index->ulCharInc, glyph_index->flAccel,
171 glyph_index->backColor, glyph_index->foreColor, glyph_index->x, glyph_index->y,
172 glyph_index->bkLeft, glyph_index->bkTop,
173 glyph_index->bkRight - glyph_index->bkLeft, glyph_index->bkBottom - glyph_index->bkTop,
174 glyph_index->opLeft, glyph_index->opTop,
175 glyph_index->opRight - glyph_index->opLeft, glyph_index->opBottom - glyph_index->opTop);
178 void update_gdi_fast_index(rdpContext* context, FAST_INDEX_ORDER* fast_index)
180 sint32 opLeft, opTop, opRight, opBottom;
182 rdpGlyphCache* glyph_cache;
184 glyph_cache = context->cache->glyph;
186 opLeft = fast_index->opLeft;
187 opTop = fast_index->opTop;
188 opRight = fast_index->opRight;
189 opBottom = fast_index->opBottom;
193 if (opBottom == -32768)
195 uint8 flags = (uint8) (opTop & 0x0F);
198 opBottom = fast_index->bkBottom;
200 opRight = fast_index->bkRight;
202 opTop = fast_index->bkTop;
204 opLeft = fast_index->bkLeft;
208 opLeft = fast_index->bkLeft;
211 opRight = fast_index->bkRight;
214 x = fast_index->bkLeft;
217 y = fast_index->bkTop;
219 update_process_glyph_fragments(context, fast_index->data, fast_index->cbData,
220 fast_index->cacheId, fast_index->ulCharInc, fast_index->flAccel,
221 fast_index->backColor, fast_index->foreColor, x, y,
222 fast_index->bkLeft, fast_index->bkTop,
223 fast_index->bkRight - fast_index->bkLeft, fast_index->bkBottom - fast_index->bkTop,
225 opRight - opLeft, opBottom - opTop);
228 void update_gdi_fast_glyph(rdpContext* context, FAST_GLYPH_ORDER* fast_glyph)
230 sint32 opLeft, opTop, opRight, opBottom;
232 GLYPH_DATA_V2* glyph_data;
234 rdpCache* cache = context->cache;
237 opLeft = fast_glyph->opLeft;
238 opTop = fast_glyph->opTop;
239 opRight = fast_glyph->opRight;
240 opBottom = fast_glyph->opBottom;
244 if (opBottom == -32768)
246 uint8 flags = (uint8) (opTop & 0x0F);
249 opBottom = fast_glyph->bkBottom;
251 opRight = fast_glyph->bkRight;
253 opTop = fast_glyph->bkTop;
255 opLeft = fast_glyph->bkLeft;
259 opLeft = fast_glyph->bkLeft;
262 opRight = fast_glyph->bkRight;
265 x = fast_glyph->bkLeft;
268 y = fast_glyph->bkTop;
270 if (fast_glyph->glyph_data != NULL)
272 /* got option font that needs to go into cache */
273 glyph_data = (GLYPH_DATA_V2*) (fast_glyph->glyph_data);
274 glyph = Glyph_Alloc(context);
275 glyph->x = glyph_data->x;
276 glyph->y = glyph_data->y;
277 glyph->cx = glyph_data->cx;
278 glyph->cy = glyph_data->cy;
279 glyph->aj = glyph_data->aj;
280 glyph->cb = glyph_data->cb;
281 Glyph_New(context, glyph);
282 glyph_cache_put(cache->glyph, fast_glyph->cacheId, fast_glyph->data[0], glyph);
283 xfree(fast_glyph->glyph_data);
284 fast_glyph->glyph_data = NULL;
287 text_data[0] = fast_glyph->data[0];
290 update_process_glyph_fragments(context, text_data, 1,
291 fast_glyph->cacheId, fast_glyph->ulCharInc, fast_glyph->flAccel,
292 fast_glyph->backColor, fast_glyph->foreColor, x, y,
293 fast_glyph->bkLeft, fast_glyph->bkTop,
294 fast_glyph->bkRight - fast_glyph->bkLeft, fast_glyph->bkBottom - fast_glyph->bkTop,
296 opRight - opLeft, opBottom - opTop);
299 void update_gdi_cache_glyph(rdpContext* context, CACHE_GLYPH_ORDER* cache_glyph)
303 GLYPH_DATA* glyph_data;
304 rdpCache* cache = context->cache;
306 for (i = 0; i < (int) cache_glyph->cGlyphs; i++)
308 glyph_data = cache_glyph->glyphData[i];
310 glyph = Glyph_Alloc(context);
312 glyph->x = glyph_data->x;
313 glyph->y = glyph_data->y;
314 glyph->cx = glyph_data->cx;
315 glyph->cy = glyph_data->cy;
316 glyph->aj = glyph_data->aj;
317 glyph->cb = glyph_data->cb;
318 Glyph_New(context, glyph);
320 glyph_cache_put(cache->glyph, cache_glyph->cacheId, glyph_data->cacheIndex, glyph);
322 cache_glyph->glyphData[i] = NULL;
327 void update_gdi_cache_glyph_v2(rdpContext* context, CACHE_GLYPH_V2_ORDER* cache_glyph_v2)
331 GLYPH_DATA_V2* glyph_data;
332 rdpCache* cache = context->cache;
334 for (i = 0; i < (int) cache_glyph_v2->cGlyphs; i++)
336 glyph_data = cache_glyph_v2->glyphData[i];
338 glyph = Glyph_Alloc(context);
340 glyph->x = glyph_data->x;
341 glyph->y = glyph_data->y;
342 glyph->cx = glyph_data->cx;
343 glyph->cy = glyph_data->cy;
344 glyph->aj = glyph_data->aj;
345 glyph->cb = glyph_data->cb;
346 Glyph_New(context, glyph);
348 glyph_cache_put(cache->glyph, cache_glyph_v2->cacheId, glyph_data->cacheIndex, glyph);
350 cache_glyph_v2->glyphData[i] = NULL;
355 rdpGlyph* glyph_cache_get(rdpGlyphCache* glyph_cache, uint32 id, uint32 index)
361 printf("invalid glyph cache id: %d\n", id);
365 if (index > glyph_cache->glyphCache[id].number)
367 printf("invalid glyph cache index: %d in cache id: %d\n", index, id);
371 glyph = glyph_cache->glyphCache[id].entries[index];
375 printf("invalid glyph at cache index: %d in cache id: %d\n", index, id);
381 void glyph_cache_put(rdpGlyphCache* glyph_cache, uint32 id, uint32 index, rdpGlyph* glyph)
387 printf("invalid glyph cache id: %d\n", id);
391 if (index > glyph_cache->glyphCache[id].number)
393 printf("invalid glyph cache index: %d in cache id: %d\n", index, id);
397 prevGlyph = glyph_cache->glyphCache[id].entries[index];
399 if (prevGlyph != NULL)
401 Glyph_Free(glyph_cache->context, prevGlyph);
402 xfree(prevGlyph->aj);
406 glyph_cache->glyphCache[id].entries[index] = glyph;
409 void* glyph_cache_fragment_get(rdpGlyphCache* glyph_cache, uint32 index, uint32* size)
413 fragment = glyph_cache->fragCache.entries[index].fragment;
414 *size = (uint8) glyph_cache->fragCache.entries[index].size;
416 if (fragment == NULL)
418 printf("invalid glyph fragment at index:%d\n", index);
424 void glyph_cache_fragment_put(rdpGlyphCache* glyph_cache, uint32 index, uint32 size, void* fragment)
428 prevFragment = glyph_cache->fragCache.entries[index].fragment;
430 glyph_cache->fragCache.entries[index].fragment = fragment;
431 glyph_cache->fragCache.entries[index].size = size;
433 if (prevFragment != NULL)
439 void glyph_cache_register_callbacks(rdpUpdate* update)
441 update->primary->GlyphIndex = update_gdi_glyph_index;
442 update->primary->FastIndex = update_gdi_fast_index;
443 update->primary->FastGlyph = update_gdi_fast_glyph;
444 update->secondary->CacheGlyph = update_gdi_cache_glyph;
445 update->secondary->CacheGlyphV2 = update_gdi_cache_glyph_v2;
448 rdpGlyphCache* glyph_cache_new(rdpSettings* settings)
450 rdpGlyphCache* glyph;
452 glyph = (rdpGlyphCache*) xzalloc(sizeof(rdpGlyphCache));
458 glyph->settings = settings;
459 glyph->context = ((freerdp*) settings->instance)->update->context;
461 if (settings->glyph_cache)
462 settings->glyphSupportLevel = GLYPH_SUPPORT_FULL;
464 for (i = 0; i < 10; i++)
466 glyph->glyphCache[i].number = settings->glyphCache[i].cacheEntries;
467 glyph->glyphCache[i].maxCellSize = settings->glyphCache[i].cacheMaximumCellSize;
468 glyph->glyphCache[i].entries = (rdpGlyph**) xzalloc(sizeof(rdpGlyph*) * glyph->glyphCache[i].number);
471 glyph->fragCache.entries = xzalloc(sizeof(FRAGMENT_CACHE_ENTRY) * 256);
477 void glyph_cache_free(rdpGlyphCache* glyph_cache)
479 if (glyph_cache != NULL)
484 for (i = 0; i < 10; i++)
488 for (j = 0; j < (int) glyph_cache->glyphCache[i].number; j++)
492 glyph = glyph_cache->glyphCache[i].entries[j];
496 Glyph_Free(glyph_cache->context, glyph);
501 xfree(glyph_cache->glyphCache[i].entries);
504 for (i = 0; i < 255; i++)
506 fragment = glyph_cache->fragCache.entries[i].fragment;
510 xfree(glyph_cache->fragCache.entries);