1 /**************************************************************************** 2 * 3 * ttcolr.c 4 * 5 * TrueType and OpenType colored glyph layer support (body). 6 * 7 * Copyright (C) 2018-2020 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 <freetype/internal/ftdebug.h> 31 #include <freetype/internal/ftstream.h> 32 #include <freetype/tttags.h> 33 #include <freetype/ftcolor.h> 34 35 36 #ifdef TT_CONFIG_OPTION_COLOR_LAYERS 37 38 #include "ttcolr.h" 39 40 41 /* NOTE: These are the table sizes calculated through the specs. */ 42 #define BASE_GLYPH_SIZE 6U 43 #define LAYER_SIZE 4U 44 #define COLR_HEADER_SIZE 14U 45 46 47 typedef struct BaseGlyphRecord_ 48 { 49 FT_UShort gid; 50 FT_UShort first_layer_index; 51 FT_UShort num_layers; 52 53 } BaseGlyphRecord; 54 55 56 typedef struct Colr_ 57 { 58 FT_UShort version; 59 FT_UShort num_base_glyphs; 60 FT_UShort num_layers; 61 62 FT_Byte* base_glyphs; 63 FT_Byte* layers; 64 65 /* The memory which backs up the `COLR' table. */ 66 void* table; 67 FT_ULong table_size; 68 69 } Colr; 70 71 72 /************************************************************************** 73 * 74 * The macro FT_COMPONENT is used in trace mode. It is an implicit 75 * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log 76 * messages during execution. 77 */ 78 #undef FT_COMPONENT 79 #define FT_COMPONENT ttcolr 80 81 82 FT_LOCAL_DEF( FT_Error ) tt_face_load_colr(TT_Face face,FT_Stream stream)83 tt_face_load_colr( TT_Face face, 84 FT_Stream stream ) 85 { 86 FT_Error error; 87 FT_Memory memory = face->root.memory; 88 89 FT_Byte* table = NULL; 90 FT_Byte* p = NULL; 91 92 Colr* colr = NULL; 93 94 FT_ULong base_glyph_offset, layer_offset; 95 FT_ULong table_size; 96 97 98 /* `COLR' always needs `CPAL' */ 99 if ( !face->cpal ) 100 return FT_THROW( Invalid_File_Format ); 101 102 error = face->goto_table( face, TTAG_COLR, stream, &table_size ); 103 if ( error ) 104 goto NoColr; 105 106 if ( table_size < COLR_HEADER_SIZE ) 107 goto InvalidTable; 108 109 if ( FT_FRAME_EXTRACT( table_size, table ) ) 110 goto NoColr; 111 112 p = table; 113 114 if ( FT_NEW( colr ) ) 115 goto NoColr; 116 117 colr->version = FT_NEXT_USHORT( p ); 118 if ( colr->version != 0 ) 119 goto InvalidTable; 120 121 colr->num_base_glyphs = FT_NEXT_USHORT( p ); 122 base_glyph_offset = FT_NEXT_ULONG( p ); 123 124 if ( base_glyph_offset >= table_size ) 125 goto InvalidTable; 126 if ( colr->num_base_glyphs * BASE_GLYPH_SIZE > 127 table_size - base_glyph_offset ) 128 goto InvalidTable; 129 130 layer_offset = FT_NEXT_ULONG( p ); 131 colr->num_layers = FT_NEXT_USHORT( p ); 132 133 if ( layer_offset >= table_size ) 134 goto InvalidTable; 135 if ( colr->num_layers * LAYER_SIZE > table_size - layer_offset ) 136 goto InvalidTable; 137 138 colr->base_glyphs = (FT_Byte*)( table + base_glyph_offset ); 139 colr->layers = (FT_Byte*)( table + layer_offset ); 140 colr->table = table; 141 colr->table_size = table_size; 142 143 face->colr = colr; 144 145 return FT_Err_Ok; 146 147 InvalidTable: 148 error = FT_THROW( Invalid_Table ); 149 150 NoColr: 151 FT_FRAME_RELEASE( table ); 152 FT_FREE( colr ); 153 154 return error; 155 } 156 157 158 FT_LOCAL_DEF( void ) tt_face_free_colr(TT_Face face)159 tt_face_free_colr( TT_Face face ) 160 { 161 FT_Stream stream = face->root.stream; 162 FT_Memory memory = face->root.memory; 163 164 Colr* colr = (Colr*)face->colr; 165 166 167 if ( colr ) 168 { 169 FT_FRAME_RELEASE( colr->table ); 170 FT_FREE( colr ); 171 } 172 } 173 174 175 static FT_Bool find_base_glyph_record(FT_Byte * base_glyph_begin,FT_Int num_base_glyph,FT_UInt glyph_id,BaseGlyphRecord * record)176 find_base_glyph_record( FT_Byte* base_glyph_begin, 177 FT_Int num_base_glyph, 178 FT_UInt glyph_id, 179 BaseGlyphRecord* record ) 180 { 181 FT_Int min = 0; 182 FT_Int max = num_base_glyph - 1; 183 184 185 while ( min <= max ) 186 { 187 FT_Int mid = min + ( max - min ) / 2; 188 FT_Byte* p = base_glyph_begin + mid * BASE_GLYPH_SIZE; 189 190 FT_UShort gid = FT_NEXT_USHORT( p ); 191 192 193 if ( gid < glyph_id ) 194 min = mid + 1; 195 else if (gid > glyph_id ) 196 max = mid - 1; 197 else 198 { 199 record->gid = gid; 200 record->first_layer_index = FT_NEXT_USHORT( p ); 201 record->num_layers = FT_NEXT_USHORT( p ); 202 203 return 1; 204 } 205 } 206 207 return 0; 208 } 209 210 211 FT_LOCAL_DEF( FT_Bool ) tt_face_get_colr_layer(TT_Face face,FT_UInt base_glyph,FT_UInt * aglyph_index,FT_UInt * acolor_index,FT_LayerIterator * iterator)212 tt_face_get_colr_layer( TT_Face face, 213 FT_UInt base_glyph, 214 FT_UInt *aglyph_index, 215 FT_UInt *acolor_index, 216 FT_LayerIterator* iterator ) 217 { 218 Colr* colr = (Colr*)face->colr; 219 BaseGlyphRecord glyph_record; 220 221 222 if ( !colr ) 223 return 0; 224 225 if ( !iterator->p ) 226 { 227 FT_ULong offset; 228 229 230 /* first call to function */ 231 iterator->layer = 0; 232 233 if ( !find_base_glyph_record( colr->base_glyphs, 234 colr->num_base_glyphs, 235 base_glyph, 236 &glyph_record ) ) 237 return 0; 238 239 if ( glyph_record.num_layers ) 240 iterator->num_layers = glyph_record.num_layers; 241 else 242 return 0; 243 244 offset = LAYER_SIZE * glyph_record.first_layer_index; 245 if ( offset + LAYER_SIZE * glyph_record.num_layers > colr->table_size ) 246 return 0; 247 248 iterator->p = colr->layers + offset; 249 } 250 251 if ( iterator->layer >= iterator->num_layers ) 252 return 0; 253 254 *aglyph_index = FT_NEXT_USHORT( iterator->p ); 255 *acolor_index = FT_NEXT_USHORT( iterator->p ); 256 257 if ( *aglyph_index >= (FT_UInt)( FT_FACE( face )->num_glyphs ) || 258 ( *acolor_index != 0xFFFF && 259 *acolor_index >= face->palette_data.num_palette_entries ) ) 260 return 0; 261 262 iterator->layer++; 263 264 return 1; 265 } 266 267 268 FT_LOCAL_DEF( FT_Error ) tt_face_colr_blend_layer(TT_Face face,FT_UInt color_index,FT_GlyphSlot dstSlot,FT_GlyphSlot srcSlot)269 tt_face_colr_blend_layer( TT_Face face, 270 FT_UInt color_index, 271 FT_GlyphSlot dstSlot, 272 FT_GlyphSlot srcSlot ) 273 { 274 FT_Error error; 275 276 FT_UInt x, y; 277 FT_Byte b, g, r, alpha; 278 279 FT_ULong size; 280 FT_Byte* src; 281 FT_Byte* dst; 282 283 284 if ( !dstSlot->bitmap.buffer ) 285 { 286 /* Initialize destination of color bitmap */ 287 /* with the size of first component. */ 288 dstSlot->bitmap_left = srcSlot->bitmap_left; 289 dstSlot->bitmap_top = srcSlot->bitmap_top; 290 291 dstSlot->bitmap.width = srcSlot->bitmap.width; 292 dstSlot->bitmap.rows = srcSlot->bitmap.rows; 293 dstSlot->bitmap.pixel_mode = FT_PIXEL_MODE_BGRA; 294 dstSlot->bitmap.pitch = (int)dstSlot->bitmap.width * 4; 295 dstSlot->bitmap.num_grays = 256; 296 297 size = dstSlot->bitmap.rows * (unsigned int)dstSlot->bitmap.pitch; 298 299 error = ft_glyphslot_alloc_bitmap( dstSlot, size ); 300 if ( error ) 301 return error; 302 303 FT_MEM_ZERO( dstSlot->bitmap.buffer, size ); 304 } 305 else 306 { 307 /* Resize destination if needed such that new component fits. */ 308 FT_Int x_min, x_max, y_min, y_max; 309 310 311 x_min = FT_MIN( dstSlot->bitmap_left, srcSlot->bitmap_left ); 312 x_max = FT_MAX( dstSlot->bitmap_left + (FT_Int)dstSlot->bitmap.width, 313 srcSlot->bitmap_left + (FT_Int)srcSlot->bitmap.width ); 314 315 y_min = FT_MIN( dstSlot->bitmap_top - (FT_Int)dstSlot->bitmap.rows, 316 srcSlot->bitmap_top - (FT_Int)srcSlot->bitmap.rows ); 317 y_max = FT_MAX( dstSlot->bitmap_top, srcSlot->bitmap_top ); 318 319 if ( x_min != dstSlot->bitmap_left || 320 x_max != dstSlot->bitmap_left + (FT_Int)dstSlot->bitmap.width || 321 y_min != dstSlot->bitmap_top - (FT_Int)dstSlot->bitmap.rows || 322 y_max != dstSlot->bitmap_top ) 323 { 324 FT_Memory memory = face->root.memory; 325 326 FT_UInt width = (FT_UInt)( x_max - x_min ); 327 FT_UInt rows = (FT_UInt)( y_max - y_min ); 328 FT_UInt pitch = width * 4; 329 330 FT_Byte* buf = NULL; 331 FT_Byte* p; 332 FT_Byte* q; 333 334 335 size = rows * pitch; 336 if ( FT_ALLOC( buf, size ) ) 337 return error; 338 339 p = dstSlot->bitmap.buffer; 340 q = buf + 341 (int)pitch * ( y_max - dstSlot->bitmap_top ) + 342 4 * ( dstSlot->bitmap_left - x_min ); 343 344 for ( y = 0; y < dstSlot->bitmap.rows; y++ ) 345 { 346 FT_MEM_COPY( q, p, dstSlot->bitmap.width * 4 ); 347 348 p += dstSlot->bitmap.pitch; 349 q += pitch; 350 } 351 352 ft_glyphslot_set_bitmap( dstSlot, buf ); 353 354 dstSlot->bitmap_top = y_max; 355 dstSlot->bitmap_left = x_min; 356 357 dstSlot->bitmap.width = width; 358 dstSlot->bitmap.rows = rows; 359 dstSlot->bitmap.pitch = (int)pitch; 360 361 dstSlot->internal->flags |= FT_GLYPH_OWN_BITMAP; 362 dstSlot->format = FT_GLYPH_FORMAT_BITMAP; 363 } 364 } 365 366 if ( color_index == 0xFFFF ) 367 { 368 if ( face->have_foreground_color ) 369 { 370 b = face->foreground_color.blue; 371 g = face->foreground_color.green; 372 r = face->foreground_color.red; 373 alpha = face->foreground_color.alpha; 374 } 375 else 376 { 377 if ( face->palette_data.palette_flags && 378 ( face->palette_data.palette_flags[face->palette_index] & 379 FT_PALETTE_FOR_DARK_BACKGROUND ) ) 380 { 381 /* white opaque */ 382 b = 0xFF; 383 g = 0xFF; 384 r = 0xFF; 385 alpha = 0xFF; 386 } 387 else 388 { 389 /* black opaque */ 390 b = 0x00; 391 g = 0x00; 392 r = 0x00; 393 alpha = 0xFF; 394 } 395 } 396 } 397 else 398 { 399 b = face->palette[color_index].blue; 400 g = face->palette[color_index].green; 401 r = face->palette[color_index].red; 402 alpha = face->palette[color_index].alpha; 403 } 404 405 /* XXX Convert if srcSlot.bitmap is not grey? */ 406 src = srcSlot->bitmap.buffer; 407 dst = dstSlot->bitmap.buffer + 408 dstSlot->bitmap.pitch * ( dstSlot->bitmap_top - srcSlot->bitmap_top ) + 409 4 * ( srcSlot->bitmap_left - dstSlot->bitmap_left ); 410 411 for ( y = 0; y < srcSlot->bitmap.rows; y++ ) 412 { 413 for ( x = 0; x < srcSlot->bitmap.width; x++ ) 414 { 415 int aa = src[x]; 416 int fa = alpha * aa / 255; 417 418 int fb = b * fa / 255; 419 int fg = g * fa / 255; 420 int fr = r * fa / 255; 421 422 int ba2 = 255 - fa; 423 424 int bb = dst[4 * x + 0]; 425 int bg = dst[4 * x + 1]; 426 int br = dst[4 * x + 2]; 427 int ba = dst[4 * x + 3]; 428 429 430 dst[4 * x + 0] = (FT_Byte)( bb * ba2 / 255 + fb ); 431 dst[4 * x + 1] = (FT_Byte)( bg * ba2 / 255 + fg ); 432 dst[4 * x + 2] = (FT_Byte)( br * ba2 / 255 + fr ); 433 dst[4 * x + 3] = (FT_Byte)( ba * ba2 / 255 + fa ); 434 } 435 436 src += srcSlot->bitmap.pitch; 437 dst += dstSlot->bitmap.pitch; 438 } 439 440 return FT_Err_Ok; 441 } 442 443 #else /* !TT_CONFIG_OPTION_COLOR_LAYERS */ 444 445 /* ANSI C doesn't like empty source files */ 446 typedef int _tt_colr_dummy; 447 448 #endif /* !TT_CONFIG_OPTION_COLOR_LAYERS */ 449 450 /* EOF */ 451