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 <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   {
  59     FT_UShort  version;
  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;
  68     FT_ULong  table_size;
  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 
  83   FT_LOCAL_DEF( FT_Error )
  84   tt_face_load_colr( TT_Face    face,
  85                      FT_Stream  stream )
  86   {
  87     FT_Error   error;
  88     FT_Memory  memory = face->root.memory;
  89 
  90     FT_Byte*  table = NULL;
  91     FT_Byte*  p     = NULL;
  92 
  93     Colr*  colr = NULL;
  94 
  95     FT_ULong  base_glyph_offset, layer_offset;
  96     FT_ULong  table_size;
  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 
 110     if ( FT_FRAME_EXTRACT( table_size, table ) )
 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:
 152     FT_FRAME_RELEASE( table );
 153     FT_FREE( colr );
 154 
 155     return error;
 156   }
 157 
 158 
 159   FT_LOCAL_DEF( void )
 160   tt_face_free_colr( TT_Face  face )
 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 
 212   FT_LOCAL_DEF( FT_Bool )
 213   tt_face_get_colr_layer( TT_Face            face,
 214                           FT_UInt            base_glyph,
 215                           FT_UInt           *aglyph_index,
 216                           FT_UInt           *acolor_index,
 217                           FT_LayerIterator*  iterator )
 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     {
 228       FT_ULong  offset;
 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 
 269   FT_LOCAL_DEF( FT_Error )
 270   tt_face_colr_blend_layer( TT_Face       face,
 271                             FT_UInt       color_index,
 272                             FT_GlyphSlot  dstSlot,
 273                             FT_GlyphSlot  srcSlot )
 274   {
 275     FT_Error  error;
 276 
 277     FT_UInt  x, y;
 278     FT_Byte  b, g, r, alpha;
 279 
 280     FT_ULong  size;
 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;
 294       dstSlot->bitmap.pixel_mode = FT_PIXEL_MODE_BGRA;
 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 
 300       error = ft_glyphslot_alloc_bitmap( dstSlot, size );
 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 
 362         dstSlot->internal->flags |= FT_GLYPH_OWN_BITMAP;
 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] &
 380                  FT_PALETTE_FOR_DARK_BACKGROUND                      ) )
 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 */