Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright  2011,2012,2013  Google, Inc.
      3  *
      4  *  This is part of HarfBuzz, a text shaping library.
      5  *
      6  * Permission is hereby granted, without written agreement and without
      7  * license or royalty fees, to use, copy, modify, and distribute this
      8  * software and its documentation for any purpose, provided that the
      9  * above copyright notice and the following two paragraphs appear in
     10  * all copies of this software.
     11  *
     12  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
     13  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
     14  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
     15  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
     16  * DAMAGE.
     17  *
     18  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
     19  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
     20  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
     21  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
     22  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
     23  *
     24  * Google Author(s): Behdad Esfahbod
     25  */
     26 
     27 #include "hb-private.hh"
     28 #include "hb-debug.hh"
     29 #define HB_SHAPER uniscribe
     30 #include "hb-shaper-impl-private.hh"
     31 
     32 #include <windows.h>
     33 #include <usp10.h>
     34 #include <rpc.h>
     35 
     36 #include "hb-uniscribe.h"
     37 
     38 #include "hb-open-file-private.hh"
     39 #include "hb-ot-name-table.hh"
     40 #include "hb-ot-tag.h"
     41 
     42 
     43 static inline uint16_t hb_uint16_swap (const uint16_t v)
     44 { return (v >> 8) | (v << 8); }
     45 static inline uint32_t hb_uint32_swap (const uint32_t v)
     46 { return (hb_uint16_swap (v) << 16) | hb_uint16_swap (v >> 16); }
     47 
     48 
     49 typedef HRESULT (WINAPI *SIOT) /*ScriptItemizeOpenType*/(
     50   const WCHAR *pwcInChars,
     51   int cInChars,
     52   int cMaxItems,
     53   const SCRIPT_CONTROL *psControl,
     54   const SCRIPT_STATE *psState,
     55   SCRIPT_ITEM *pItems,
     56   OPENTYPE_TAG *pScriptTags,
     57   int *pcItems
     58 );
     59 
     60 typedef HRESULT (WINAPI *SSOT) /*ScriptShapeOpenType*/(
     61   HDC hdc,
     62   SCRIPT_CACHE *psc,
     63   SCRIPT_ANALYSIS *psa,
     64   OPENTYPE_TAG tagScript,
     65   OPENTYPE_TAG tagLangSys,
     66   int *rcRangeChars,
     67   TEXTRANGE_PROPERTIES **rpRangeProperties,
     68   int cRanges,
     69   const WCHAR *pwcChars,
     70   int cChars,
     71   int cMaxGlyphs,
     72   WORD *pwLogClust,
     73   SCRIPT_CHARPROP *pCharProps,
     74   WORD *pwOutGlyphs,
     75   SCRIPT_GLYPHPROP *pOutGlyphProps,
     76   int *pcGlyphs
     77 );
     78 
     79 typedef HRESULT (WINAPI *SPOT) /*ScriptPlaceOpenType*/(
     80   HDC hdc,
     81   SCRIPT_CACHE *psc,
     82   SCRIPT_ANALYSIS *psa,
     83   OPENTYPE_TAG tagScript,
     84   OPENTYPE_TAG tagLangSys,
     85   int *rcRangeChars,
     86   TEXTRANGE_PROPERTIES **rpRangeProperties,
     87   int cRanges,
     88   const WCHAR *pwcChars,
     89   WORD *pwLogClust,
     90   SCRIPT_CHARPROP *pCharProps,
     91   int cChars,
     92   const WORD *pwGlyphs,
     93   const SCRIPT_GLYPHPROP *pGlyphProps,
     94   int cGlyphs,
     95   int *piAdvance,
     96   GOFFSET *pGoffset,
     97   ABC *pABC
     98 );
     99 
    100 
    101 /* Fallback implementations. */
    102 
    103 static HRESULT WINAPI
    104 hb_ScriptItemizeOpenType(
    105   const WCHAR *pwcInChars,
    106   int cInChars,
    107   int cMaxItems,
    108   const SCRIPT_CONTROL *psControl,
    109   const SCRIPT_STATE *psState,
    110   SCRIPT_ITEM *pItems,
    111   OPENTYPE_TAG *pScriptTags,
    112   int *pcItems
    113 )
    114 {
    115 {
    116   return ScriptItemize (pwcInChars,
    117 			cInChars,
    118 			cMaxItems,
    119 			psControl,
    120 			psState,
    121 			pItems,
    122 			pcItems);
    123 }
    124 }
    125 
    126 static HRESULT WINAPI
    127 hb_ScriptShapeOpenType(
    128   HDC hdc,
    129   SCRIPT_CACHE *psc,
    130   SCRIPT_ANALYSIS *psa,
    131   OPENTYPE_TAG tagScript,
    132   OPENTYPE_TAG tagLangSys,
    133   int *rcRangeChars,
    134   TEXTRANGE_PROPERTIES **rpRangeProperties,
    135   int cRanges,
    136   const WCHAR *pwcChars,
    137   int cChars,
    138   int cMaxGlyphs,
    139   WORD *pwLogClust,
    140   SCRIPT_CHARPROP *pCharProps,
    141   WORD *pwOutGlyphs,
    142   SCRIPT_GLYPHPROP *pOutGlyphProps,
    143   int *pcGlyphs
    144 )
    145 {
    146   SCRIPT_VISATTR *psva = (SCRIPT_VISATTR *) pOutGlyphProps;
    147   return ScriptShape (hdc,
    148 		      psc,
    149 		      pwcChars,
    150 		      cChars,
    151 		      cMaxGlyphs,
    152 		      psa,
    153 		      pwOutGlyphs,
    154 		      pwLogClust,
    155 		      psva,
    156 		      pcGlyphs);
    157 }
    158 
    159 static HRESULT WINAPI
    160 hb_ScriptPlaceOpenType(
    161   HDC hdc,
    162   SCRIPT_CACHE *psc,
    163   SCRIPT_ANALYSIS *psa,
    164   OPENTYPE_TAG tagScript,
    165   OPENTYPE_TAG tagLangSys,
    166   int *rcRangeChars,
    167   TEXTRANGE_PROPERTIES **rpRangeProperties,
    168   int cRanges,
    169   const WCHAR *pwcChars,
    170   WORD *pwLogClust,
    171   SCRIPT_CHARPROP *pCharProps,
    172   int cChars,
    173   const WORD *pwGlyphs,
    174   const SCRIPT_GLYPHPROP *pGlyphProps,
    175   int cGlyphs,
    176   int *piAdvance,
    177   GOFFSET *pGoffset,
    178   ABC *pABC
    179 )
    180 {
    181   SCRIPT_VISATTR *psva = (SCRIPT_VISATTR *) pGlyphProps;
    182   return ScriptPlace (hdc,
    183 		      psc,
    184 		      pwGlyphs,
    185 		      cGlyphs,
    186 		      psva,
    187 		      psa,
    188 		      piAdvance,
    189 		      pGoffset,
    190 		      pABC);
    191 }
    192 
    193 
    194 struct hb_uniscribe_shaper_funcs_t {
    195   SIOT ScriptItemizeOpenType;
    196   SSOT ScriptShapeOpenType;
    197   SPOT ScriptPlaceOpenType;
    198 
    199   inline void init (void)
    200   {
    201     HMODULE hinstLib;
    202     this->ScriptItemizeOpenType = nullptr;
    203     this->ScriptShapeOpenType   = nullptr;
    204     this->ScriptPlaceOpenType   = nullptr;
    205 
    206     hinstLib = GetModuleHandle (TEXT ("usp10.dll"));
    207     if (hinstLib)
    208     {
    209       this->ScriptItemizeOpenType = (SIOT) GetProcAddress (hinstLib, "ScriptItemizeOpenType");
    210       this->ScriptShapeOpenType   = (SSOT) GetProcAddress (hinstLib, "ScriptShapeOpenType");
    211       this->ScriptPlaceOpenType   = (SPOT) GetProcAddress (hinstLib, "ScriptPlaceOpenType");
    212     }
    213     if (!this->ScriptItemizeOpenType ||
    214 	!this->ScriptShapeOpenType   ||
    215 	!this->ScriptPlaceOpenType)
    216     {
    217       DEBUG_MSG (UNISCRIBE, nullptr, "OpenType versions of functions not found; falling back.");
    218       this->ScriptItemizeOpenType = hb_ScriptItemizeOpenType;
    219       this->ScriptShapeOpenType   = hb_ScriptShapeOpenType;
    220       this->ScriptPlaceOpenType   = hb_ScriptPlaceOpenType;
    221     }
    222   }
    223 };
    224 static hb_uniscribe_shaper_funcs_t *uniscribe_funcs;
    225 
    226 static inline void
    227 free_uniscribe_funcs (void)
    228 {
    229   free (uniscribe_funcs);
    230 }
    231 
    232 static hb_uniscribe_shaper_funcs_t *
    233 hb_uniscribe_shaper_get_funcs (void)
    234 {
    235 retry:
    236   hb_uniscribe_shaper_funcs_t *funcs = (hb_uniscribe_shaper_funcs_t *) hb_atomic_ptr_get (&uniscribe_funcs);
    237 
    238   if (unlikely (!funcs))
    239   {
    240     funcs = (hb_uniscribe_shaper_funcs_t *) calloc (1, sizeof (hb_uniscribe_shaper_funcs_t));
    241     if (unlikely (!funcs))
    242       return nullptr;
    243 
    244     funcs->init ();
    245 
    246     if (!hb_atomic_ptr_cmpexch (&uniscribe_funcs, nullptr, funcs)) {
    247       free (funcs);
    248       goto retry;
    249     }
    250 
    251 #ifdef HB_USE_ATEXIT
    252     atexit (free_uniscribe_funcs); /* First person registers atexit() callback. */
    253 #endif
    254   }
    255 
    256   return funcs;
    257 }
    258 
    259 
    260 struct active_feature_t {
    261   OPENTYPE_FEATURE_RECORD rec;
    262   unsigned int order;
    263 
    264   static int cmp (const void *pa, const void *pb) {
    265     const active_feature_t *a = (const active_feature_t *) pa;
    266     const active_feature_t *b = (const active_feature_t *) pb;
    267     return a->rec.tagFeature < b->rec.tagFeature ? -1 : a->rec.tagFeature > b->rec.tagFeature ? 1 :
    268 	   a->order < b->order ? -1 : a->order > b->order ? 1 :
    269 	   a->rec.lParameter < b->rec.lParameter ? -1 : a->rec.lParameter > b->rec.lParameter ? 1 :
    270 	   0;
    271   }
    272   bool operator== (const active_feature_t *f) {
    273     return cmp (this, f) == 0;
    274   }
    275 };
    276 
    277 struct feature_event_t {
    278   unsigned int index;
    279   bool start;
    280   active_feature_t feature;
    281 
    282   static int cmp (const void *pa, const void *pb) {
    283     const feature_event_t *a = (const feature_event_t *) pa;
    284     const feature_event_t *b = (const feature_event_t *) pb;
    285     return a->index < b->index ? -1 : a->index > b->index ? 1 :
    286 	   a->start < b->start ? -1 : a->start > b->start ? 1 :
    287 	   active_feature_t::cmp (&a->feature, &b->feature);
    288   }
    289 };
    290 
    291 struct range_record_t {
    292   TEXTRANGE_PROPERTIES props;
    293   unsigned int index_first; /* == start */
    294   unsigned int index_last;  /* == end - 1 */
    295 };
    296 
    297 HB_SHAPER_DATA_ENSURE_DEFINE(uniscribe, face)
    298 HB_SHAPER_DATA_ENSURE_DEFINE(uniscribe, font)
    299 
    300 
    301 /*
    302  * shaper face data
    303  */
    304 
    305 struct hb_uniscribe_shaper_face_data_t {
    306   HANDLE fh;
    307   hb_uniscribe_shaper_funcs_t *funcs;
    308   wchar_t face_name[LF_FACESIZE];
    309 };
    310 
    311 /* face_name should point to a wchar_t[LF_FACESIZE] object. */
    312 static void
    313 _hb_generate_unique_face_name (wchar_t *face_name, unsigned int *plen)
    314 {
    315   /* We'll create a private name for the font from a UUID using a simple,
    316    * somewhat base64-like encoding scheme */
    317   const char *enc = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-";
    318   UUID id;
    319   UuidCreate ((UUID*) &id);
    320   static_assert ((2 + 3 * (16/2) < LF_FACESIZE), "");
    321   unsigned int name_str_len = 0;
    322   face_name[name_str_len++] = 'F';
    323   face_name[name_str_len++] = '_';
    324   unsigned char *p = (unsigned char *) &id;
    325   for (unsigned int i = 0; i < 16; i += 2)
    326   {
    327     /* Spread the 16 bits from two bytes of the UUID across three chars of face_name,
    328      * using the bits in groups of 5,5,6 to select chars from enc.
    329      * This will generate 24 characters; with the 'F_' prefix we already provided,
    330      * the name will be 26 chars (plus the NUL terminator), so will always fit within
    331      * face_name (LF_FACESIZE = 32). */
    332     face_name[name_str_len++] = enc[p[i] >> 3];
    333     face_name[name_str_len++] = enc[((p[i] << 2) | (p[i + 1] >> 6)) & 0x1f];
    334     face_name[name_str_len++] = enc[p[i + 1] & 0x3f];
    335   }
    336   face_name[name_str_len] = 0;
    337   if (plen)
    338     *plen = name_str_len;
    339 }
    340 
    341 /* Destroys blob. */
    342 static hb_blob_t *
    343 _hb_rename_font (hb_blob_t *blob, wchar_t *new_name)
    344 {
    345   /* Create a copy of the font data, with the 'name' table replaced by a
    346    * table that names the font with our private F_* name created above.
    347    * For simplicity, we just append a new 'name' table and update the
    348    * sfnt directory; the original table is left in place, but unused.
    349    *
    350    * The new table will contain just 5 name IDs: family, style, unique,
    351    * full, PS. All of them point to the same name data with our unique name.
    352    */
    353 
    354   blob = OT::Sanitizer<OT::OpenTypeFontFile>::sanitize (blob);
    355 
    356   unsigned int length, new_length, name_str_len;
    357   const char *orig_sfnt_data = hb_blob_get_data (blob, &length);
    358 
    359   _hb_generate_unique_face_name (new_name, &name_str_len);
    360 
    361   static const uint16_t name_IDs[] = { 1, 2, 3, 4, 6 };
    362 
    363   unsigned int name_table_length = OT::name::min_size +
    364                                    ARRAY_LENGTH (name_IDs) * OT::NameRecord::static_size +
    365                                    name_str_len * 2; /* for name data in UTF16BE form */
    366   unsigned int name_table_offset = (length + 3) & ~3;
    367 
    368   new_length = name_table_offset + ((name_table_length + 3) & ~3);
    369   void *new_sfnt_data = calloc (1, new_length);
    370   if (!new_sfnt_data)
    371   {
    372     hb_blob_destroy (blob);
    373     return nullptr;
    374   }
    375 
    376   memcpy(new_sfnt_data, orig_sfnt_data, length);
    377 
    378   OT::name &name = OT::StructAtOffset<OT::name> (new_sfnt_data, name_table_offset);
    379   name.format.set (0);
    380   name.count.set (ARRAY_LENGTH (name_IDs));
    381   name.stringOffset.set (name.get_size ());
    382   for (unsigned int i = 0; i < ARRAY_LENGTH (name_IDs); i++)
    383   {
    384     OT::NameRecord &record = name.nameRecord[i];
    385     record.platformID.set (3);
    386     record.encodingID.set (1);
    387     record.languageID.set (0x0409u); /* English */
    388     record.nameID.set (name_IDs[i]);
    389     record.length.set (name_str_len * 2);
    390     record.offset.set (0);
    391   }
    392 
    393   /* Copy string data from new_name, converting wchar_t to UTF16BE. */
    394   unsigned char *p = &OT::StructAfter<unsigned char> (name);
    395   for (unsigned int i = 0; i < name_str_len; i++)
    396   {
    397     *p++ = new_name[i] >> 8;
    398     *p++ = new_name[i] & 0xff;
    399   }
    400 
    401   /* Adjust name table entry to point to new name table */
    402   const OT::OpenTypeFontFile &file = * (OT::OpenTypeFontFile *) (new_sfnt_data);
    403   unsigned int face_count = file.get_face_count ();
    404   for (unsigned int face_index = 0; face_index < face_count; face_index++)
    405   {
    406     /* Note: doing multiple edits (ie. TTC) can be unsafe.  There may be
    407      * toe-stepping.  But we don't really care. */
    408     const OT::OpenTypeFontFace &face = file.get_face (face_index);
    409     unsigned int index;
    410     if (face.find_table_index (HB_OT_TAG_name, &index))
    411     {
    412       OT::TableRecord &record = const_cast<OT::TableRecord &> (face.get_table (index));
    413       record.checkSum.set_for_data (&name, name_table_length);
    414       record.offset.set (name_table_offset);
    415       record.length.set (name_table_length);
    416     }
    417     else if (face_index == 0) /* Fail if first face doesn't have 'name' table. */
    418     {
    419       free (new_sfnt_data);
    420       hb_blob_destroy (blob);
    421       return nullptr;
    422     }
    423   }
    424 
    425   /* The checkSumAdjustment field in the 'head' table is now wrong,
    426    * but that doesn't actually seem to cause any problems so we don't
    427    * bother. */
    428 
    429   hb_blob_destroy (blob);
    430   return hb_blob_create ((const char *) new_sfnt_data, new_length,
    431 			 HB_MEMORY_MODE_WRITABLE, nullptr, free);
    432 }
    433 
    434 hb_uniscribe_shaper_face_data_t *
    435 _hb_uniscribe_shaper_face_data_create (hb_face_t *face)
    436 {
    437   hb_uniscribe_shaper_face_data_t *data = (hb_uniscribe_shaper_face_data_t *) calloc (1, sizeof (hb_uniscribe_shaper_face_data_t));
    438   if (unlikely (!data))
    439     return nullptr;
    440 
    441   data->funcs = hb_uniscribe_shaper_get_funcs ();
    442   if (unlikely (!data->funcs))
    443   {
    444     free (data);
    445     return nullptr;
    446   }
    447 
    448   hb_blob_t *blob = hb_face_reference_blob (face);
    449   if (unlikely (!hb_blob_get_length (blob)))
    450     DEBUG_MSG (UNISCRIBE, face, "Face has empty blob");
    451 
    452   blob = _hb_rename_font (blob, data->face_name);
    453   if (unlikely (!blob))
    454   {
    455     free (data);
    456     return nullptr;
    457   }
    458 
    459   DWORD num_fonts_installed;
    460   data->fh = AddFontMemResourceEx ((void *) hb_blob_get_data (blob, nullptr),
    461 				   hb_blob_get_length (blob),
    462 				   0, &num_fonts_installed);
    463   if (unlikely (!data->fh))
    464   {
    465     DEBUG_MSG (UNISCRIBE, face, "Face AddFontMemResourceEx() failed");
    466     free (data);
    467     return nullptr;
    468   }
    469 
    470   return data;
    471 }
    472 
    473 void
    474 _hb_uniscribe_shaper_face_data_destroy (hb_uniscribe_shaper_face_data_t *data)
    475 {
    476   RemoveFontMemResourceEx (data->fh);
    477   free (data);
    478 }
    479 
    480 
    481 /*
    482  * shaper font data
    483  */
    484 
    485 struct hb_uniscribe_shaper_font_data_t {
    486   HDC hdc;
    487   LOGFONTW log_font;
    488   HFONT hfont;
    489   SCRIPT_CACHE script_cache;
    490   double x_mult, y_mult; /* From LOGFONT space to HB space. */
    491 };
    492 
    493 static bool
    494 populate_log_font (LOGFONTW  *lf,
    495 		   hb_font_t *font,
    496 		   unsigned int font_size)
    497 {
    498   memset (lf, 0, sizeof (*lf));
    499   lf->lfHeight = - (int) font_size;
    500   lf->lfCharSet = DEFAULT_CHARSET;
    501 
    502   hb_face_t *face = font->face;
    503   hb_uniscribe_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
    504 
    505   memcpy (lf->lfFaceName, face_data->face_name, sizeof (lf->lfFaceName));
    506 
    507   return true;
    508 }
    509 
    510 hb_uniscribe_shaper_font_data_t *
    511 _hb_uniscribe_shaper_font_data_create (hb_font_t *font)
    512 {
    513   if (unlikely (!hb_uniscribe_shaper_face_data_ensure (font->face))) return nullptr;
    514 
    515   hb_uniscribe_shaper_font_data_t *data = (hb_uniscribe_shaper_font_data_t *) calloc (1, sizeof (hb_uniscribe_shaper_font_data_t));
    516   if (unlikely (!data))
    517     return nullptr;
    518 
    519   int font_size = font->face->get_upem (); /* Default... */
    520   /* No idea if the following is even a good idea. */
    521   if (font->y_ppem)
    522     font_size = font->y_ppem;
    523 
    524   if (font_size < 0)
    525     font_size = -font_size;
    526   data->x_mult = (double) font->x_scale / font_size;
    527   data->y_mult = (double) font->y_scale / font_size;
    528 
    529   data->hdc = GetDC (nullptr);
    530 
    531   if (unlikely (!populate_log_font (&data->log_font, font, font_size))) {
    532     DEBUG_MSG (UNISCRIBE, font, "Font populate_log_font() failed");
    533     _hb_uniscribe_shaper_font_data_destroy (data);
    534     return nullptr;
    535   }
    536 
    537   data->hfont = CreateFontIndirectW (&data->log_font);
    538   if (unlikely (!data->hfont)) {
    539     DEBUG_MSG (UNISCRIBE, font, "Font CreateFontIndirectW() failed");
    540     _hb_uniscribe_shaper_font_data_destroy (data);
    541      return nullptr;
    542   }
    543 
    544   if (!SelectObject (data->hdc, data->hfont)) {
    545     DEBUG_MSG (UNISCRIBE, font, "Font SelectObject() failed");
    546     _hb_uniscribe_shaper_font_data_destroy (data);
    547      return nullptr;
    548   }
    549 
    550   return data;
    551 }
    552 
    553 void
    554 _hb_uniscribe_shaper_font_data_destroy (hb_uniscribe_shaper_font_data_t *data)
    555 {
    556   if (data->hdc)
    557     ReleaseDC (nullptr, data->hdc);
    558   if (data->hfont)
    559     DeleteObject (data->hfont);
    560   if (data->script_cache)
    561     ScriptFreeCache (&data->script_cache);
    562   free (data);
    563 }
    564 
    565 LOGFONTW *
    566 hb_uniscribe_font_get_logfontw (hb_font_t *font)
    567 {
    568   if (unlikely (!hb_uniscribe_shaper_font_data_ensure (font))) return nullptr;
    569   hb_uniscribe_shaper_font_data_t *font_data =  HB_SHAPER_DATA_GET (font);
    570   return &font_data->log_font;
    571 }
    572 
    573 HFONT
    574 hb_uniscribe_font_get_hfont (hb_font_t *font)
    575 {
    576   if (unlikely (!hb_uniscribe_shaper_font_data_ensure (font))) return nullptr;
    577   hb_uniscribe_shaper_font_data_t *font_data =  HB_SHAPER_DATA_GET (font);
    578   return font_data->hfont;
    579 }
    580 
    581 
    582 /*
    583  * shaper shape_plan data
    584  */
    585 
    586 struct hb_uniscribe_shaper_shape_plan_data_t {};
    587 
    588 hb_uniscribe_shaper_shape_plan_data_t *
    589 _hb_uniscribe_shaper_shape_plan_data_create (hb_shape_plan_t    *shape_plan HB_UNUSED,
    590 					     const hb_feature_t *user_features HB_UNUSED,
    591 					     unsigned int        num_user_features HB_UNUSED,
    592 					     const int          *coords HB_UNUSED,
    593 					     unsigned int        num_coords HB_UNUSED)
    594 {
    595   return (hb_uniscribe_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
    596 }
    597 
    598 void
    599 _hb_uniscribe_shaper_shape_plan_data_destroy (hb_uniscribe_shaper_shape_plan_data_t *data HB_UNUSED)
    600 {
    601 }
    602 
    603 
    604 /*
    605  * shaper
    606  */
    607 
    608 
    609 hb_bool_t
    610 _hb_uniscribe_shape (hb_shape_plan_t    *shape_plan,
    611 		     hb_font_t          *font,
    612 		     hb_buffer_t        *buffer,
    613 		     const hb_feature_t *features,
    614 		     unsigned int        num_features)
    615 {
    616   hb_face_t *face = font->face;
    617   hb_uniscribe_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
    618   hb_uniscribe_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font);
    619   hb_uniscribe_shaper_funcs_t *funcs = face_data->funcs;
    620 
    621   /*
    622    * Set up features.
    623    */
    624   hb_auto_array_t<OPENTYPE_FEATURE_RECORD> feature_records;
    625   hb_auto_array_t<range_record_t> range_records;
    626   if (num_features)
    627   {
    628     /* Sort features by start/end events. */
    629     hb_auto_array_t<feature_event_t> feature_events;
    630     for (unsigned int i = 0; i < num_features; i++)
    631     {
    632       active_feature_t feature;
    633       feature.rec.tagFeature = hb_uint32_swap (features[i].tag);
    634       feature.rec.lParameter = features[i].value;
    635       feature.order = i;
    636 
    637       feature_event_t *event;
    638 
    639       event = feature_events.push ();
    640       if (unlikely (!event))
    641 	goto fail_features;
    642       event->index = features[i].start;
    643       event->start = true;
    644       event->feature = feature;
    645 
    646       event = feature_events.push ();
    647       if (unlikely (!event))
    648 	goto fail_features;
    649       event->index = features[i].end;
    650       event->start = false;
    651       event->feature = feature;
    652     }
    653     feature_events.qsort ();
    654     /* Add a strategic final event. */
    655     {
    656       active_feature_t feature;
    657       feature.rec.tagFeature = 0;
    658       feature.rec.lParameter = 0;
    659       feature.order = num_features + 1;
    660 
    661       feature_event_t *event = feature_events.push ();
    662       if (unlikely (!event))
    663 	goto fail_features;
    664       event->index = 0; /* This value does magic. */
    665       event->start = false;
    666       event->feature = feature;
    667     }
    668 
    669     /* Scan events and save features for each range. */
    670     hb_auto_array_t<active_feature_t> active_features;
    671     unsigned int last_index = 0;
    672     for (unsigned int i = 0; i < feature_events.len; i++)
    673     {
    674       feature_event_t *event = &feature_events[i];
    675 
    676       if (event->index != last_index)
    677       {
    678         /* Save a snapshot of active features and the range. */
    679 	range_record_t *range = range_records.push ();
    680 	if (unlikely (!range))
    681 	  goto fail_features;
    682 
    683 	unsigned int offset = feature_records.len;
    684 
    685 	active_features.qsort ();
    686 	for (unsigned int j = 0; j < active_features.len; j++)
    687 	{
    688 	  if (!j || active_features[j].rec.tagFeature != feature_records[feature_records.len - 1].tagFeature)
    689 	  {
    690 	    OPENTYPE_FEATURE_RECORD *feature = feature_records.push ();
    691 	    if (unlikely (!feature))
    692 	      goto fail_features;
    693 	    *feature = active_features[j].rec;
    694 	  }
    695 	  else
    696 	  {
    697 	    /* Overrides value for existing feature. */
    698 	    feature_records[feature_records.len - 1].lParameter = active_features[j].rec.lParameter;
    699 	  }
    700 	}
    701 
    702 	/* Will convert to pointer after all is ready, since feature_records.array
    703 	 * may move as we grow it. */
    704 	range->props.potfRecords = reinterpret_cast<OPENTYPE_FEATURE_RECORD *> (offset);
    705 	range->props.cotfRecords = feature_records.len - offset;
    706 	range->index_first = last_index;
    707 	range->index_last  = event->index - 1;
    708 
    709 	last_index = event->index;
    710       }
    711 
    712       if (event->start) {
    713         active_feature_t *feature = active_features.push ();
    714 	if (unlikely (!feature))
    715 	  goto fail_features;
    716 	*feature = event->feature;
    717       } else {
    718         active_feature_t *feature = active_features.find (&event->feature);
    719 	if (feature)
    720 	  active_features.remove (feature - active_features.array);
    721       }
    722     }
    723 
    724     if (!range_records.len) /* No active feature found. */
    725       goto fail_features;
    726 
    727     /* Fixup the pointers. */
    728     for (unsigned int i = 0; i < range_records.len; i++)
    729     {
    730       range_record_t *range = &range_records[i];
    731       range->props.potfRecords = feature_records.array + reinterpret_cast<uintptr_t> (range->props.potfRecords);
    732     }
    733   }
    734   else
    735   {
    736   fail_features:
    737     num_features = 0;
    738   }
    739 
    740 #define FAIL(...) \
    741   HB_STMT_START { \
    742     DEBUG_MSG (UNISCRIBE, nullptr, __VA_ARGS__); \
    743     return false; \
    744   } HB_STMT_END;
    745 
    746   HRESULT hr;
    747 
    748 retry:
    749 
    750   unsigned int scratch_size;
    751   hb_buffer_t::scratch_buffer_t *scratch = buffer->get_scratch_buffer (&scratch_size);
    752 
    753 #define ALLOCATE_ARRAY(Type, name, len) \
    754   Type *name = (Type *) scratch; \
    755   { \
    756     unsigned int _consumed = DIV_CEIL ((len) * sizeof (Type), sizeof (*scratch)); \
    757     assert (_consumed <= scratch_size); \
    758     scratch += _consumed; \
    759     scratch_size -= _consumed; \
    760   }
    761 
    762 #define utf16_index() var1.u32
    763 
    764   ALLOCATE_ARRAY (WCHAR, pchars, buffer->len * 2);
    765 
    766   unsigned int chars_len = 0;
    767   for (unsigned int i = 0; i < buffer->len; i++)
    768   {
    769     hb_codepoint_t c = buffer->info[i].codepoint;
    770     buffer->info[i].utf16_index() = chars_len;
    771     if (likely (c <= 0xFFFFu))
    772       pchars[chars_len++] = c;
    773     else if (unlikely (c > 0x10FFFFu))
    774       pchars[chars_len++] = 0xFFFDu;
    775     else {
    776       pchars[chars_len++] = 0xD800u + ((c - 0x10000u) >> 10);
    777       pchars[chars_len++] = 0xDC00u + ((c - 0x10000u) & ((1u << 10) - 1));
    778     }
    779   }
    780 
    781   ALLOCATE_ARRAY (WORD, log_clusters, chars_len);
    782   ALLOCATE_ARRAY (SCRIPT_CHARPROP, char_props, chars_len);
    783 
    784   if (num_features)
    785   {
    786     /* Need log_clusters to assign features. */
    787     chars_len = 0;
    788     for (unsigned int i = 0; i < buffer->len; i++)
    789     {
    790       hb_codepoint_t c = buffer->info[i].codepoint;
    791       unsigned int cluster = buffer->info[i].cluster;
    792       log_clusters[chars_len++] = cluster;
    793       if (hb_in_range (c, 0x10000u, 0x10FFFFu))
    794 	log_clusters[chars_len++] = cluster; /* Surrogates. */
    795     }
    796   }
    797 
    798   /* The -2 in the following is to compensate for possible
    799    * alignment needed after the WORD array.  sizeof(WORD) == 2. */
    800   unsigned int glyphs_size = (scratch_size * sizeof (int) - 2)
    801 			   / (sizeof (WORD) +
    802 			      sizeof (SCRIPT_GLYPHPROP) +
    803 			      sizeof (int) +
    804 			      sizeof (GOFFSET) +
    805 			      sizeof (uint32_t));
    806 
    807   ALLOCATE_ARRAY (WORD, glyphs, glyphs_size);
    808   ALLOCATE_ARRAY (SCRIPT_GLYPHPROP, glyph_props, glyphs_size);
    809   ALLOCATE_ARRAY (int, advances, glyphs_size);
    810   ALLOCATE_ARRAY (GOFFSET, offsets, glyphs_size);
    811   ALLOCATE_ARRAY (uint32_t, vis_clusters, glyphs_size);
    812 
    813   /* Note:
    814    * We can't touch the contents of glyph_props.  Our fallback
    815    * implementations of Shape and Place functions use that buffer
    816    * by casting it to a different type.  It works because they
    817    * both agree about it, but if we want to access it here we
    818    * need address that issue first.
    819    */
    820 
    821 #undef ALLOCATE_ARRAY
    822 
    823 #define MAX_ITEMS 256
    824 
    825   SCRIPT_ITEM items[MAX_ITEMS + 1];
    826   SCRIPT_CONTROL bidi_control = {0};
    827   SCRIPT_STATE bidi_state = {0};
    828   ULONG script_tags[MAX_ITEMS];
    829   int item_count;
    830 
    831   /* MinGW32 doesn't define fMergeNeutralItems, so we bruteforce */
    832   //bidi_control.fMergeNeutralItems = true;
    833   *(uint32_t*)&bidi_control |= 1u<<24;
    834 
    835   bidi_state.uBidiLevel = HB_DIRECTION_IS_FORWARD (buffer->props.direction) ? 0 : 1;
    836   bidi_state.fOverrideDirection = 1;
    837 
    838   hr = funcs->ScriptItemizeOpenType (pchars,
    839 				     chars_len,
    840 				     MAX_ITEMS,
    841 				     &bidi_control,
    842 				     &bidi_state,
    843 				     items,
    844 				     script_tags,
    845 				     &item_count);
    846   if (unlikely (FAILED (hr)))
    847     FAIL ("ScriptItemizeOpenType() failed: 0x%08xL", hr);
    848 
    849 #undef MAX_ITEMS
    850 
    851   OPENTYPE_TAG language_tag = hb_uint32_swap (hb_ot_tag_from_language (buffer->props.language));
    852   hb_auto_array_t<TEXTRANGE_PROPERTIES*> range_properties;
    853   hb_auto_array_t<int> range_char_counts;
    854 
    855   unsigned int glyphs_offset = 0;
    856   unsigned int glyphs_len;
    857   bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
    858   for (int i = 0; i < item_count; i++)
    859   {
    860     unsigned int chars_offset = items[i].iCharPos;
    861     unsigned int item_chars_len = items[i + 1].iCharPos - chars_offset;
    862 
    863     if (num_features)
    864     {
    865       range_properties.shrink (0);
    866       range_char_counts.shrink (0);
    867 
    868       range_record_t *last_range = &range_records[0];
    869 
    870       for (unsigned int k = chars_offset; k < chars_offset + item_chars_len; k++)
    871       {
    872 	range_record_t *range = last_range;
    873 	while (log_clusters[k] < range->index_first)
    874 	  range--;
    875 	while (log_clusters[k] > range->index_last)
    876 	  range++;
    877 	if (!range_properties.len ||
    878 	    &range->props != range_properties[range_properties.len - 1])
    879 	{
    880 	  TEXTRANGE_PROPERTIES **props = range_properties.push ();
    881 	  int *c = range_char_counts.push ();
    882 	  if (unlikely (!props || !c))
    883 	  {
    884 	    range_properties.shrink (0);
    885 	    range_char_counts.shrink (0);
    886 	    break;
    887 	  }
    888 	  *props = &range->props;
    889 	  *c = 1;
    890 	}
    891 	else
    892 	{
    893 	  range_char_counts[range_char_counts.len - 1]++;
    894 	}
    895 
    896 	last_range = range;
    897       }
    898     }
    899 
    900     /* Asking for glyphs in logical order circumvents at least
    901      * one bug in Uniscribe. */
    902     items[i].a.fLogicalOrder = true;
    903 
    904   retry_shape:
    905     hr = funcs->ScriptShapeOpenType (font_data->hdc,
    906 				     &font_data->script_cache,
    907 				     &items[i].a,
    908 				     script_tags[i],
    909 				     language_tag,
    910 				     range_char_counts.array,
    911 				     range_properties.array,
    912 				     range_properties.len,
    913 				     pchars + chars_offset,
    914 				     item_chars_len,
    915 				     glyphs_size - glyphs_offset,
    916 				     /* out */
    917 				     log_clusters + chars_offset,
    918 				     char_props + chars_offset,
    919 				     glyphs + glyphs_offset,
    920 				     glyph_props + glyphs_offset,
    921 				     (int *) &glyphs_len);
    922 
    923     if (unlikely (items[i].a.fNoGlyphIndex))
    924       FAIL ("ScriptShapeOpenType() set fNoGlyphIndex");
    925     if (unlikely (hr == E_OUTOFMEMORY || hr == E_NOT_SUFFICIENT_BUFFER))
    926     {
    927       if (unlikely (!buffer->ensure (buffer->allocated * 2)))
    928 	FAIL ("Buffer resize failed");
    929       goto retry;
    930     }
    931     if (unlikely (hr == USP_E_SCRIPT_NOT_IN_FONT))
    932     {
    933       if (items[i].a.eScript == SCRIPT_UNDEFINED)
    934 	FAIL ("ScriptShapeOpenType() failed: Font doesn't support script");
    935       items[i].a.eScript = SCRIPT_UNDEFINED;
    936       goto retry_shape;
    937     }
    938     if (unlikely (FAILED (hr)))
    939     {
    940       FAIL ("ScriptShapeOpenType() failed: 0x%08xL", hr);
    941     }
    942 
    943     for (unsigned int j = chars_offset; j < chars_offset + item_chars_len; j++)
    944       log_clusters[j] += glyphs_offset;
    945 
    946     hr = funcs->ScriptPlaceOpenType (font_data->hdc,
    947 				     &font_data->script_cache,
    948 				     &items[i].a,
    949 				     script_tags[i],
    950 				     language_tag,
    951 				     range_char_counts.array,
    952 				     range_properties.array,
    953 				     range_properties.len,
    954 				     pchars + chars_offset,
    955 				     log_clusters + chars_offset,
    956 				     char_props + chars_offset,
    957 				     item_chars_len,
    958 				     glyphs + glyphs_offset,
    959 				     glyph_props + glyphs_offset,
    960 				     glyphs_len,
    961 				     /* out */
    962 				     advances + glyphs_offset,
    963 				     offsets + glyphs_offset,
    964 				     nullptr);
    965     if (unlikely (FAILED (hr)))
    966       FAIL ("ScriptPlaceOpenType() failed: 0x%08xL", hr);
    967 
    968     if (DEBUG_ENABLED (UNISCRIBE))
    969       fprintf (stderr, "Item %d RTL %d LayoutRTL %d LogicalOrder %d ScriptTag %c%c%c%c\n",
    970 	       i,
    971 	       items[i].a.fRTL,
    972 	       items[i].a.fLayoutRTL,
    973 	       items[i].a.fLogicalOrder,
    974 	       HB_UNTAG (hb_uint32_swap (script_tags[i])));
    975 
    976     glyphs_offset += glyphs_len;
    977   }
    978   glyphs_len = glyphs_offset;
    979 
    980   /* Ok, we've got everything we need, now compose output buffer,
    981    * very, *very*, carefully! */
    982 
    983   /* Calculate visual-clusters.  That's what we ship. */
    984   for (unsigned int i = 0; i < glyphs_len; i++)
    985     vis_clusters[i] = -1;
    986   for (unsigned int i = 0; i < buffer->len; i++) {
    987     uint32_t *p = &vis_clusters[log_clusters[buffer->info[i].utf16_index()]];
    988     *p = MIN (*p, buffer->info[i].cluster);
    989   }
    990   for (unsigned int i = 1; i < glyphs_len; i++)
    991     if (vis_clusters[i] == -1)
    992       vis_clusters[i] = vis_clusters[i - 1];
    993 
    994 #undef utf16_index
    995 
    996   if (unlikely (!buffer->ensure (glyphs_len)))
    997     FAIL ("Buffer in error");
    998 
    999 #undef FAIL
   1000 
   1001   /* Set glyph infos */
   1002   buffer->len = 0;
   1003   for (unsigned int i = 0; i < glyphs_len; i++)
   1004   {
   1005     hb_glyph_info_t *info = &buffer->info[buffer->len++];
   1006 
   1007     info->codepoint = glyphs[i];
   1008     info->cluster = vis_clusters[i];
   1009 
   1010     /* The rest is crap.  Let's store position info there for now. */
   1011     info->mask = advances[i];
   1012     info->var1.i32 = offsets[i].du;
   1013     info->var2.i32 = offsets[i].dv;
   1014   }
   1015 
   1016   /* Set glyph positions */
   1017   buffer->clear_positions ();
   1018   double x_mult = font_data->x_mult, y_mult = font_data->y_mult;
   1019   for (unsigned int i = 0; i < glyphs_len; i++)
   1020   {
   1021     hb_glyph_info_t *info = &buffer->info[i];
   1022     hb_glyph_position_t *pos = &buffer->pos[i];
   1023 
   1024     /* TODO vertical */
   1025     pos->x_advance = x_mult * (int32_t) info->mask;
   1026     pos->x_offset = x_mult * (backward ? -info->var1.i32 : info->var1.i32);
   1027     pos->y_offset = y_mult * info->var2.i32;
   1028 
   1029     info->mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
   1030   }
   1031 
   1032   if (backward)
   1033     hb_buffer_reverse (buffer);
   1034 
   1035   buffer->unsafe_to_break_all ();
   1036 
   1037   /* Wow, done! */
   1038   return true;
   1039 }
   1040 
   1041 
   1042