10fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod/*
23613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod * Copyright © 2011,2012,2013  Google, Inc.
30fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod *
40fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod *  This is part of HarfBuzz, a text shaping library.
50fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod *
60fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * Permission is hereby granted, without written agreement and without
70fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * license or royalty fees, to use, copy, modify, and distribute this
80fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * software and its documentation for any purpose, provided that the
90fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * above copyright notice and the following two paragraphs appear in
100fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * all copies of this software.
110fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod *
120fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
130fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
140fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
150fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
160fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * DAMAGE.
170fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod *
180fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
190fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
200fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
210fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
220fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
230fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod *
240fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * Google Author(s): Behdad Esfahbod
250fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod */
260fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
27027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod#define HB_SHAPER uniscribe
28027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod#include "hb-shaper-impl-private.hh"
290fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
30b492299eb3c398701557e452f6c2c9bd370fbbf3Behdad Esfahbod#include <windows.h>
31b492299eb3c398701557e452f6c2c9bd370fbbf3Behdad Esfahbod#include <usp10.h>
328ac2e88deff3d069c19fd59d0fbbfb88a762b113Behdad Esfahbod#include <rpc.h>
33b492299eb3c398701557e452f6c2c9bd370fbbf3Behdad Esfahbod
340fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#include "hb-uniscribe.h"
350fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
368ac2e88deff3d069c19fd59d0fbbfb88a762b113Behdad Esfahbod#include "hb-open-file-private.hh"
377a750ac33ec482e2c4856c19ea607f3563741c24Behdad Esfahbod#include "hb-ot-name-table.hh"
380fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#include "hb-ot-tag.h"
390fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
400fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
410fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#ifndef HB_DEBUG_UNISCRIBE
420fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#define HB_DEBUG_UNISCRIBE (HB_DEBUG+0)
430fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#endif
440fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
450fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
46666b42f73bd1f516657b206ef738108825bf239fBehdad Esfahbodstatic inline uint16_t hb_uint16_swap (const uint16_t v)
47666b42f73bd1f516657b206ef738108825bf239fBehdad Esfahbod{ return (v >> 8) | (v << 8); }
48666b42f73bd1f516657b206ef738108825bf239fBehdad Esfahbodstatic inline uint32_t hb_uint32_swap (const uint32_t v)
49666b42f73bd1f516657b206ef738108825bf239fBehdad Esfahbod{ return (hb_uint16_swap (v) << 16) | hb_uint16_swap (v >> 16); }
50666b42f73bd1f516657b206ef738108825bf239fBehdad Esfahbod
51666b42f73bd1f516657b206ef738108825bf239fBehdad Esfahbod
5293a04b8b5e6d8067cb925fdf532aadc24c1d4861Chun-wei Fantypedef HRESULT (WINAPI *SIOT) /*ScriptItemizeOpenType*/(
532a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  const WCHAR *pwcInChars,
542a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  int cInChars,
552a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  int cMaxItems,
562a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  const SCRIPT_CONTROL *psControl,
572a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  const SCRIPT_STATE *psState,
582a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  SCRIPT_ITEM *pItems,
592a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  OPENTYPE_TAG *pScriptTags,
602a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  int *pcItems
612a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod);
622a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod
6393a04b8b5e6d8067cb925fdf532aadc24c1d4861Chun-wei Fantypedef HRESULT (WINAPI *SSOT) /*ScriptShapeOpenType*/(
642a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  HDC hdc,
652a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  SCRIPT_CACHE *psc,
662a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  SCRIPT_ANALYSIS *psa,
672a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  OPENTYPE_TAG tagScript,
682a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  OPENTYPE_TAG tagLangSys,
692a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  int *rcRangeChars,
702a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  TEXTRANGE_PROPERTIES **rpRangeProperties,
712a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  int cRanges,
722a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  const WCHAR *pwcChars,
732a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  int cChars,
742a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  int cMaxGlyphs,
752a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  WORD *pwLogClust,
762a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  SCRIPT_CHARPROP *pCharProps,
772a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  WORD *pwOutGlyphs,
782a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  SCRIPT_GLYPHPROP *pOutGlyphProps,
792a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  int *pcGlyphs
800fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod);
812a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod
8293a04b8b5e6d8067cb925fdf532aadc24c1d4861Chun-wei Fantypedef HRESULT (WINAPI *SPOT) /*ScriptPlaceOpenType*/(
832a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  HDC hdc,
842a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  SCRIPT_CACHE *psc,
852a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  SCRIPT_ANALYSIS *psa,
862a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  OPENTYPE_TAG tagScript,
872a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  OPENTYPE_TAG tagLangSys,
882a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  int *rcRangeChars,
892a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  TEXTRANGE_PROPERTIES **rpRangeProperties,
902a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  int cRanges,
912a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  const WCHAR *pwcChars,
922a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  WORD *pwLogClust,
932a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  SCRIPT_CHARPROP *pCharProps,
942a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  int cChars,
952a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  const WORD *pwGlyphs,
962a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  const SCRIPT_GLYPHPROP *pGlyphProps,
972a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  int cGlyphs,
982a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  int *piAdvance,
992a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  GOFFSET *pGoffset,
1002a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  ABC *pABC
1012a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod);
1022a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod
1032a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod
1042a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod/* Fallback implementations. */
1052a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod
1062a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbodstatic HRESULT WINAPI
1072a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbodhb_ScriptItemizeOpenType(
1082a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  const WCHAR *pwcInChars,
1092a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  int cInChars,
1102a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  int cMaxItems,
1112a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  const SCRIPT_CONTROL *psControl,
1122a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  const SCRIPT_STATE *psState,
1132a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  SCRIPT_ITEM *pItems,
1142a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  OPENTYPE_TAG *pScriptTags,
1152a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  int *pcItems
1162a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod)
1172a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod{
1182a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod{
1192a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  return ScriptItemize (pwcInChars,
1202a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod			cInChars,
1212a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod			cMaxItems,
1222a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod			psControl,
1232a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod			psState,
1242a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod			pItems,
1252a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod			pcItems);
1262a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod}
1272a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod}
1282a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod
1292a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbodstatic HRESULT WINAPI
1302a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbodhb_ScriptShapeOpenType(
1312a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  HDC hdc,
1322a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  SCRIPT_CACHE *psc,
1332a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  SCRIPT_ANALYSIS *psa,
1342a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  OPENTYPE_TAG tagScript,
1352a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  OPENTYPE_TAG tagLangSys,
1362a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  int *rcRangeChars,
1372a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  TEXTRANGE_PROPERTIES **rpRangeProperties,
1382a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  int cRanges,
1392a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  const WCHAR *pwcChars,
1402a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  int cChars,
1412a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  int cMaxGlyphs,
1422a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  WORD *pwLogClust,
1432a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  SCRIPT_CHARPROP *pCharProps,
1442a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  WORD *pwOutGlyphs,
1452a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  SCRIPT_GLYPHPROP *pOutGlyphProps,
1462a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  int *pcGlyphs
1472a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod)
1482a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod{
1492a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  SCRIPT_VISATTR *psva = (SCRIPT_VISATTR *) pOutGlyphProps;
1502a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  return ScriptShape (hdc,
1512a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod		      psc,
1522a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod		      pwcChars,
1532a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod		      cChars,
1542a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod		      cMaxGlyphs,
1552a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod		      psa,
1562a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod		      pwOutGlyphs,
1572a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod		      pwLogClust,
1582a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod		      psva,
1592a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod		      pcGlyphs);
1602a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod}
1612a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod
1622a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbodstatic HRESULT WINAPI
1632a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbodhb_ScriptPlaceOpenType(
1642a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  HDC hdc,
1652a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  SCRIPT_CACHE *psc,
1662a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  SCRIPT_ANALYSIS *psa,
1672a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  OPENTYPE_TAG tagScript,
1682a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  OPENTYPE_TAG tagLangSys,
1692a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  int *rcRangeChars,
1702a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  TEXTRANGE_PROPERTIES **rpRangeProperties,
1712a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  int cRanges,
1722a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  const WCHAR *pwcChars,
1732a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  WORD *pwLogClust,
1742a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  SCRIPT_CHARPROP *pCharProps,
1752a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  int cChars,
1762a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  const WORD *pwGlyphs,
1772a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  const SCRIPT_GLYPHPROP *pGlyphProps,
1782a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  int cGlyphs,
1792a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  int *piAdvance,
1802a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  GOFFSET *pGoffset,
1812a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  ABC *pABC
1822a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod)
1832a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod{
1842a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  SCRIPT_VISATTR *psva = (SCRIPT_VISATTR *) pGlyphProps;
1852a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  return ScriptPlace (hdc,
1862a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod		      psc,
1872a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod		      pwGlyphs,
1882a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod		      cGlyphs,
1892a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod		      psva,
1902a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod		      psa,
1912a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod		      piAdvance,
1922a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod		      pGoffset,
1932a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod		      pABC);
1942a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod}
1952a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod
1962a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod
1972a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbodstruct hb_uniscribe_shaper_funcs_t {
1982a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  SIOT ScriptItemizeOpenType;
1992a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  SSOT ScriptShapeOpenType;
2002a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  SPOT ScriptPlaceOpenType;
2012a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod
2022a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  inline void init (void)
2032a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  {
20493a04b8b5e6d8067cb925fdf532aadc24c1d4861Chun-wei Fan    HMODULE hinstLib;
2052a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod    this->ScriptItemizeOpenType = NULL;
2062a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod    this->ScriptShapeOpenType   = NULL;
2072a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod    this->ScriptPlaceOpenType   = NULL;
2082a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod
209757a7a9018577dcc399be03dc45a59589585d2fbBehdad Esfahbod    hinstLib = GetModuleHandle (TEXT ("usp10.dll"));
2102a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod    if (hinstLib)
2112a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod    {
2122a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod      this->ScriptItemizeOpenType = (SIOT) GetProcAddress (hinstLib, "ScriptItemizeOpenType");
2132a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod      this->ScriptShapeOpenType   = (SSOT) GetProcAddress (hinstLib, "ScriptShapeOpenType");
2142a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod      this->ScriptPlaceOpenType   = (SPOT) GetProcAddress (hinstLib, "ScriptPlaceOpenType");
2152a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod    }
2162a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod    if (!this->ScriptItemizeOpenType ||
2172a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod	!this->ScriptShapeOpenType   ||
2182a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod	!this->ScriptPlaceOpenType)
2192a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod    {
2202a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod      DEBUG_MSG (UNISCRIBE, NULL, "OpenType versions of functions not found; falling back.");
2212a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod      this->ScriptItemizeOpenType = hb_ScriptItemizeOpenType;
2222a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod      this->ScriptShapeOpenType   = hb_ScriptShapeOpenType;
2232a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod      this->ScriptPlaceOpenType   = hb_ScriptPlaceOpenType;
2242a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod    }
2252a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  }
2262a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod};
2272a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbodstatic hb_uniscribe_shaper_funcs_t *uniscribe_funcs;
2282a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod
2292a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbodstatic inline void
2302a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbodfree_uniscribe_funcs (void)
2312a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod{
2322a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  free (uniscribe_funcs);
2332a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod}
2342a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod
2352a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbodstatic hb_uniscribe_shaper_funcs_t *
2362a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbodhb_uniscribe_shaper_get_funcs (void)
2372a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod{
2382a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbodretry:
2392a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  hb_uniscribe_shaper_funcs_t *funcs = (hb_uniscribe_shaper_funcs_t *) hb_atomic_ptr_get (&uniscribe_funcs);
2402a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod
2412a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  if (unlikely (!funcs))
2422a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  {
2432a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod    funcs = (hb_uniscribe_shaper_funcs_t *) calloc (1, sizeof (hb_uniscribe_shaper_funcs_t));
2442a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod    if (unlikely (!funcs))
2452a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod      return NULL;
2462a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod
2472a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod    funcs->init ();
2482a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod
2492a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod    if (!hb_atomic_ptr_cmpexch (&uniscribe_funcs, NULL, funcs)) {
2502a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod      free (funcs);
2512a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod      goto retry;
2522a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod    }
2532a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod
25438fb30d7420a4b01f99cee31baa8c3990a1d1c5fBehdad Esfahbod#ifdef HB_USE_ATEXIT
2552a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod    atexit (free_uniscribe_funcs); /* First person registers atexit() callback. */
2562a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod#endif
2572a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  }
2582a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod
2592a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  return funcs;
2602a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod}
2610fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
262bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
2639a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbodstruct active_feature_t {
2649a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod  OPENTYPE_FEATURE_RECORD rec;
2659a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod  unsigned int order;
2669a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod
2679a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod  static int cmp (const active_feature_t *a, const active_feature_t *b) {
2689a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod    return a->rec.tagFeature < b->rec.tagFeature ? -1 : a->rec.tagFeature > b->rec.tagFeature ? 1 :
2699a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	   a->order < b->order ? -1 : a->order > b->order ? 1 :
2709a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	   a->rec.lParameter < b->rec.lParameter ? -1 : a->rec.lParameter > b->rec.lParameter ? 1 :
2719a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	   0;
2729a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod  }
2739a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod  bool operator== (const active_feature_t *f) {
2749a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod    return cmp (this, f) == 0;
2759a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod  }
2769a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod};
2779a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod
2789a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbodstruct feature_event_t {
2799a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod  unsigned int index;
2809a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod  bool start;
2819a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod  active_feature_t feature;
2829a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod
2839a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod  static int cmp (const feature_event_t *a, const feature_event_t *b) {
2849a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod    return a->index < b->index ? -1 : a->index > b->index ? 1 :
2859a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	   a->start < b->start ? -1 : a->start > b->start ? 1 :
2869a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	   active_feature_t::cmp (&a->feature, &b->feature);
2879a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod  }
2889a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod};
2899a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod
2909a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbodstruct range_record_t {
2919a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod  TEXTRANGE_PROPERTIES props;
2929a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod  unsigned int index_first; /* == start */
2939a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod  unsigned int index_last;  /* == end - 1 */
2949a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod};
2959a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod
296cfe9882610489e1b917e09a74dfbf6bbba2e4a57Behdad EsfahbodHB_SHAPER_DATA_ENSURE_DECLARE(uniscribe, face)
297cfe9882610489e1b917e09a74dfbf6bbba2e4a57Behdad EsfahbodHB_SHAPER_DATA_ENSURE_DECLARE(uniscribe, font)
298cfe9882610489e1b917e09a74dfbf6bbba2e4a57Behdad Esfahbod
299cfe9882610489e1b917e09a74dfbf6bbba2e4a57Behdad Esfahbod
300027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod/*
301027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod * shaper face data
302027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod */
30371388b3ee71c7d3b79f842db7588bd683691797cBehdad Esfahbod
304027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbodstruct hb_uniscribe_shaper_face_data_t {
305bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  HANDLE fh;
3062a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  hb_uniscribe_shaper_funcs_t *funcs;
3078ac2e88deff3d069c19fd59d0fbbfb88a762b113Behdad Esfahbod  wchar_t face_name[LF_FACESIZE];
308027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod};
309bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
310bdeea605fe597bff4430eaae3317189bb81ec76eBehdad Esfahbod/* face_name should point to a wchar_t[LF_FACESIZE] object. */
311bdeea605fe597bff4430eaae3317189bb81ec76eBehdad Esfahbodstatic void
312bdeea605fe597bff4430eaae3317189bb81ec76eBehdad Esfahbod_hb_generate_unique_face_name (wchar_t *face_name, unsigned int *plen)
3138ac2e88deff3d069c19fd59d0fbbfb88a762b113Behdad Esfahbod{
3148ac2e88deff3d069c19fd59d0fbbfb88a762b113Behdad Esfahbod  /* We'll create a private name for the font from a UUID using a simple,
3158ac2e88deff3d069c19fd59d0fbbfb88a762b113Behdad Esfahbod   * somewhat base64-like encoding scheme */
3168ac2e88deff3d069c19fd59d0fbbfb88a762b113Behdad Esfahbod  const char *enc = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-";
3178ac2e88deff3d069c19fd59d0fbbfb88a762b113Behdad Esfahbod  UUID id;
3188ac2e88deff3d069c19fd59d0fbbfb88a762b113Behdad Esfahbod  UuidCreate ((UUID*) &id);
319d7c850f8037d2701366008eb8c2a527c9d40abdeBehdad Esfahbod  ASSERT_STATIC (2 + 3 * (16/2) < LF_FACESIZE);
3208ac2e88deff3d069c19fd59d0fbbfb88a762b113Behdad Esfahbod  unsigned int name_str_len = 0;
321bdeea605fe597bff4430eaae3317189bb81ec76eBehdad Esfahbod  face_name[name_str_len++] = 'F';
322bdeea605fe597bff4430eaae3317189bb81ec76eBehdad Esfahbod  face_name[name_str_len++] = '_';
3238ac2e88deff3d069c19fd59d0fbbfb88a762b113Behdad Esfahbod  unsigned char *p = (unsigned char *) &id;
3248ac2e88deff3d069c19fd59d0fbbfb88a762b113Behdad Esfahbod  for (unsigned int i = 0; i < 16; i += 2)
3258ac2e88deff3d069c19fd59d0fbbfb88a762b113Behdad Esfahbod  {
3268ac2e88deff3d069c19fd59d0fbbfb88a762b113Behdad Esfahbod    /* Spread the 16 bits from two bytes of the UUID across three chars of face_name,
3278ac2e88deff3d069c19fd59d0fbbfb88a762b113Behdad Esfahbod     * using the bits in groups of 5,5,6 to select chars from enc.
3288ac2e88deff3d069c19fd59d0fbbfb88a762b113Behdad Esfahbod     * This will generate 24 characters; with the 'F_' prefix we already provided,
3298ac2e88deff3d069c19fd59d0fbbfb88a762b113Behdad Esfahbod     * the name will be 26 chars (plus the NUL terminator), so will always fit within
3308ac2e88deff3d069c19fd59d0fbbfb88a762b113Behdad Esfahbod     * face_name (LF_FACESIZE = 32). */
331bdeea605fe597bff4430eaae3317189bb81ec76eBehdad Esfahbod    face_name[name_str_len++] = enc[p[i] >> 3];
332bdeea605fe597bff4430eaae3317189bb81ec76eBehdad Esfahbod    face_name[name_str_len++] = enc[((p[i] << 2) | (p[i + 1] >> 6)) & 0x1f];
333bdeea605fe597bff4430eaae3317189bb81ec76eBehdad Esfahbod    face_name[name_str_len++] = enc[p[i + 1] & 0x3f];
3348ac2e88deff3d069c19fd59d0fbbfb88a762b113Behdad Esfahbod  }
335bdeea605fe597bff4430eaae3317189bb81ec76eBehdad Esfahbod  face_name[name_str_len] = 0;
336bdeea605fe597bff4430eaae3317189bb81ec76eBehdad Esfahbod  if (plen)
337bdeea605fe597bff4430eaae3317189bb81ec76eBehdad Esfahbod    *plen = name_str_len;
338bdeea605fe597bff4430eaae3317189bb81ec76eBehdad Esfahbod}
339bdeea605fe597bff4430eaae3317189bb81ec76eBehdad Esfahbod
340bdeea605fe597bff4430eaae3317189bb81ec76eBehdad Esfahbod/* Destroys blob. */
341bdeea605fe597bff4430eaae3317189bb81ec76eBehdad Esfahbodstatic hb_blob_t *
342bdeea605fe597bff4430eaae3317189bb81ec76eBehdad Esfahbod_hb_rename_font (hb_blob_t *blob, wchar_t *new_name)
343bdeea605fe597bff4430eaae3317189bb81ec76eBehdad Esfahbod{
34405bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod  /* Create a copy of the font data, with the 'name' table replaced by a
34505bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod   * table that names the font with our private F_* name created above.
34605bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod   * For simplicity, we just append a new 'name' table and update the
34705bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod   * sfnt directory; the original table is left in place, but unused.
34805bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod   *
34905bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod   * The new table will contain just 5 name IDs: family, style, unique,
35005bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod   * full, PS. All of them point to the same name data with our unique name.
35105bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod   */
35205bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod
3538b427c78efa988ed27a2a394146d73f59688707bBehdad Esfahbod  blob = OT::Sanitizer<OT::OpenTypeFontFile>::sanitize (blob);
3548b427c78efa988ed27a2a394146d73f59688707bBehdad Esfahbod
355bdeea605fe597bff4430eaae3317189bb81ec76eBehdad Esfahbod  unsigned int length, new_length, name_str_len;
356bdeea605fe597bff4430eaae3317189bb81ec76eBehdad Esfahbod  const char *orig_sfnt_data = hb_blob_get_data (blob, &length);
357bdeea605fe597bff4430eaae3317189bb81ec76eBehdad Esfahbod
358bdeea605fe597bff4430eaae3317189bb81ec76eBehdad Esfahbod  _hb_generate_unique_face_name (new_name, &name_str_len);
3598ac2e88deff3d069c19fd59d0fbbfb88a762b113Behdad Esfahbod
3608ac2e88deff3d069c19fd59d0fbbfb88a762b113Behdad Esfahbod  static const uint16_t name_IDs[] = { 1, 2, 3, 4, 6 };
3618ac2e88deff3d069c19fd59d0fbbfb88a762b113Behdad Esfahbod
36205bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod  unsigned int name_table_length = OT::name::min_size +
36305bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod                                   ARRAY_LENGTH (name_IDs) * OT::NameRecord::static_size +
3648ac2e88deff3d069c19fd59d0fbbfb88a762b113Behdad Esfahbod                                   name_str_len * 2; /* for name data in UTF16BE form */
3658ac2e88deff3d069c19fd59d0fbbfb88a762b113Behdad Esfahbod  unsigned int name_table_offset = (length + 3) & ~3;
3668ac2e88deff3d069c19fd59d0fbbfb88a762b113Behdad Esfahbod
36705bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod  new_length = name_table_offset + ((name_table_length + 3) & ~3);
36805bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod  void *new_sfnt_data = calloc (1, new_length);
3698ac2e88deff3d069c19fd59d0fbbfb88a762b113Behdad Esfahbod  if (!new_sfnt_data)
37005bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod  {
37105bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod    hb_blob_destroy (blob);
3728ac2e88deff3d069c19fd59d0fbbfb88a762b113Behdad Esfahbod    return NULL;
37305bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod  }
3748ac2e88deff3d069c19fd59d0fbbfb88a762b113Behdad Esfahbod
3758ac2e88deff3d069c19fd59d0fbbfb88a762b113Behdad Esfahbod  memcpy(new_sfnt_data, orig_sfnt_data, length);
3768ac2e88deff3d069c19fd59d0fbbfb88a762b113Behdad Esfahbod
37705bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod  OT::name &name = OT::StructAtOffset<OT::name> (new_sfnt_data, name_table_offset);
37805bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod  name.format.set (0);
37905bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod  name.count.set (ARRAY_LENGTH (name_IDs));
38005bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod  name.stringOffset.set (name.get_size ());
38105bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod  for (unsigned int i = 0; i < ARRAY_LENGTH (name_IDs); i++)
38205bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod  {
38305bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod    OT::NameRecord &record = name.nameRecord[i];
38405bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod    record.platformID.set (3);
38505bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod    record.encodingID.set (1);
3867627100f428ac0ec8509d961d368d2d25d8f0b6eBehdad Esfahbod    record.languageID.set (0x0409u); /* English */
38705bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod    record.nameID.set (name_IDs[i]);
38805bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod    record.length.set (name_str_len * 2);
38905bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod    record.offset.set (0);
3908ac2e88deff3d069c19fd59d0fbbfb88a762b113Behdad Esfahbod  }
3918ac2e88deff3d069c19fd59d0fbbfb88a762b113Behdad Esfahbod
39205bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod  /* Copy string data from new_name, converting wchar_t to UTF16BE. */
39305bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod  unsigned char *p = &OT::StructAfter<unsigned char> (name);
39405bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod  for (unsigned int i = 0; i < name_str_len; i++)
39505bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod  {
3968ac2e88deff3d069c19fd59d0fbbfb88a762b113Behdad Esfahbod    *p++ = new_name[i] >> 8;
3978ac2e88deff3d069c19fd59d0fbbfb88a762b113Behdad Esfahbod    *p++ = new_name[i] & 0xff;
3988ac2e88deff3d069c19fd59d0fbbfb88a762b113Behdad Esfahbod  }
3998ac2e88deff3d069c19fd59d0fbbfb88a762b113Behdad Esfahbod
40005bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod  /* Adjust name table entry to point to new name table */
40112ff69df21ac91ae21860db7000d9f9973d3da1aBehdad Esfahbod  const OT::OpenTypeFontFile &file = * (OT::OpenTypeFontFile *) (new_sfnt_data);
40212ff69df21ac91ae21860db7000d9f9973d3da1aBehdad Esfahbod  unsigned int face_count = file.get_face_count ();
40312ff69df21ac91ae21860db7000d9f9973d3da1aBehdad Esfahbod  for (unsigned int face_index = 0; face_index < face_count; face_index++)
4048ac2e88deff3d069c19fd59d0fbbfb88a762b113Behdad Esfahbod  {
4058b427c78efa988ed27a2a394146d73f59688707bBehdad Esfahbod    /* Note: doing multiple edits (ie. TTC) can be unsafe.  There may be
4068b427c78efa988ed27a2a394146d73f59688707bBehdad Esfahbod     * toe-stepping.  But we don't really care. */
40712ff69df21ac91ae21860db7000d9f9973d3da1aBehdad Esfahbod    const OT::OpenTypeFontFace &face = file.get_face (face_index);
40812ff69df21ac91ae21860db7000d9f9973d3da1aBehdad Esfahbod    unsigned int index;
40912ff69df21ac91ae21860db7000d9f9973d3da1aBehdad Esfahbod    if (face.find_table_index (HB_OT_TAG_name, &index))
41012ff69df21ac91ae21860db7000d9f9973d3da1aBehdad Esfahbod    {
41112ff69df21ac91ae21860db7000d9f9973d3da1aBehdad Esfahbod      OT::TableRecord &record = const_cast<OT::TableRecord &> (face.get_table (index));
41212ff69df21ac91ae21860db7000d9f9973d3da1aBehdad Esfahbod      record.checkSum.set_for_data (&name, name_table_length);
41312ff69df21ac91ae21860db7000d9f9973d3da1aBehdad Esfahbod      record.offset.set (name_table_offset);
41412ff69df21ac91ae21860db7000d9f9973d3da1aBehdad Esfahbod      record.length.set (name_table_length);
41512ff69df21ac91ae21860db7000d9f9973d3da1aBehdad Esfahbod    }
41612ff69df21ac91ae21860db7000d9f9973d3da1aBehdad Esfahbod    else if (face_index == 0) /* Fail if first face doesn't have 'name' table. */
41712ff69df21ac91ae21860db7000d9f9973d3da1aBehdad Esfahbod    {
41812ff69df21ac91ae21860db7000d9f9973d3da1aBehdad Esfahbod      free (new_sfnt_data);
41912ff69df21ac91ae21860db7000d9f9973d3da1aBehdad Esfahbod      hb_blob_destroy (blob);
42012ff69df21ac91ae21860db7000d9f9973d3da1aBehdad Esfahbod      return NULL;
42112ff69df21ac91ae21860db7000d9f9973d3da1aBehdad Esfahbod    }
4228ac2e88deff3d069c19fd59d0fbbfb88a762b113Behdad Esfahbod  }
4238ac2e88deff3d069c19fd59d0fbbfb88a762b113Behdad Esfahbod
4248ac2e88deff3d069c19fd59d0fbbfb88a762b113Behdad Esfahbod  /* The checkSumAdjustment field in the 'head' table is now wrong,
42505bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod   * but that doesn't actually seem to cause any problems so we don't
42605bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod   * bother. */
4278ac2e88deff3d069c19fd59d0fbbfb88a762b113Behdad Esfahbod
42873f947e2a7bc5b29d731da2e9d1fafe958be839eBehdad Esfahbod  hb_blob_destroy (blob);
42905bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod  return hb_blob_create ((const char *) new_sfnt_data, new_length,
43005bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod			 HB_MEMORY_MODE_WRITABLE, NULL, free);
4318ac2e88deff3d069c19fd59d0fbbfb88a762b113Behdad Esfahbod}
4328ac2e88deff3d069c19fd59d0fbbfb88a762b113Behdad Esfahbod
433027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbodhb_uniscribe_shaper_face_data_t *
434027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod_hb_uniscribe_shaper_face_data_create (hb_face_t *face)
435bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod{
436027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  hb_uniscribe_shaper_face_data_t *data = (hb_uniscribe_shaper_face_data_t *) calloc (1, sizeof (hb_uniscribe_shaper_face_data_t));
437bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  if (unlikely (!data))
438027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    return NULL;
439a3bd8a0e1862212a2d4141b973039bd000a3054fBehdad Esfahbod
4402a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  data->funcs = hb_uniscribe_shaper_get_funcs ();
4412a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  if (unlikely (!data->funcs))
4422a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  {
4432a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod    free (data);
4442a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod    return NULL;
4452a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  }
4462a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod
447bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  hb_blob_t *blob = hb_face_reference_blob (face);
44873f947e2a7bc5b29d731da2e9d1fafe958be839eBehdad Esfahbod  if (unlikely (!hb_blob_get_length (blob)))
449bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod    DEBUG_MSG (UNISCRIBE, face, "Face has empty blob");
450bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
45173f947e2a7bc5b29d731da2e9d1fafe958be839eBehdad Esfahbod  blob = _hb_rename_font (blob, data->face_name);
45205bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod  if (unlikely (!blob))
45305bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod  {
45405bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod    free (data);
45505bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod    return NULL;
45605bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod  }
4578ac2e88deff3d069c19fd59d0fbbfb88a762b113Behdad Esfahbod
4588ac2e88deff3d069c19fd59d0fbbfb88a762b113Behdad Esfahbod  DWORD num_fonts_installed;
45973f947e2a7bc5b29d731da2e9d1fafe958be839eBehdad Esfahbod  data->fh = AddFontMemResourceEx ((void *) hb_blob_get_data (blob, NULL),
46073f947e2a7bc5b29d731da2e9d1fafe958be839eBehdad Esfahbod				   hb_blob_get_length (blob),
46173f947e2a7bc5b29d731da2e9d1fafe958be839eBehdad Esfahbod				   0, &num_fonts_installed);
46205bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod  if (unlikely (!data->fh))
46305bad3b8c25a89bc0f20f99f9215e492f48f03feBehdad Esfahbod  {
464bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod    DEBUG_MSG (UNISCRIBE, face, "Face AddFontMemResourceEx() failed");
465027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    free (data);
466027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    return NULL;
467bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  }
468bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
469bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  return data;
470bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod}
471bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
472027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbodvoid
473027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod_hb_uniscribe_shaper_face_data_destroy (hb_uniscribe_shaper_face_data_t *data)
474027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod{
475713914d3203109a8e9213f5a1d3b384730703ce9Behdad Esfahbod  RemoveFontMemResourceEx (data->fh);
476027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  free (data);
477027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod}
478bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
479027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
480027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod/*
481027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod * shaper font data
482027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod */
483027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
484027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbodstruct hb_uniscribe_shaper_font_data_t {
485bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  HDC hdc;
486d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad Esfahbod  LOGFONTW log_font;
487bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  HFONT hfont;
488bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  SCRIPT_CACHE script_cache;
4897c5bee09d9c7c25672c7c77572ebae0b731892d0Behdad Esfahbod  double x_mult, y_mult; /* From LOGFONT space to HB space. */
490027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod};
491bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
492b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbodstatic bool
493b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbodpopulate_log_font (LOGFONTW  *lf,
4947c5bee09d9c7c25672c7c77572ebae0b731892d0Behdad Esfahbod		   hb_font_t *font,
4957c5bee09d9c7c25672c7c77572ebae0b731892d0Behdad Esfahbod		   unsigned int font_size)
496b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod{
497b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod  memset (lf, 0, sizeof (*lf));
4987c5bee09d9c7c25672c7c77572ebae0b731892d0Behdad Esfahbod  lf->lfHeight = -font_size;
499b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod  lf->lfCharSet = DEFAULT_CHARSET;
500b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod
5018ac2e88deff3d069c19fd59d0fbbfb88a762b113Behdad Esfahbod  hb_face_t *face = font->face;
5028ac2e88deff3d069c19fd59d0fbbfb88a762b113Behdad Esfahbod  hb_uniscribe_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
503b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod
5048ac2e88deff3d069c19fd59d0fbbfb88a762b113Behdad Esfahbod  memcpy (lf->lfFaceName, face_data->face_name, sizeof (lf->lfFaceName));
505b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod
506b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod  return true;
507b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod}
508b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod
509027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbodhb_uniscribe_shaper_font_data_t *
510027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod_hb_uniscribe_shaper_font_data_create (hb_font_t *font)
511027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod{
512713914d3203109a8e9213f5a1d3b384730703ce9Behdad Esfahbod  if (unlikely (!hb_uniscribe_shaper_face_data_ensure (font->face))) return NULL;
513713914d3203109a8e9213f5a1d3b384730703ce9Behdad Esfahbod
514e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod  hb_uniscribe_shaper_font_data_t *data = (hb_uniscribe_shaper_font_data_t *) calloc (1, sizeof (hb_uniscribe_shaper_font_data_t));
515027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  if (unlikely (!data))
516027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    return NULL;
517027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
5187c5bee09d9c7c25672c7c77572ebae0b731892d0Behdad Esfahbod  int font_size = font->face->get_upem (); /* Default... */
5197c5bee09d9c7c25672c7c77572ebae0b731892d0Behdad Esfahbod  /* No idea if the following is even a good idea. */
5207c5bee09d9c7c25672c7c77572ebae0b731892d0Behdad Esfahbod  if (font->y_ppem)
5217c5bee09d9c7c25672c7c77572ebae0b731892d0Behdad Esfahbod    font_size = font->y_ppem;
5227c5bee09d9c7c25672c7c77572ebae0b731892d0Behdad Esfahbod
5237c5bee09d9c7c25672c7c77572ebae0b731892d0Behdad Esfahbod  if (font_size < 0)
5247c5bee09d9c7c25672c7c77572ebae0b731892d0Behdad Esfahbod    font_size = -font_size;
5257c5bee09d9c7c25672c7c77572ebae0b731892d0Behdad Esfahbod  data->x_mult = (double) font->x_scale / font_size;
5267c5bee09d9c7c25672c7c77572ebae0b731892d0Behdad Esfahbod  data->y_mult = (double) font->y_scale / font_size;
5277c5bee09d9c7c25672c7c77572ebae0b731892d0Behdad Esfahbod
528027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  data->hdc = GetDC (NULL);
529027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
5307c5bee09d9c7c25672c7c77572ebae0b731892d0Behdad Esfahbod  if (unlikely (!populate_log_font (&data->log_font, font, font_size))) {
531027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    DEBUG_MSG (UNISCRIBE, font, "Font populate_log_font() failed");
532027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    _hb_uniscribe_shaper_font_data_destroy (data);
533027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    return NULL;
534027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  }
535027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
536027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  data->hfont = CreateFontIndirectW (&data->log_font);
537027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  if (unlikely (!data->hfont)) {
538027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    DEBUG_MSG (UNISCRIBE, font, "Font CreateFontIndirectW() failed");
539027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    _hb_uniscribe_shaper_font_data_destroy (data);
540027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod     return NULL;
541027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  }
542027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
543027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  if (!SelectObject (data->hdc, data->hfont)) {
544027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    DEBUG_MSG (UNISCRIBE, font, "Font SelectObject() failed");
545027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    _hb_uniscribe_shaper_font_data_destroy (data);
546027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod     return NULL;
547027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  }
548027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
549027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  return data;
550027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod}
551027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
552027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbodvoid
553027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod_hb_uniscribe_shaper_font_data_destroy (hb_uniscribe_shaper_font_data_t *data)
554bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod{
555bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  if (data->hdc)
556bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod    ReleaseDC (NULL, data->hdc);
557bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  if (data->hfont)
558bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod    DeleteObject (data->hfont);
559bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  if (data->script_cache)
560bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod    ScriptFreeCache (&data->script_cache);
561bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  free (data);
562bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod}
563bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
5640ae6dbf1b4de8a0326b8a2f201597427cecfb6dbBehdad EsfahbodLOGFONTW *
5650ae6dbf1b4de8a0326b8a2f201597427cecfb6dbBehdad Esfahbodhb_uniscribe_font_get_logfontw (hb_font_t *font)
5660ae6dbf1b4de8a0326b8a2f201597427cecfb6dbBehdad Esfahbod{
5670ae6dbf1b4de8a0326b8a2f201597427cecfb6dbBehdad Esfahbod  if (unlikely (!hb_uniscribe_shaper_font_data_ensure (font))) return NULL;
5680ae6dbf1b4de8a0326b8a2f201597427cecfb6dbBehdad Esfahbod  hb_uniscribe_shaper_font_data_t *font_data =  HB_SHAPER_DATA_GET (font);
5690ae6dbf1b4de8a0326b8a2f201597427cecfb6dbBehdad Esfahbod  return &font_data->log_font;
5700ae6dbf1b4de8a0326b8a2f201597427cecfb6dbBehdad Esfahbod}
5710ae6dbf1b4de8a0326b8a2f201597427cecfb6dbBehdad Esfahbod
5720ae6dbf1b4de8a0326b8a2f201597427cecfb6dbBehdad EsfahbodHFONT
5730ae6dbf1b4de8a0326b8a2f201597427cecfb6dbBehdad Esfahbodhb_uniscribe_font_get_hfont (hb_font_t *font)
5740ae6dbf1b4de8a0326b8a2f201597427cecfb6dbBehdad Esfahbod{
5750ae6dbf1b4de8a0326b8a2f201597427cecfb6dbBehdad Esfahbod  if (unlikely (!hb_uniscribe_shaper_font_data_ensure (font))) return NULL;
5760ae6dbf1b4de8a0326b8a2f201597427cecfb6dbBehdad Esfahbod  hb_uniscribe_shaper_font_data_t *font_data =  HB_SHAPER_DATA_GET (font);
5770ae6dbf1b4de8a0326b8a2f201597427cecfb6dbBehdad Esfahbod  return font_data->hfont;
5780ae6dbf1b4de8a0326b8a2f201597427cecfb6dbBehdad Esfahbod}
5790ae6dbf1b4de8a0326b8a2f201597427cecfb6dbBehdad Esfahbod
580027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
581027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod/*
582027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod * shaper shape_plan data
583027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod */
584027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
585027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbodstruct hb_uniscribe_shaper_shape_plan_data_t {};
586027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
587027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbodhb_uniscribe_shaper_shape_plan_data_t *
58845c1383cc7315f89c23c0ed388b99e87224884e7Behdad Esfahbod_hb_uniscribe_shaper_shape_plan_data_create (hb_shape_plan_t    *shape_plan HB_UNUSED,
58945c1383cc7315f89c23c0ed388b99e87224884e7Behdad Esfahbod					     const hb_feature_t *user_features HB_UNUSED,
59045c1383cc7315f89c23c0ed388b99e87224884e7Behdad Esfahbod					     unsigned int        num_user_features HB_UNUSED)
591bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod{
592027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  return (hb_uniscribe_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
593027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod}
594bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
595027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbodvoid
59645c1383cc7315f89c23c0ed388b99e87224884e7Behdad Esfahbod_hb_uniscribe_shaper_shape_plan_data_destroy (hb_uniscribe_shaper_shape_plan_data_t *data HB_UNUSED)
597027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod{
598027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod}
599bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
600bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
601027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod/*
602027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod * shaper
603027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod */
604bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
605bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
60602aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbodhb_bool_t
607bd26b4d21f59312805d294f46f15182adbcc47daBehdad Esfahbod_hb_uniscribe_shape (hb_shape_plan_t    *shape_plan,
608bd26b4d21f59312805d294f46f15182adbcc47daBehdad Esfahbod		     hb_font_t          *font,
6096bd9b479b8b2befbb0847282e93beade197c8038Behdad Esfahbod		     hb_buffer_t        *buffer,
6106bd9b479b8b2befbb0847282e93beade197c8038Behdad Esfahbod		     const hb_feature_t *features,
6116bd9b479b8b2befbb0847282e93beade197c8038Behdad Esfahbod		     unsigned int        num_features)
6120fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod{
613b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod  hb_face_t *face = font->face;
614b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod  hb_uniscribe_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
615b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod  hb_uniscribe_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font);
6162a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  hb_uniscribe_shaper_funcs_t *funcs = face_data->funcs;
61702aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbod
6189a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod  /*
6199a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod   * Set up features.
6209a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod   */
6219a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod  hb_auto_array_t<OPENTYPE_FEATURE_RECORD> feature_records;
6229a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod  hb_auto_array_t<range_record_t> range_records;
6239a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod  if (num_features)
6249a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod  {
6259a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod    /* Sort features by start/end events. */
6269a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod    hb_auto_array_t<feature_event_t> feature_events;
6279a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod    for (unsigned int i = 0; i < num_features; i++)
6289a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod    {
6299a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod      active_feature_t feature;
6309a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod      feature.rec.tagFeature = hb_uint32_swap (features[i].tag);
6319a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod      feature.rec.lParameter = features[i].value;
6329a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod      feature.order = i;
6339a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod
6349a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod      feature_event_t *event;
6359a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod
6369a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod      event = feature_events.push ();
6379a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod      if (unlikely (!event))
6389a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	goto fail_features;
6399a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod      event->index = features[i].start;
6409a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod      event->start = true;
6419a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod      event->feature = feature;
6429a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod
6439a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod      event = feature_events.push ();
6449a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod      if (unlikely (!event))
6459a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	goto fail_features;
6469a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod      event->index = features[i].end;
6479a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod      event->start = false;
6489a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod      event->feature = feature;
6499a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod    }
650fb8cc86ff99c08064ac58a559bb66cc340693b92Behdad Esfahbod    feature_events.qsort ();
6519a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod    /* Add a strategic final event. */
6529a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod    {
6539a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod      active_feature_t feature;
6549a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod      feature.rec.tagFeature = 0;
6559a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod      feature.rec.lParameter = 0;
6569a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod      feature.order = num_features + 1;
6579a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod
6589a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod      feature_event_t *event = feature_events.push ();
6599a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod      if (unlikely (!event))
6609a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	goto fail_features;
6619a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod      event->index = 0; /* This value does magic. */
6629a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod      event->start = false;
6639a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod      event->feature = feature;
6649a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod    }
6659a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod
6669a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod    /* Scan events and save features for each range. */
6679a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod    hb_auto_array_t<active_feature_t> active_features;
6689a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod    unsigned int last_index = 0;
6699a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod    for (unsigned int i = 0; i < feature_events.len; i++)
6709a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod    {
6719a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod      feature_event_t *event = &feature_events[i];
6729a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod
6739a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod      if (event->index != last_index)
6749a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod      {
6759a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod        /* Save a snapshot of active features and the range. */
6769a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	range_record_t *range = range_records.push ();
6779a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	if (unlikely (!range))
6789a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	  goto fail_features;
6799a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod
6809a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	unsigned int offset = feature_records.len;
6819a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod
682fb8cc86ff99c08064ac58a559bb66cc340693b92Behdad Esfahbod	active_features.qsort ();
6839a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	for (unsigned int j = 0; j < active_features.len; j++)
6849a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	{
6859a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	  if (!j || active_features[j].rec.tagFeature != feature_records[feature_records.len - 1].tagFeature)
6869a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	  {
6879a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	    OPENTYPE_FEATURE_RECORD *feature = feature_records.push ();
6889a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	    if (unlikely (!feature))
6899a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	      goto fail_features;
6909a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	    *feature = active_features[j].rec;
6919a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	  }
6929a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	  else
6939a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	  {
6949a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	    /* Overrides value for existing feature. */
6959a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	    feature_records[feature_records.len - 1].lParameter = active_features[j].rec.lParameter;
6969a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	  }
6979a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	}
6989a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod
6999a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	/* Will convert to pointer after all is ready, since feature_records.array
7009a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	 * may move as we grow it. */
7019a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	range->props.potfRecords = reinterpret_cast<OPENTYPE_FEATURE_RECORD *> (offset);
7029a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	range->props.cotfRecords = feature_records.len - offset;
7039a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	range->index_first = last_index;
7049a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	range->index_last  = event->index - 1;
7059a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod
7069a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	last_index = event->index;
7079a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod      }
7089a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod
7099a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod      if (event->start) {
7109a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod        active_feature_t *feature = active_features.push ();
7119a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	if (unlikely (!feature))
7129a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	  goto fail_features;
7139a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	*feature = event->feature;
7149a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod      } else {
7159a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod        active_feature_t *feature = active_features.find (&event->feature);
7169a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	if (feature)
7179a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	  active_features.remove (feature - active_features.array);
7189a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod      }
7199a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod    }
7209a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod
7219a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod    if (!range_records.len) /* No active feature found. */
7229a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod      goto fail_features;
7239a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod
7249a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod    /* Fixup the pointers. */
7259a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod    for (unsigned int i = 0; i < range_records.len; i++)
7269a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod    {
7279a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod      range_record_t *range = &range_records[i];
72862cb28dfc668cae9cbff826229bde2271e157927Jonathan Kew      range->props.potfRecords = feature_records.array + reinterpret_cast<uintptr_t> (range->props.potfRecords);
7299a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod    }
7309a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod  }
7319a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod  else
7329a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod  {
7339a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod  fail_features:
7349a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod    num_features = 0;
7359a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod  }
7369a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod
737bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod#define FAIL(...) \
738bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  HB_STMT_START { \
739bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod    DEBUG_MSG (UNISCRIBE, NULL, __VA_ARGS__); \
7400594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod    return false; \
741bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  } HB_STMT_END;
742bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
743bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  HRESULT hr;
744bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
7450fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbodretry:
7460fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
7470fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  unsigned int scratch_size;
74868c372ed2eac76a6d347811293fe2ba2fd6a1eedBehdad Esfahbod  hb_buffer_t::scratch_buffer_t *scratch = buffer->get_scratch_buffer (&scratch_size);
7490fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
75068c372ed2eac76a6d347811293fe2ba2fd6a1eedBehdad Esfahbod#define ALLOCATE_ARRAY(Type, name, len) \
75168c372ed2eac76a6d347811293fe2ba2fd6a1eedBehdad Esfahbod  Type *name = (Type *) scratch; \
75268c372ed2eac76a6d347811293fe2ba2fd6a1eedBehdad Esfahbod  { \
75368c372ed2eac76a6d347811293fe2ba2fd6a1eedBehdad Esfahbod    unsigned int _consumed = DIV_CEIL ((len) * sizeof (Type), sizeof (*scratch)); \
75468c372ed2eac76a6d347811293fe2ba2fd6a1eedBehdad Esfahbod    assert (_consumed <= scratch_size); \
75568c372ed2eac76a6d347811293fe2ba2fd6a1eedBehdad Esfahbod    scratch += _consumed; \
75668c372ed2eac76a6d347811293fe2ba2fd6a1eedBehdad Esfahbod    scratch_size -= _consumed; \
75768c372ed2eac76a6d347811293fe2ba2fd6a1eedBehdad Esfahbod  }
7580fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
7590fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#define utf16_index() var1.u32
7600fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
76168c372ed2eac76a6d347811293fe2ba2fd6a1eedBehdad Esfahbod  ALLOCATE_ARRAY (WCHAR, pchars, buffer->len * 2);
76268c372ed2eac76a6d347811293fe2ba2fd6a1eedBehdad Esfahbod
7630fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  unsigned int chars_len = 0;
7649a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod  for (unsigned int i = 0; i < buffer->len; i++)
7659a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod  {
7660fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    hb_codepoint_t c = buffer->info[i].codepoint;
7670fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    buffer->info[i].utf16_index() = chars_len;
7687627100f428ac0ec8509d961d368d2d25d8f0b6eBehdad Esfahbod    if (likely (c <= 0xFFFFu))
7690fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod      pchars[chars_len++] = c;
7707627100f428ac0ec8509d961d368d2d25d8f0b6eBehdad Esfahbod    else if (unlikely (c > 0x10FFFFu))
7717627100f428ac0ec8509d961d368d2d25d8f0b6eBehdad Esfahbod      pchars[chars_len++] = 0xFFFDu;
7720fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    else {
7737627100f428ac0ec8509d961d368d2d25d8f0b6eBehdad Esfahbod      pchars[chars_len++] = 0xD800u + ((c - 0x10000u) >> 10);
7747627100f428ac0ec8509d961d368d2d25d8f0b6eBehdad Esfahbod      pchars[chars_len++] = 0xDC00u + ((c - 0x10000u) & ((1 << 10) - 1));
7750fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    }
7760fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  }
7770fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
7780fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  ALLOCATE_ARRAY (WORD, log_clusters, chars_len);
7790fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  ALLOCATE_ARRAY (SCRIPT_CHARPROP, char_props, chars_len);
7800fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
7819a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod  if (num_features)
7829a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod  {
7839a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod    /* Need log_clusters to assign features. */
7849a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod    chars_len = 0;
7859a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod    for (unsigned int i = 0; i < buffer->len; i++)
7869a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod    {
7879a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod      hb_codepoint_t c = buffer->info[i].codepoint;
7889a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod      unsigned int cluster = buffer->info[i].cluster;
7899a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod      log_clusters[chars_len++] = cluster;
7907627100f428ac0ec8509d961d368d2d25d8f0b6eBehdad Esfahbod      if (hb_in_range (c, 0x10000u, 0x10FFFFu))
7919a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	log_clusters[chars_len++] = cluster; /* Surrogates. */
7929a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod    }
7939a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod  }
7949a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod
7953216e44feb7b97f44620b51e197425a80a41cdb7Behdad Esfahbod  /* The -2 in the following is to compensate for possible
7963216e44feb7b97f44620b51e197425a80a41cdb7Behdad Esfahbod   * alignment needed after the WORD array.  sizeof(WORD) == 2. */
7973216e44feb7b97f44620b51e197425a80a41cdb7Behdad Esfahbod  unsigned int glyphs_size = (scratch_size * sizeof (int) - 2)
7983216e44feb7b97f44620b51e197425a80a41cdb7Behdad Esfahbod			   / (sizeof (WORD) +
7993216e44feb7b97f44620b51e197425a80a41cdb7Behdad Esfahbod			      sizeof (SCRIPT_GLYPHPROP) +
8003216e44feb7b97f44620b51e197425a80a41cdb7Behdad Esfahbod			      sizeof (int) +
8013216e44feb7b97f44620b51e197425a80a41cdb7Behdad Esfahbod			      sizeof (GOFFSET) +
8023216e44feb7b97f44620b51e197425a80a41cdb7Behdad Esfahbod			      sizeof (uint32_t));
8030fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
8040fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  ALLOCATE_ARRAY (WORD, glyphs, glyphs_size);
8050fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  ALLOCATE_ARRAY (SCRIPT_GLYPHPROP, glyph_props, glyphs_size);
8060fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  ALLOCATE_ARRAY (int, advances, glyphs_size);
8070fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  ALLOCATE_ARRAY (GOFFSET, offsets, glyphs_size);
8080fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  ALLOCATE_ARRAY (uint32_t, vis_clusters, glyphs_size);
8090fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
8102a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod  /* Note:
8112a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod   * We can't touch the contents of glyph_props.  Our fallback
8122a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod   * implementations of Shape and Place functions use that buffer
8132a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod   * by casting it to a different type.  It works because they
8142a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod   * both agree about it, but if we want to access it here we
8152a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod   * need address that issue first.
8162a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod   */
8172a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod
81891e721ea8693205f4f738bca97a5055ee75cf463Behdad Esfahbod#undef ALLOCATE_ARRAY
8190fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
820872969126756456a69bf958f3df6e56a26e57b0aBehdad Esfahbod#define MAX_ITEMS 256
8210fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
8220fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  SCRIPT_ITEM items[MAX_ITEMS + 1];
8235c299343118d1eaff32ffb2a5dac077cfff67deeBehdad Esfahbod  SCRIPT_CONTROL bidi_control = {0};
8240fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  SCRIPT_STATE bidi_state = {0};
8257c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  ULONG script_tags[MAX_ITEMS];
8260fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  int item_count;
8270fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
8285c299343118d1eaff32ffb2a5dac077cfff67deeBehdad Esfahbod  /* MinGW32 doesn't define fMergeNeutralItems, so we bruteforce */
8290594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod  //bidi_control.fMergeNeutralItems = true;
8305c299343118d1eaff32ffb2a5dac077cfff67deeBehdad Esfahbod  *(uint32_t*)&bidi_control |= 1<<24;
8315c299343118d1eaff32ffb2a5dac077cfff67deeBehdad Esfahbod
8320fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  bidi_state.uBidiLevel = HB_DIRECTION_IS_FORWARD (buffer->props.direction) ? 0 : 1;
83329eac8f591fdb86f1c4fdc0a6ab63910ff286b84Behdad Esfahbod  bidi_state.fOverrideDirection = 1;
8340fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
83568c372ed2eac76a6d347811293fe2ba2fd6a1eedBehdad Esfahbod  hr = funcs->ScriptItemizeOpenType (pchars,
8362a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod				     chars_len,
8372a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod				     MAX_ITEMS,
8382a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod				     &bidi_control,
8392a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod				     &bidi_state,
8402a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod				     items,
8412a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod				     script_tags,
8422a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod				     &item_count);
8430fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  if (unlikely (FAILED (hr)))
8442eb474afb4a09f4da8f14b444bd6066769010224Behdad Esfahbod    FAIL ("ScriptItemizeOpenType() failed: 0x%08xL", hr);
8450fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
8460fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#undef MAX_ITEMS
8470fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
8489a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod  OPENTYPE_TAG language_tag = hb_uint32_swap (hb_ot_tag_from_language (buffer->props.language));
84938d5c58d23fce38221689cda98cea1c3e42ed615Behdad Esfahbod  hb_auto_array_t<TEXTRANGE_PROPERTIES*> range_properties;
85038d5c58d23fce38221689cda98cea1c3e42ed615Behdad Esfahbod  hb_auto_array_t<int> range_char_counts;
8510fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
8520fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  unsigned int glyphs_offset = 0;
8530fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  unsigned int glyphs_len;
854b069c3c31bfbbf160eb897c7474be9ea90ed4fc1Behdad Esfahbod  bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
8553409fb1c767118067cf7edfb97068936b6f4b717Behdad Esfahbod  for (unsigned int i = 0; i < item_count; i++)
8560fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  {
8570dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod    unsigned int chars_offset = items[i].iCharPos;
8580dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod    unsigned int item_chars_len = items[i + 1].iCharPos - chars_offset;
8590dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod
86038d5c58d23fce38221689cda98cea1c3e42ed615Behdad Esfahbod    if (num_features)
86138d5c58d23fce38221689cda98cea1c3e42ed615Behdad Esfahbod    {
86238d5c58d23fce38221689cda98cea1c3e42ed615Behdad Esfahbod      range_properties.shrink (0);
8639a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod      range_char_counts.shrink (0);
86438d5c58d23fce38221689cda98cea1c3e42ed615Behdad Esfahbod
8659a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod      range_record_t *last_range = &range_records[0];
86638d5c58d23fce38221689cda98cea1c3e42ed615Behdad Esfahbod
8679a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod      for (unsigned int k = chars_offset; k < chars_offset + item_chars_len; k++)
8689a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod      {
8699a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	range_record_t *range = last_range;
8709a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	while (log_clusters[k] < range->index_first)
8719a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	  range--;
8729a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	while (log_clusters[k] > range->index_last)
8739a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	  range++;
8749a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	if (!range_properties.len ||
8759a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	    &range->props != range_properties[range_properties.len - 1])
8769a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	{
8779a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	  TEXTRANGE_PROPERTIES **props = range_properties.push ();
8789a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	  int *c = range_char_counts.push ();
8799a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	  if (unlikely (!props || !c))
8809a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	  {
8819a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	    range_properties.shrink (0);
8829a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	    range_char_counts.shrink (0);
8839a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	    break;
8849a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	  }
8859a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	  *props = &range->props;
8869a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	  *c = 1;
8879a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	}
8889a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	else
8899a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	{
8909a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	  range_char_counts[range_char_counts.len - 1]++;
8919a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	}
8929a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod
8939a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod	last_range = range;
8949a175914d72187d0c3f50ddad50c9569649c3072Behdad Esfahbod      }
89538d5c58d23fce38221689cda98cea1c3e42ed615Behdad Esfahbod    }
89638d5c58d23fce38221689cda98cea1c3e42ed615Behdad Esfahbod
8973409fb1c767118067cf7edfb97068936b6f4b717Behdad Esfahbod    /* Asking for glyphs in logical order circumvents at least
8983409fb1c767118067cf7edfb97068936b6f4b717Behdad Esfahbod     * one bug in Uniscribe. */
8993409fb1c767118067cf7edfb97068936b6f4b717Behdad Esfahbod    items[i].a.fLogicalOrder = true;
9003409fb1c767118067cf7edfb97068936b6f4b717Behdad Esfahbod
901e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod  retry_shape:
9022a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod    hr = funcs->ScriptShapeOpenType (font_data->hdc,
9032a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod				     &font_data->script_cache,
9042a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod				     &items[i].a,
9052a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod				     script_tags[i],
9062a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod				     language_tag,
90738d5c58d23fce38221689cda98cea1c3e42ed615Behdad Esfahbod				     range_char_counts.array,
90838d5c58d23fce38221689cda98cea1c3e42ed615Behdad Esfahbod				     range_properties.array,
90938d5c58d23fce38221689cda98cea1c3e42ed615Behdad Esfahbod				     range_properties.len,
91068c372ed2eac76a6d347811293fe2ba2fd6a1eedBehdad Esfahbod				     pchars + chars_offset,
9112a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod				     item_chars_len,
9122a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod				     glyphs_size - glyphs_offset,
9132a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod				     /* out */
9142a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod				     log_clusters + chars_offset,
9152a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod				     char_props + chars_offset,
9162a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod				     glyphs + glyphs_offset,
9172a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod				     glyph_props + glyphs_offset,
9182a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod				     (int *) &glyphs_len);
9190dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod
9200dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod    if (unlikely (items[i].a.fNoGlyphIndex))
9210dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod      FAIL ("ScriptShapeOpenType() set fNoGlyphIndex");
922eaf1e93ef1ee19a3e72d781e8abbd7f1165c1618Behdad Esfahbod    if (unlikely (hr == E_OUTOFMEMORY || hr == E_NOT_SUFFICIENT_BUFFER))
9230dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod    {
92415c633dd1f412f9ef839d80a8f7af35e7ea48fbcBehdad Esfahbod      if (unlikely (!buffer->ensure (buffer->allocated * 2)))
9250dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod	FAIL ("Buffer resize failed");
9260dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod      goto retry;
9270dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod    }
9280dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod    if (unlikely (hr == USP_E_SCRIPT_NOT_IN_FONT))
929e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod    {
930e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod      if (items[i].a.eScript == SCRIPT_UNDEFINED)
931e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod	FAIL ("ScriptShapeOpenType() failed: Font doesn't support script");
932e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod      items[i].a.eScript = SCRIPT_UNDEFINED;
933e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod      goto retry_shape;
934e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod    }
9350dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod    if (unlikely (FAILED (hr)))
936e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod    {
9370dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod      FAIL ("ScriptShapeOpenType() failed: 0x%08xL", hr);
938e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod    }
939e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod
940e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod    for (unsigned int j = chars_offset; j < chars_offset + item_chars_len; j++)
941e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod      log_clusters[j] += glyphs_offset;
9420dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod
9432a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod    hr = funcs->ScriptPlaceOpenType (font_data->hdc,
9442a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod				     &font_data->script_cache,
9452a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod				     &items[i].a,
9462a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod				     script_tags[i],
9472a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod				     language_tag,
94838d5c58d23fce38221689cda98cea1c3e42ed615Behdad Esfahbod				     range_char_counts.array,
94938d5c58d23fce38221689cda98cea1c3e42ed615Behdad Esfahbod				     range_properties.array,
95038d5c58d23fce38221689cda98cea1c3e42ed615Behdad Esfahbod				     range_properties.len,
95168c372ed2eac76a6d347811293fe2ba2fd6a1eedBehdad Esfahbod				     pchars + chars_offset,
9522a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod				     log_clusters + chars_offset,
9532a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod				     char_props + chars_offset,
9542a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod				     item_chars_len,
9552a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod				     glyphs + glyphs_offset,
9562a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod				     glyph_props + glyphs_offset,
9572a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod				     glyphs_len,
9582a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod				     /* out */
9592a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod				     advances + glyphs_offset,
9602a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod				     offsets + glyphs_offset,
9612a17f9568d9724e045d2c1d660e007f3acd747d9Behdad Esfahbod				     NULL);
9620dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod    if (unlikely (FAILED (hr)))
9630dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod      FAIL ("ScriptPlaceOpenType() failed: 0x%08xL", hr);
9640dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod
9651d05fdd09fa271b641f30a2138171e6fafcd8db7Behdad Esfahbod    if (DEBUG_ENABLED (UNISCRIBE))
9661d05fdd09fa271b641f30a2138171e6fafcd8db7Behdad Esfahbod      fprintf (stderr, "Item %d RTL %d LayoutRTL %d LogicalOrder %d ScriptTag %c%c%c%c\n",
9671d05fdd09fa271b641f30a2138171e6fafcd8db7Behdad Esfahbod	       i,
9681d05fdd09fa271b641f30a2138171e6fafcd8db7Behdad Esfahbod	       items[i].a.fRTL,
9691d05fdd09fa271b641f30a2138171e6fafcd8db7Behdad Esfahbod	       items[i].a.fLayoutRTL,
9701d05fdd09fa271b641f30a2138171e6fafcd8db7Behdad Esfahbod	       items[i].a.fLogicalOrder,
9711d05fdd09fa271b641f30a2138171e6fafcd8db7Behdad Esfahbod	       HB_UNTAG (hb_uint32_swap (script_tags[i])));
9721d05fdd09fa271b641f30a2138171e6fafcd8db7Behdad Esfahbod
9730dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod    glyphs_offset += glyphs_len;
9740fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  }
9750fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  glyphs_len = glyphs_offset;
9760fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
9770fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  /* Ok, we've got everything we need, now compose output buffer,
9780fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod   * very, *very*, carefully! */
9790fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
9800fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  /* Calculate visual-clusters.  That's what we ship. */
9815c299343118d1eaff32ffb2a5dac077cfff67deeBehdad Esfahbod  for (unsigned int i = 0; i < glyphs_len; i++)
9825c299343118d1eaff32ffb2a5dac077cfff67deeBehdad Esfahbod    vis_clusters[i] = -1;
983577326b86af80cc137eea81f4cc1e30adf9232b1Behdad Esfahbod  for (unsigned int i = 0; i < buffer->len; i++) {
984577326b86af80cc137eea81f4cc1e30adf9232b1Behdad Esfahbod    uint32_t *p = &vis_clusters[log_clusters[buffer->info[i].utf16_index()]];
985577326b86af80cc137eea81f4cc1e30adf9232b1Behdad Esfahbod    *p = MIN (*p, buffer->info[i].cluster);
986577326b86af80cc137eea81f4cc1e30adf9232b1Behdad Esfahbod  }
9873409fb1c767118067cf7edfb97068936b6f4b717Behdad Esfahbod  for (unsigned int i = 1; i < glyphs_len; i++)
9883409fb1c767118067cf7edfb97068936b6f4b717Behdad Esfahbod    if (vis_clusters[i] == -1)
9893409fb1c767118067cf7edfb97068936b6f4b717Behdad Esfahbod      vis_clusters[i] = vis_clusters[i - 1];
9900fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
9910fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#undef utf16_index
9920fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
99315c633dd1f412f9ef839d80a8f7af35e7ea48fbcBehdad Esfahbod  if (unlikely (!buffer->ensure (glyphs_len)))
99402aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbod    FAIL ("Buffer in error");
9950fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
99602aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbod#undef FAIL
9970fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
9980fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  /* Set glyph infos */
999d753ac78da5619a0a545cdaf7a8e65787e996570Behdad Esfahbod  buffer->len = 0;
10000fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  for (unsigned int i = 0; i < glyphs_len; i++)
10010fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  {
1002d753ac78da5619a0a545cdaf7a8e65787e996570Behdad Esfahbod    hb_glyph_info_t *info = &buffer->info[buffer->len++];
10030fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
10040fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    info->codepoint = glyphs[i];
10050fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    info->cluster = vis_clusters[i];
10060fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
10070fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    /* The rest is crap.  Let's store position info there for now. */
10080fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    info->mask = advances[i];
1009163c435f1807c138da9f74f09d29d913eb9e29e9Behdad Esfahbod    info->var1.i32 = offsets[i].du;
1010163c435f1807c138da9f74f09d29d913eb9e29e9Behdad Esfahbod    info->var2.i32 = offsets[i].dv;
10110fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  }
10120fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
10130fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  /* Set glyph positions */
10140fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  buffer->clear_positions ();
10157c5bee09d9c7c25672c7c77572ebae0b731892d0Behdad Esfahbod  double x_mult = font_data->x_mult, y_mult = font_data->y_mult;
10160fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  for (unsigned int i = 0; i < glyphs_len; i++)
10170fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  {
10180fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    hb_glyph_info_t *info = &buffer->info[i];
10190fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    hb_glyph_position_t *pos = &buffer->pos[i];
10200fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
10210fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    /* TODO vertical */
1022e6d5e4c3106180cb22253c2c278b40f7c4c98f2fBehdad Esfahbod    pos->x_advance = x_mult * (int32_t) info->mask;
1023163c435f1807c138da9f74f09d29d913eb9e29e9Behdad Esfahbod    pos->x_offset = x_mult * (backward ? -info->var1.i32 : info->var1.i32);
1024163c435f1807c138da9f74f09d29d913eb9e29e9Behdad Esfahbod    pos->y_offset = y_mult * info->var2.i32;
10250fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  }
10260fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
10273409fb1c767118067cf7edfb97068936b6f4b717Behdad Esfahbod  if (backward)
10283409fb1c767118067cf7edfb97068936b6f4b717Behdad Esfahbod    hb_buffer_reverse (buffer);
10293409fb1c767118067cf7edfb97068936b6f4b717Behdad Esfahbod
10300fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  /* Wow, done! */
10310594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod  return true;
10320fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod}
10330fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
10340fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
1035