ReactOS 0.4.16-dev-1059-gb1cf981
ttcolr.c
Go to the documentation of this file.
1/****************************************************************************
2 *
3 * ttcolr.c
4 *
5 * TrueType and OpenType colored glyph layer support (body).
6 *
7 * Copyright (C) 2018-2019 by
8 * David Turner, Robert Wilhelm, and Werner Lemberg.
9 *
10 * Originally written by Shao Yu Zhang <shaozhang@fb.com>.
11 *
12 * This file is part of the FreeType project, and may only be used,
13 * modified, and distributed under the terms of the FreeType project
14 * license, LICENSE.TXT. By continuing to use, modify, or distribute
15 * this file you indicate that you have read the license and
16 * understand and accept it fully.
17 *
18 */
19
20
21 /**************************************************************************
22 *
23 * `COLR' table specification:
24 *
25 * https://www.microsoft.com/typography/otspec/colr.htm
26 *
27 */
28
29
30#include <ft2build.h>
31#include FT_INTERNAL_DEBUG_H
32#include FT_INTERNAL_STREAM_H
33#include FT_TRUETYPE_TAGS_H
34#include FT_COLOR_H
35
36
37#ifdef TT_CONFIG_OPTION_COLOR_LAYERS
38
39#include "ttcolr.h"
40
41
42 /* NOTE: These are the table sizes calculated through the specs. */
43#define BASE_GLYPH_SIZE 6
44#define LAYER_SIZE 4
45#define COLR_HEADER_SIZE 14
46
47
48 typedef struct BaseGlyphRecord_
49 {
50 FT_UShort gid;
51 FT_UShort first_layer_index;
52 FT_UShort num_layers;
53
54 } BaseGlyphRecord;
55
56
57 typedef struct Colr_
58 {
60 FT_UShort num_base_glyphs;
61 FT_UShort num_layers;
62
63 FT_Byte* base_glyphs;
64 FT_Byte* layers;
65
66 /* The memory which backs up the `COLR' table. */
67 void* table;
69
70 } Colr;
71
72
73 /**************************************************************************
74 *
75 * The macro FT_COMPONENT is used in trace mode. It is an implicit
76 * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
77 * messages during execution.
78 */
79#undef FT_COMPONENT
80#define FT_COMPONENT ttcolr
81
82
86 {
88 FT_Memory memory = face->root.memory;
89
91 FT_Byte* p = NULL;
92
93 Colr* colr = NULL;
94
95 FT_ULong base_glyph_offset, layer_offset;
97
98
99 /* `COLR' always needs `CPAL' */
100 if ( !face->cpal )
101 return FT_THROW( Invalid_File_Format );
102
103 error = face->goto_table( face, TTAG_COLR, stream, &table_size );
104 if ( error )
105 goto NoColr;
106
107 if ( table_size < COLR_HEADER_SIZE )
108 goto InvalidTable;
109
111 goto NoColr;
112
113 p = table;
114
115 if ( FT_NEW( colr ) )
116 goto NoColr;
117
118 colr->version = FT_NEXT_USHORT( p );
119 if ( colr->version != 0 )
120 goto InvalidTable;
121
122 colr->num_base_glyphs = FT_NEXT_USHORT( p );
123 base_glyph_offset = FT_NEXT_ULONG( p );
124
125 if ( base_glyph_offset >= table_size )
126 goto InvalidTable;
127 if ( colr->num_base_glyphs * BASE_GLYPH_SIZE >
128 table_size - base_glyph_offset )
129 goto InvalidTable;
130
131 layer_offset = FT_NEXT_ULONG( p );
132 colr->num_layers = FT_NEXT_USHORT( p );
133
134 if ( layer_offset >= table_size )
135 goto InvalidTable;
136 if ( colr->num_layers * LAYER_SIZE > table_size - layer_offset )
137 goto InvalidTable;
138
139 colr->base_glyphs = (FT_Byte*)( table + base_glyph_offset );
140 colr->layers = (FT_Byte*)( table + layer_offset );
141 colr->table = table;
142 colr->table_size = table_size;
143
144 face->colr = colr;
145
146 return FT_Err_Ok;
147
148 InvalidTable:
149 error = FT_THROW( Invalid_Table );
150
151 NoColr:
153 FT_FREE( colr );
154
155 return error;
156 }
157
158
159 FT_LOCAL_DEF( void )
161 {
162 FT_Stream stream = face->root.stream;
163 FT_Memory memory = face->root.memory;
164
165 Colr* colr = (Colr*)face->colr;
166
167
168 if ( colr )
169 {
170 FT_FRAME_RELEASE( colr->table );
171 FT_FREE( colr );
172 }
173 }
174
175
176 static FT_Bool
177 find_base_glyph_record( FT_Byte* base_glyph_begin,
178 FT_Int num_base_glyph,
179 FT_UInt glyph_id,
180 BaseGlyphRecord* record )
181 {
182 FT_Int min = 0;
183 FT_Int max = num_base_glyph - 1;
184
185
186 while ( min <= max )
187 {
188 FT_Int mid = min + ( max - min ) / 2;
189 FT_Byte* p = base_glyph_begin + mid * BASE_GLYPH_SIZE;
190
191 FT_UShort gid = FT_NEXT_USHORT( p );
192
193
194 if ( gid < glyph_id )
195 min = mid + 1;
196 else if (gid > glyph_id )
197 max = mid - 1;
198 else
199 {
200 record->gid = gid;
201 record->first_layer_index = FT_NEXT_USHORT( p );
202 record->num_layers = FT_NEXT_USHORT( p );
203
204 return 1;
205 }
206 }
207
208 return 0;
209 }
210
211
214 FT_UInt base_glyph,
215 FT_UInt *aglyph_index,
216 FT_UInt *acolor_index,
218 {
219 Colr* colr = (Colr*)face->colr;
220 BaseGlyphRecord glyph_record;
221
222
223 if ( !colr )
224 return 0;
225
226 if ( !iterator->p )
227 {
229
230
231 /* first call to function */
232 iterator->layer = 0;
233
234 if ( !find_base_glyph_record( colr->base_glyphs,
235 colr->num_base_glyphs,
236 base_glyph,
237 &glyph_record ) )
238 return 0;
239
240 if ( glyph_record.num_layers )
241 iterator->num_layers = glyph_record.num_layers;
242 else
243 return 0;
244
245 offset = LAYER_SIZE * glyph_record.first_layer_index;
246 if ( offset + LAYER_SIZE * glyph_record.num_layers > colr->table_size )
247 return 0;
248
249 iterator->p = colr->layers + offset;
250 }
251
252 if ( iterator->layer >= iterator->num_layers )
253 return 0;
254
255 *aglyph_index = FT_NEXT_USHORT( iterator->p );
256 *acolor_index = FT_NEXT_USHORT( iterator->p );
257
258 if ( *aglyph_index >= (FT_UInt)( FT_FACE( face )->num_glyphs ) ||
259 ( *acolor_index != 0xFFFF &&
260 *acolor_index >= face->palette_data.num_palette_entries ) )
261 return 0;
262
263 iterator->layer++;
264
265 return 1;
266 }
267
268
271 FT_UInt color_index,
272 FT_GlyphSlot dstSlot,
273 FT_GlyphSlot srcSlot )
274 {
276
277 FT_UInt x, y;
278 FT_Byte b, g, r, alpha;
279
281 FT_Byte* src;
282 FT_Byte* dst;
283
284
285 if ( !dstSlot->bitmap.buffer )
286 {
287 /* Initialize destination of color bitmap */
288 /* with the size of first component. */
289 dstSlot->bitmap_left = srcSlot->bitmap_left;
290 dstSlot->bitmap_top = srcSlot->bitmap_top;
291
292 dstSlot->bitmap.width = srcSlot->bitmap.width;
293 dstSlot->bitmap.rows = srcSlot->bitmap.rows;
295 dstSlot->bitmap.pitch = (int)dstSlot->bitmap.width * 4;
296 dstSlot->bitmap.num_grays = 256;
297
298 size = dstSlot->bitmap.rows * (unsigned int)dstSlot->bitmap.pitch;
299
301 if ( error )
302 return error;
303
304 FT_MEM_ZERO( dstSlot->bitmap.buffer, size );
305 }
306 else
307 {
308 /* Resize destination if needed such that new component fits. */
309 FT_Int x_min, x_max, y_min, y_max;
310
311
312 x_min = FT_MIN( dstSlot->bitmap_left, srcSlot->bitmap_left );
313 x_max = FT_MAX( dstSlot->bitmap_left + (FT_Int)dstSlot->bitmap.width,
314 srcSlot->bitmap_left + (FT_Int)srcSlot->bitmap.width );
315
316 y_min = FT_MIN( dstSlot->bitmap_top - (FT_Int)dstSlot->bitmap.rows,
317 srcSlot->bitmap_top - (FT_Int)srcSlot->bitmap.rows );
318 y_max = FT_MAX( dstSlot->bitmap_top, srcSlot->bitmap_top );
319
320 if ( x_min != dstSlot->bitmap_left ||
321 x_max != dstSlot->bitmap_left + (FT_Int)dstSlot->bitmap.width ||
322 y_min != dstSlot->bitmap_top - (FT_Int)dstSlot->bitmap.rows ||
323 y_max != dstSlot->bitmap_top )
324 {
325 FT_Memory memory = face->root.memory;
326
327 FT_UInt width = (FT_UInt)( x_max - x_min );
328 FT_UInt rows = (FT_UInt)( y_max - y_min );
329 FT_UInt pitch = width * 4;
330
331 FT_Byte* buf = NULL;
332 FT_Byte* p;
333 FT_Byte* q;
334
335
336 size = rows * pitch;
337 if ( FT_ALLOC( buf, size ) )
338 return error;
339
340 p = dstSlot->bitmap.buffer;
341 q = buf +
342 (int)pitch * ( y_max - dstSlot->bitmap_top ) +
343 4 * ( dstSlot->bitmap_left - x_min );
344
345 for ( y = 0; y < dstSlot->bitmap.rows; y++ )
346 {
347 FT_MEM_COPY( q, p, dstSlot->bitmap.width * 4 );
348
349 p += dstSlot->bitmap.pitch;
350 q += pitch;
351 }
352
353 ft_glyphslot_set_bitmap( dstSlot, buf );
354
355 dstSlot->bitmap_top = y_max;
356 dstSlot->bitmap_left = x_min;
357
358 dstSlot->bitmap.width = width;
359 dstSlot->bitmap.rows = rows;
360 dstSlot->bitmap.pitch = (int)pitch;
361
363 dstSlot->format = FT_GLYPH_FORMAT_BITMAP;
364 }
365 }
366
367 if ( color_index == 0xFFFF )
368 {
369 if ( face->have_foreground_color )
370 {
371 b = face->foreground_color.blue;
372 g = face->foreground_color.green;
373 r = face->foreground_color.red;
374 alpha = face->foreground_color.alpha;
375 }
376 else
377 {
378 if ( face->palette_data.palette_flags &&
379 ( face->palette_data.palette_flags[face->palette_index] &
381 {
382 /* white opaque */
383 b = 0xFF;
384 g = 0xFF;
385 r = 0xFF;
386 alpha = 0xFF;
387 }
388 else
389 {
390 /* black opaque */
391 b = 0x00;
392 g = 0x00;
393 r = 0x00;
394 alpha = 0xFF;
395 }
396 }
397 }
398 else
399 {
400 b = face->palette[color_index].blue;
401 g = face->palette[color_index].green;
402 r = face->palette[color_index].red;
403 alpha = face->palette[color_index].alpha;
404 }
405
406 /* XXX Convert if srcSlot.bitmap is not grey? */
407 src = srcSlot->bitmap.buffer;
408 dst = dstSlot->bitmap.buffer +
409 dstSlot->bitmap.pitch * ( dstSlot->bitmap_top - srcSlot->bitmap_top ) +
410 4 * ( srcSlot->bitmap_left - dstSlot->bitmap_left );
411
412 for ( y = 0; y < srcSlot->bitmap.rows; y++ )
413 {
414 for ( x = 0; x < srcSlot->bitmap.width; x++ )
415 {
416 int aa = src[x];
417 int fa = alpha * aa / 255;
418
419 int fb = b * fa / 255;
420 int fg = g * fa / 255;
421 int fr = r * fa / 255;
422
423 int ba2 = 255 - fa;
424
425 int bb = dst[4 * x + 0];
426 int bg = dst[4 * x + 1];
427 int br = dst[4 * x + 2];
428 int ba = dst[4 * x + 3];
429
430
431 dst[4 * x + 0] = (FT_Byte)( bb * ba2 / 255 + fb );
432 dst[4 * x + 1] = (FT_Byte)( bg * ba2 / 255 + fg );
433 dst[4 * x + 2] = (FT_Byte)( br * ba2 / 255 + fr );
434 dst[4 * x + 3] = (FT_Byte)( ba * ba2 / 255 + fa );
435 }
436
437 src += srcSlot->bitmap.pitch;
438 dst += dstSlot->bitmap.pitch;
439 }
440
441 return FT_Err_Ok;
442 }
443
444#else /* !TT_CONFIG_OPTION_COLOR_LAYERS */
445
446 /* ANSI C doesn't like empty source files */
447 typedef int _tt_colr_dummy;
448
449#endif /* !TT_CONFIG_OPTION_COLOR_LAYERS */
450
451/* EOF */
#define NULL
Definition: types.h:112
static const WCHAR version[]
Definition: asmname.c:66
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
return FT_Err_Ok
Definition: ftbbox.c:527
#define FT_PALETTE_FOR_DARK_BACKGROUND
Definition: ftcolor.h:112
#define FT_LOCAL_DEF(x)
Definition: ftconfig.h:387
#define FT_THROW(e)
Definition: ftdebug.h:241
@ FT_PIXEL_MODE_BGRA
Definition: ftimage.h:190
#define FT_NEW(ptr)
Definition: ftmemory.h:330
#define FT_ALLOC(ptr, size)
Definition: ftmemory.h:302
#define FT_FREE(ptr)
Definition: ftmemory.h:328
#define FT_MEM_COPY(dest, source, count)
Definition: ftmemory.h:228
#define FT_MEM_ZERO(dest, count)
Definition: ftmemory.h:235
#define FT_FACE(x)
Definition: ftobjs.h:599
#define FT_MIN(a, b)
Definition: ftobjs.h:70
#define FT_MAX(a, b)
Definition: ftobjs.h:71
#define FT_GLYPH_OWN_BITMAP
Definition: ftobjs.h:423
ft_glyphslot_alloc_bitmap(FT_GlyphSlot slot, FT_ULong size)
Definition: ftobjs.c:515
ft_glyphslot_set_bitmap(FT_GlyphSlot slot, FT_Byte *buffer)
Definition: ftobjs.c:503
#define FT_FRAME_RELEASE(bytes)
Definition: ftstream.h:551
#define FT_NEXT_USHORT(buffer)
Definition: ftstream.h:233
#define FT_FRAME_EXTRACT(size, bytes)
Definition: ftstream.h:545
#define FT_NEXT_ULONG(buffer)
Definition: ftstream.h:245
typedefFT_BEGIN_HEADER struct FT_MemoryRec_ * FT_Memory
Definition: ftsystem.h:65
FT_BEGIN_HEADER typedef unsigned char FT_Bool
Definition: fttypes.h:108
unsigned long FT_ULong
Definition: fttypes.h:253
unsigned char FT_Byte
Definition: fttypes.h:154
int FT_Error
Definition: fttypes.h:299
unsigned short FT_UShort
Definition: fttypes.h:209
unsigned int FT_UInt
Definition: fttypes.h:231
signed int FT_Int
Definition: fttypes.h:220
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLclampf GLclampf GLclampf alpha
Definition: gl.h:1740
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLint GLint GLsizei width
Definition: gl.h:1546
GLdouble GLdouble GLdouble GLdouble q
Definition: gl.h:2063
GLenum src
Definition: glext.h:6340
GLsizeiptr size
Definition: glext.h:5919
GLintptr offset
Definition: glext.h:5920
GLenum GLuint GLint GLenum face
Definition: glext.h:7025
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLenum GLenum dst
Definition: glext.h:6340
GLboolean GLboolean g
Definition: glext.h:6204
GLfloat GLfloat p
Definition: glext.h:8902
#define b
Definition: ke_i.h:79
if(dx< 0)
Definition: linetemp.h:194
#define error(str)
Definition: mkdosfs.c:1605
static char memory[1024 *256]
Definition: process.c:116
#define min(a, b)
Definition: monoChain.cc:55
f_args fa
Definition: format.c:280
LOCAL int table_size
Definition: write.c:65
unsigned short num_grays
Definition: ftimage.h:267
unsigned int width
Definition: ftimage.h:264
unsigned char * buffer
Definition: ftimage.h:266
unsigned char pixel_mode
Definition: ftimage.h:268
unsigned int rows
Definition: ftimage.h:263
int pitch
Definition: ftimage.h:265
FT_Int bitmap_top
Definition: freetype.h:1894
FT_Int bitmap_left
Definition: freetype.h:1893
FT_Bitmap bitmap
Definition: freetype.h:1892
FT_Slot_Internal internal
Definition: freetype.h:1909
FT_Glyph_Format format
Definition: freetype.h:1890
Definition: parse.h:23
#define max(a, b)
Definition: svc.c:63
int _tt_colr_dummy
Definition: ttcolr.c:447
tt_face_free_colr(TT_Face face)
FT_BEGIN_HEADER tt_face_load_colr(TT_Face face, FT_Stream stream)
tt_face_get_colr_layer(TT_Face face, FT_UInt base_glyph, FT_UInt *aglyph_index, FT_UInt *acolor_index, FT_LayerIterator *iterator)
tt_face_colr_blend_layer(TT_Face face, FT_UInt color_index, FT_GlyphSlot dstSlot, FT_GlyphSlot srcSlot)
#define TTAG_COLR
Definition: tttags.h:49