Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright  2011,2012  Google, Inc.
      3  * Copyright  2018  Ebrahim Byagowi
      4  *
      5  *  This is part of HarfBuzz, a text shaping library.
      6  *
      7  * Permission is hereby granted, without written agreement and without
      8  * license or royalty fees, to use, copy, modify, and distribute this
      9  * software and its documentation for any purpose, provided that the
     10  * above copyright notice and the following two paragraphs appear in
     11  * all copies of this software.
     12  *
     13  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
     14  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
     15  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
     16  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
     17  * DAMAGE.
     18  *
     19  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
     20  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
     21  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
     22  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
     23  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
     24  *
     25  * Google Author(s): Behdad Esfahbod
     26  */
     27 
     28 #ifndef HB_OT_OS2_TABLE_HH
     29 #define HB_OT_OS2_TABLE_HH
     30 
     31 #include "hb-open-type.hh"
     32 #include "hb-ot-os2-unicode-ranges.hh"
     33 
     34 #include "hb-set.hh"
     35 
     36 /*
     37  * OS/2 and Windows Metrics
     38  * https://docs.microsoft.com/en-us/typography/opentype/spec/os2
     39  */
     40 #define HB_OT_TAG_OS2 HB_TAG('O','S','/','2')
     41 
     42 
     43 namespace OT {
     44 
     45 struct OS2V1Tail
     46 {
     47   bool sanitize (hb_sanitize_context_t *c) const
     48   {
     49     TRACE_SANITIZE (this);
     50     return_trace (c->check_struct (this));
     51   }
     52 
     53   public:
     54   HBUINT32	ulCodePageRange1;
     55   HBUINT32	ulCodePageRange2;
     56   public:
     57   DEFINE_SIZE_STATIC (8);
     58 };
     59 
     60 struct OS2V2Tail
     61 {
     62   bool sanitize (hb_sanitize_context_t *c) const
     63   {
     64     TRACE_SANITIZE (this);
     65     return_trace (c->check_struct (this));
     66   }
     67 
     68   public:
     69   HBINT16	sxHeight;
     70   HBINT16	sCapHeight;
     71   HBUINT16	usDefaultChar;
     72   HBUINT16	usBreakChar;
     73   HBUINT16	usMaxContext;
     74   public:
     75   DEFINE_SIZE_STATIC (10);
     76 };
     77 
     78 struct OS2V5Tail
     79 {
     80   bool sanitize (hb_sanitize_context_t *c) const
     81   {
     82     TRACE_SANITIZE (this);
     83     return_trace (c->check_struct (this));
     84   }
     85 
     86   public:
     87   HBUINT16	usLowerOpticalPointSize;
     88   HBUINT16	usUpperOpticalPointSize;
     89   public:
     90   DEFINE_SIZE_STATIC (4);
     91 };
     92 
     93 struct OS2
     94 {
     95   enum { tableTag = HB_OT_TAG_OS2 };
     96 
     97   bool has_data () const { return this != &Null (OS2); }
     98 
     99   const OS2V1Tail &v1 () const { return version >= 1 ? v1X : Null (OS2V1Tail); }
    100   const OS2V2Tail &v2 () const { return version >= 2 ? v2X : Null (OS2V2Tail); }
    101   const OS2V5Tail &v5 () const { return version >= 5 ? v5X : Null (OS2V5Tail); }
    102 
    103   enum selection_flag_t {
    104     ITALIC		= 1u<<0,
    105     UNDERSCORE		= 1u<<1,
    106     NEGATIVE		= 1u<<2,
    107     OUTLINED		= 1u<<3,
    108     STRIKEOUT		= 1u<<4,
    109     BOLD		= 1u<<5,
    110     REGULAR		= 1u<<6,
    111     USE_TYPO_METRICS	= 1u<<7,
    112     WWS			= 1u<<8,
    113     OBLIQUE		= 1u<<9
    114   };
    115 
    116   bool is_italic () const       { return fsSelection & ITALIC; }
    117   bool is_oblique () const      { return fsSelection & OBLIQUE; }
    118   bool is_typo_metrics () const { return fsSelection & USE_TYPO_METRICS; }
    119 
    120   enum width_class_t {
    121     FWIDTH_ULTRA_CONDENSED	= 1, /* 50% */
    122     FWIDTH_EXTRA_CONDENSED	= 2, /* 62.5% */
    123     FWIDTH_CONDENSED		= 3, /* 75% */
    124     FWIDTH_SEMI_CONDENSED	= 4, /* 87.5% */
    125     FWIDTH_NORMAL		= 5, /* 100% */
    126     FWIDTH_SEMI_EXPANDED	= 6, /* 112.5% */
    127     FWIDTH_EXPANDED		= 7, /* 125% */
    128     FWIDTH_EXTRA_EXPANDED	= 8, /* 150% */
    129     FWIDTH_ULTRA_EXPANDED	= 9  /* 200% */
    130   };
    131 
    132   float get_width () const
    133   {
    134     switch (usWidthClass) {
    135     case FWIDTH_ULTRA_CONDENSED:return 50.f;
    136     case FWIDTH_EXTRA_CONDENSED:return 62.5f;
    137     case FWIDTH_CONDENSED:	return 75.f;
    138     case FWIDTH_SEMI_CONDENSED:	return 87.5f;
    139     default:
    140     case FWIDTH_NORMAL:		return 100.f;
    141     case FWIDTH_SEMI_EXPANDED:	return 112.5f;
    142     case FWIDTH_EXPANDED:	return 125.f;
    143     case FWIDTH_EXTRA_EXPANDED:	return 150.f;
    144     case FWIDTH_ULTRA_EXPANDED:	return 200.f;
    145     }
    146   }
    147 
    148   bool subset (hb_subset_plan_t *plan) const
    149   {
    150     hb_blob_t *os2_blob = hb_sanitize_context_t ().reference_table<OS2> (plan->source);
    151     hb_blob_t *os2_prime_blob = hb_blob_create_sub_blob (os2_blob, 0, -1);
    152     // TODO(grieger): move to hb_blob_copy_writable_or_fail
    153     hb_blob_destroy (os2_blob);
    154 
    155     OS2 *os2_prime = (OS2 *) hb_blob_get_data_writable (os2_prime_blob, nullptr);
    156     if (unlikely (!os2_prime)) {
    157       hb_blob_destroy (os2_prime_blob);
    158       return false;
    159     }
    160 
    161     uint16_t min_cp, max_cp;
    162     find_min_and_max_codepoint (plan->unicodes, &min_cp, &max_cp);
    163     os2_prime->usFirstCharIndex.set (min_cp);
    164     os2_prime->usLastCharIndex.set (max_cp);
    165 
    166     _update_unicode_ranges (plan->unicodes, os2_prime->ulUnicodeRange);
    167     bool result = plan->add_table (HB_OT_TAG_OS2, os2_prime_blob);
    168 
    169     hb_blob_destroy (os2_prime_blob);
    170     return result;
    171   }
    172 
    173   void _update_unicode_ranges (const hb_set_t *codepoints,
    174 			       HBUINT32 ulUnicodeRange[4]) const
    175   {
    176     for (unsigned int i = 0; i < 4; i++)
    177       ulUnicodeRange[i].set (0);
    178 
    179     hb_codepoint_t cp = HB_SET_VALUE_INVALID;
    180     while (codepoints->next (&cp)) {
    181       unsigned int bit = _hb_ot_os2_get_unicode_range_bit (cp);
    182       if (bit < 128)
    183       {
    184 	unsigned int block = bit / 32;
    185 	unsigned int bit_in_block = bit % 32;
    186 	unsigned int mask = 1 << bit_in_block;
    187 	ulUnicodeRange[block].set (ulUnicodeRange[block] | mask);
    188       }
    189       if (cp >= 0x10000 && cp <= 0x110000)
    190       {
    191 	/* the spec says that bit 57 ("Non Plane 0") implies that there's
    192 	   at least one codepoint beyond the BMP; so I also include all
    193 	   the non-BMP codepoints here */
    194 	ulUnicodeRange[1].set (ulUnicodeRange[1] | (1 << 25));
    195       }
    196     }
    197   }
    198 
    199   static void find_min_and_max_codepoint (const hb_set_t *codepoints,
    200 						 uint16_t *min_cp, /* OUT */
    201 						 uint16_t *max_cp  /* OUT */)
    202   {
    203     *min_cp = codepoints->get_min ();
    204     *max_cp = codepoints->get_max ();
    205   }
    206 
    207   enum font_page_t {
    208     HEBREW_FONT_PAGE		= 0xB100, // Hebrew Windows 3.1 font page
    209     SIMP_ARABIC_FONT_PAGE	= 0xB200, // Simplified Arabic Windows 3.1 font page
    210     TRAD_ARABIC_FONT_PAGE	= 0xB300, // Traditional Arabic Windows 3.1 font page
    211     OEM_ARABIC_FONT_PAGE	= 0xB400, // OEM Arabic Windows 3.1 font page
    212     SIMP_FARSI_FONT_PAGE	= 0xBA00, // Simplified Farsi Windows 3.1 font page
    213     TRAD_FARSI_FONT_PAGE	= 0xBB00, // Traditional Farsi Windows 3.1 font page
    214     THAI_FONT_PAGE		= 0xDE00  // Thai Windows 3.1 font page
    215   };
    216 
    217   // https://github.com/Microsoft/Font-Validator/blob/520aaae/OTFontFileVal/val_OS2.cs#L644-L681
    218   font_page_t get_font_page () const
    219   { return (font_page_t) (version == 0 ? fsSelection & 0xFF00 : 0); }
    220 
    221   bool sanitize (hb_sanitize_context_t *c) const
    222   {
    223     TRACE_SANITIZE (this);
    224     if (unlikely (!c->check_struct (this))) return_trace (false);
    225     if (unlikely (version >= 1 && !v1X.sanitize (c))) return_trace (false);
    226     if (unlikely (version >= 2 && !v2X.sanitize (c))) return_trace (false);
    227     if (unlikely (version >= 5 && !v5X.sanitize (c))) return_trace (false);
    228     return_trace (true);
    229   }
    230 
    231   public:
    232   HBUINT16	version;
    233   HBINT16	xAvgCharWidth;
    234   HBUINT16	usWeightClass;
    235   HBUINT16	usWidthClass;
    236   HBUINT16	fsType;
    237   HBINT16	ySubscriptXSize;
    238   HBINT16	ySubscriptYSize;
    239   HBINT16	ySubscriptXOffset;
    240   HBINT16	ySubscriptYOffset;
    241   HBINT16	ySuperscriptXSize;
    242   HBINT16	ySuperscriptYSize;
    243   HBINT16	ySuperscriptXOffset;
    244   HBINT16	ySuperscriptYOffset;
    245   HBINT16	yStrikeoutSize;
    246   HBINT16	yStrikeoutPosition;
    247   HBINT16	sFamilyClass;
    248   HBUINT8	panose[10];
    249   HBUINT32	ulUnicodeRange[4];
    250   Tag		achVendID;
    251   HBUINT16	fsSelection;
    252   HBUINT16	usFirstCharIndex;
    253   HBUINT16	usLastCharIndex;
    254   HBINT16	sTypoAscender;
    255   HBINT16	sTypoDescender;
    256   HBINT16	sTypoLineGap;
    257   HBUINT16	usWinAscent;
    258   HBUINT16	usWinDescent;
    259   OS2V1Tail	v1X;
    260   OS2V2Tail	v2X;
    261   OS2V5Tail	v5X;
    262   public:
    263   DEFINE_SIZE_MIN (78);
    264 };
    265 
    266 } /* namespace OT */
    267 
    268 
    269 #endif /* HB_OT_OS2_TABLE_HH */
    270