15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
2f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * Copyright © 2011,2012,2013  Google, Inc.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  This is part of HarfBuzz, a text shaping library.
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Permission is hereby granted, without written agreement and without
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * license or royalty fees, to use, copy, modify, and distribute this
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * software and its documentation for any purpose, provided that the
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * above copyright notice and the following two paragraphs appear in
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * all copies of this software.
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * DAMAGE.
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Google Author(s): Behdad Esfahbod
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HB_SHAPER uniscribe
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "hb-shaper-impl-private.hh"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h>
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <usp10.h>
32f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include <rpc.h>
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "hb-uniscribe.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "hb-open-file-private.hh"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "hb-ot-name-table.hh"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "hb-ot-tag.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef HB_DEBUG_UNISCRIBE
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HB_DEBUG_UNISCRIBE (HB_DEBUG+0)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)typedef HRESULT (WINAPI *SIOT) /*ScriptItemizeOpenType*/(
47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const WCHAR *pwcInChars,
48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int cInChars,
49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int cMaxItems,
50f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const SCRIPT_CONTROL *psControl,
51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const SCRIPT_STATE *psState,
52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SCRIPT_ITEM *pItems,
53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  OPENTYPE_TAG *pScriptTags,
54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int *pcItems
55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles));
56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)typedef HRESULT (WINAPI *SSOT) /*ScriptShapeOpenType*/(
58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  HDC hdc,
59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SCRIPT_CACHE *psc,
60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SCRIPT_ANALYSIS *psa,
61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  OPENTYPE_TAG tagScript,
62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  OPENTYPE_TAG tagLangSys,
63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int *rcRangeChars,
64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  TEXTRANGE_PROPERTIES **rpRangeProperties,
65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int cRanges,
66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const WCHAR *pwcChars,
67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int cChars,
68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int cMaxGlyphs,
69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  WORD *pwLogClust,
70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SCRIPT_CHARPROP *pCharProps,
71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  WORD *pwOutGlyphs,
72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SCRIPT_GLYPHPROP *pOutGlyphProps,
73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int *pcGlyphs
74f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles));
75f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)typedef HRESULT (WINAPI *SPOT) /*ScriptPlaceOpenType*/(
77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  HDC hdc,
78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SCRIPT_CACHE *psc,
79f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SCRIPT_ANALYSIS *psa,
80f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  OPENTYPE_TAG tagScript,
81f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  OPENTYPE_TAG tagLangSys,
82f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int *rcRangeChars,
83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  TEXTRANGE_PROPERTIES **rpRangeProperties,
84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int cRanges,
85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const WCHAR *pwcChars,
86f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  WORD *pwLogClust,
87f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SCRIPT_CHARPROP *pCharProps,
88f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int cChars,
89f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const WORD *pwGlyphs,
90f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const SCRIPT_GLYPHPROP *pGlyphProps,
91f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int cGlyphs,
92f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int *piAdvance,
93f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  GOFFSET *pGoffset,
94f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ABC *pABC
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles));
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
98f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)/* Fallback implementations. */
99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
100f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)static HRESULT WINAPI
101f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)hb_ScriptItemizeOpenType(
102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const WCHAR *pwcInChars,
103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int cInChars,
104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int cMaxItems,
105f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const SCRIPT_CONTROL *psControl,
106f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const SCRIPT_STATE *psState,
107f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SCRIPT_ITEM *pItems,
108f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  OPENTYPE_TAG *pScriptTags,
109f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int *pcItems
110f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles))
111f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles){
112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles){
113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return ScriptItemize (pwcInChars,
114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)			cInChars,
115f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)			cMaxItems,
116f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)			psControl,
117f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)			psState,
118f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)			pItems,
119f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)			pcItems);
120f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
121f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
122f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
123f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)static HRESULT WINAPI
124f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)hb_ScriptShapeOpenType(
125f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  HDC hdc,
126f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SCRIPT_CACHE *psc,
127f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SCRIPT_ANALYSIS *psa,
128f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  OPENTYPE_TAG tagScript,
129f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  OPENTYPE_TAG tagLangSys,
130f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int *rcRangeChars,
131f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  TEXTRANGE_PROPERTIES **rpRangeProperties,
132f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int cRanges,
133f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const WCHAR *pwcChars,
134f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int cChars,
135f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int cMaxGlyphs,
136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  WORD *pwLogClust,
137f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SCRIPT_CHARPROP *pCharProps,
138f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  WORD *pwOutGlyphs,
139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SCRIPT_GLYPHPROP *pOutGlyphProps,
140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int *pcGlyphs
141f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles))
142f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles){
143f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SCRIPT_VISATTR *psva = (SCRIPT_VISATTR *) pOutGlyphProps;
144f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return ScriptShape (hdc,
145f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)		      psc,
146f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)		      pwcChars,
147f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)		      cChars,
148f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)		      cMaxGlyphs,
149f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)		      psa,
150f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)		      pwOutGlyphs,
151f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)		      pwLogClust,
152f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)		      psva,
153f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)		      pcGlyphs);
154f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
155f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
156f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)static HRESULT WINAPI
157f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)hb_ScriptPlaceOpenType(
158f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  HDC hdc,
159f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SCRIPT_CACHE *psc,
160f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SCRIPT_ANALYSIS *psa,
161f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  OPENTYPE_TAG tagScript,
162f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  OPENTYPE_TAG tagLangSys,
163f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int *rcRangeChars,
164f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  TEXTRANGE_PROPERTIES **rpRangeProperties,
165f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int cRanges,
166f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const WCHAR *pwcChars,
167f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  WORD *pwLogClust,
168f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SCRIPT_CHARPROP *pCharProps,
169f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int cChars,
170f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const WORD *pwGlyphs,
171f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const SCRIPT_GLYPHPROP *pGlyphProps,
172f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int cGlyphs,
173f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int *piAdvance,
174f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  GOFFSET *pGoffset,
175f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ABC *pABC
176f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles))
177f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles){
178f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SCRIPT_VISATTR *psva = (SCRIPT_VISATTR *) pGlyphProps;
179f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return ScriptPlace (hdc,
180f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)		      psc,
181f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)		      pwGlyphs,
182f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)		      cGlyphs,
183f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)		      psva,
184f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)		      psa,
185f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)		      piAdvance,
186f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)		      pGoffset,
187f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)		      pABC);
188f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
189f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
190f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
191f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)struct hb_uniscribe_shaper_funcs_t {
192f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SIOT ScriptItemizeOpenType;
193f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SSOT ScriptShapeOpenType;
194f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SPOT ScriptPlaceOpenType;
195f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
196f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  inline void init (void)
197f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  {
198f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    HMODULE hinstLib;
199f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    this->ScriptItemizeOpenType = NULL;
200f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    this->ScriptShapeOpenType   = NULL;
201f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    this->ScriptPlaceOpenType   = NULL;
202f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
203f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    hinstLib = GetModuleHandle (TEXT ("usp10.dll"));
204f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (hinstLib)
205f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    {
206f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      this->ScriptItemizeOpenType = (SIOT) GetProcAddress (hinstLib, "ScriptItemizeOpenType");
207f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      this->ScriptShapeOpenType   = (SSOT) GetProcAddress (hinstLib, "ScriptShapeOpenType");
208f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      this->ScriptPlaceOpenType   = (SPOT) GetProcAddress (hinstLib, "ScriptPlaceOpenType");
209f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
210f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (!this->ScriptItemizeOpenType ||
211f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	!this->ScriptShapeOpenType   ||
212f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	!this->ScriptPlaceOpenType)
213f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    {
214f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      DEBUG_MSG (UNISCRIBE, NULL, "OpenType versions of functions not found; falling back.");
215f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      this->ScriptItemizeOpenType = hb_ScriptItemizeOpenType;
216f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      this->ScriptShapeOpenType   = hb_ScriptShapeOpenType;
217f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      this->ScriptPlaceOpenType   = hb_ScriptPlaceOpenType;
218f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
219f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
220f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)};
221f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)static hb_uniscribe_shaper_funcs_t *uniscribe_funcs;
222f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
223f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)static inline void
224f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)free_uniscribe_funcs (void)
225f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles){
226f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  free (uniscribe_funcs);
227f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
228f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
229f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)static hb_uniscribe_shaper_funcs_t *
230f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)hb_uniscribe_shaper_get_funcs (void)
231f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles){
232f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)retry:
233f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  hb_uniscribe_shaper_funcs_t *funcs = (hb_uniscribe_shaper_funcs_t *) hb_atomic_ptr_get (&uniscribe_funcs);
234f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
235f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (unlikely (!funcs))
236f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  {
237f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    funcs = (hb_uniscribe_shaper_funcs_t *) calloc (1, sizeof (hb_uniscribe_shaper_funcs_t));
238f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (unlikely (!funcs))
239f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return NULL;
240f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
241f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    funcs->init ();
242f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
243f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (!hb_atomic_ptr_cmpexch (&uniscribe_funcs, NULL, funcs)) {
244f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      free (funcs);
245f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      goto retry;
246f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
247f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
24803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#ifdef HB_USE_ATEXIT
249f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    atexit (free_uniscribe_funcs); /* First person registers atexit() callback. */
250f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#endif
251f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
252f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
253f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return funcs;
254f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
255f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
256f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
257f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)struct active_feature_t {
258f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  OPENTYPE_FEATURE_RECORD rec;
259f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  unsigned int order;
260f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
261f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  static int cmp (const active_feature_t *a, const active_feature_t *b) {
262f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return a->rec.tagFeature < b->rec.tagFeature ? -1 : a->rec.tagFeature > b->rec.tagFeature ? 1 :
263f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	   a->order < b->order ? -1 : a->order > b->order ? 1 :
264f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	   a->rec.lParameter < b->rec.lParameter ? -1 : a->rec.lParameter > b->rec.lParameter ? 1 :
265f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	   0;
266f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
267f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  bool operator== (const active_feature_t *f) {
268f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return cmp (this, f) == 0;
269f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
270f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)};
271f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
272f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)struct feature_event_t {
273f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  unsigned int index;
274f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  bool start;
275f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  active_feature_t feature;
276f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
277f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  static int cmp (const feature_event_t *a, const feature_event_t *b) {
278f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return a->index < b->index ? -1 : a->index > b->index ? 1 :
279f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	   a->start < b->start ? -1 : a->start > b->start ? 1 :
280f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	   active_feature_t::cmp (&a->feature, &b->feature);
281f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
282f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)};
283f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
284f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)struct range_record_t {
285f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  TEXTRANGE_PROPERTIES props;
286f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  unsigned int index_first; /* == start */
287f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  unsigned int index_last;  /* == end - 1 */
288f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)};
289f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HB_SHAPER_DATA_ENSURE_DECLARE(uniscribe, face)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HB_SHAPER_DATA_ENSURE_DECLARE(uniscribe, font)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * shaper face data
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct hb_uniscribe_shaper_face_data_t {
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HANDLE fh;
300f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  hb_uniscribe_shaper_funcs_t *funcs;
301f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  wchar_t face_name[LF_FACESIZE];
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
304f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)/* face_name should point to a wchar_t[LF_FACESIZE] object. */
305f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)static void
306f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)_hb_generate_unique_face_name (wchar_t *face_name, unsigned int *plen)
307f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles){
308f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  /* We'll create a private name for the font from a UUID using a simple,
309f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)   * somewhat base64-like encoding scheme */
310f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const char *enc = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-";
311f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  UUID id;
312f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  UuidCreate ((UUID*) &id);
31303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ASSERT_STATIC (2 + 3 * (16/2) < LF_FACESIZE);
314f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  unsigned int name_str_len = 0;
315f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  face_name[name_str_len++] = 'F';
316f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  face_name[name_str_len++] = '_';
317f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  unsigned char *p = (unsigned char *) &id;
318f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (unsigned int i = 0; i < 16; i += 2)
319f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  {
320f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    /* Spread the 16 bits from two bytes of the UUID across three chars of face_name,
321f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)     * using the bits in groups of 5,5,6 to select chars from enc.
322f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)     * This will generate 24 characters; with the 'F_' prefix we already provided,
323f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)     * the name will be 26 chars (plus the NUL terminator), so will always fit within
324f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)     * face_name (LF_FACESIZE = 32). */
325f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    face_name[name_str_len++] = enc[p[i] >> 3];
326f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    face_name[name_str_len++] = enc[((p[i] << 2) | (p[i + 1] >> 6)) & 0x1f];
327f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    face_name[name_str_len++] = enc[p[i + 1] & 0x3f];
328f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
329f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  face_name[name_str_len] = 0;
330f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (plen)
331f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    *plen = name_str_len;
332f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
333f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
334f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)/* Destroys blob. */
335f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)static hb_blob_t *
336f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)_hb_rename_font (hb_blob_t *blob, wchar_t *new_name)
337f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles){
338f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  /* Create a copy of the font data, with the 'name' table replaced by a
339f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)   * table that names the font with our private F_* name created above.
340f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)   * For simplicity, we just append a new 'name' table and update the
341f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)   * sfnt directory; the original table is left in place, but unused.
342f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)   *
343f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)   * The new table will contain just 5 name IDs: family, style, unique,
344f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)   * full, PS. All of them point to the same name data with our unique name.
345f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)   */
346f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
347f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  blob = OT::Sanitizer<OT::OpenTypeFontFile>::sanitize (blob);
348f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
349f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  unsigned int length, new_length, name_str_len;
350f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const char *orig_sfnt_data = hb_blob_get_data (blob, &length);
351f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
352f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  _hb_generate_unique_face_name (new_name, &name_str_len);
353f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
354f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  static const uint16_t name_IDs[] = { 1, 2, 3, 4, 6 };
355f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
356f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  unsigned int name_table_length = OT::name::min_size +
357f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                   ARRAY_LENGTH (name_IDs) * OT::NameRecord::static_size +
358f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                   name_str_len * 2; /* for name data in UTF16BE form */
359f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  unsigned int name_table_offset = (length + 3) & ~3;
360f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
361f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  new_length = name_table_offset + ((name_table_length + 3) & ~3);
362f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  void *new_sfnt_data = calloc (1, new_length);
363f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!new_sfnt_data)
364f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  {
365f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    hb_blob_destroy (blob);
366f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return NULL;
367f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
368f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
369f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  memcpy(new_sfnt_data, orig_sfnt_data, length);
370f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
371f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  OT::name &name = OT::StructAtOffset<OT::name> (new_sfnt_data, name_table_offset);
372f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  name.format.set (0);
373f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  name.count.set (ARRAY_LENGTH (name_IDs));
374f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  name.stringOffset.set (name.get_size ());
375f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (unsigned int i = 0; i < ARRAY_LENGTH (name_IDs); i++)
376f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  {
377f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    OT::NameRecord &record = name.nameRecord[i];
378f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    record.platformID.set (3);
379f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    record.encodingID.set (1);
3805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    record.languageID.set (0x0409u); /* English */
381f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    record.nameID.set (name_IDs[i]);
382f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    record.length.set (name_str_len * 2);
383f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    record.offset.set (0);
384f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
385f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
386f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  /* Copy string data from new_name, converting wchar_t to UTF16BE. */
387f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  unsigned char *p = &OT::StructAfter<unsigned char> (name);
388f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (unsigned int i = 0; i < name_str_len; i++)
389f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  {
390f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    *p++ = new_name[i] >> 8;
391f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    *p++ = new_name[i] & 0xff;
392f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
393f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
394f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  /* Adjust name table entry to point to new name table */
395f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const OT::OpenTypeFontFile &file = * (OT::OpenTypeFontFile *) (new_sfnt_data);
396f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  unsigned int face_count = file.get_face_count ();
397f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (unsigned int face_index = 0; face_index < face_count; face_index++)
398f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  {
399f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    /* Note: doing multiple edits (ie. TTC) can be unsafe.  There may be
400f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)     * toe-stepping.  But we don't really care. */
401f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const OT::OpenTypeFontFace &face = file.get_face (face_index);
402f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    unsigned int index;
403f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (face.find_table_index (HB_OT_TAG_name, &index))
404f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    {
405f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      OT::TableRecord &record = const_cast<OT::TableRecord &> (face.get_table (index));
406f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      record.checkSum.set_for_data (&name, name_table_length);
407f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      record.offset.set (name_table_offset);
408f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      record.length.set (name_table_length);
409f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
410f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    else if (face_index == 0) /* Fail if first face doesn't have 'name' table. */
411f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    {
412f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      free (new_sfnt_data);
413f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      hb_blob_destroy (blob);
414f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return NULL;
415f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
416f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
417f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
418f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  /* The checkSumAdjustment field in the 'head' table is now wrong,
419f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)   * but that doesn't actually seem to cause any problems so we don't
420f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)   * bother. */
421f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
422f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  hb_blob_destroy (blob);
423f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return hb_blob_create ((const char *) new_sfnt_data, new_length,
424f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)			 HB_MEMORY_MODE_WRITABLE, NULL, free);
425f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
426f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_uniscribe_shaper_face_data_t *
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_hb_uniscribe_shaper_face_data_create (hb_face_t *face)
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hb_uniscribe_shaper_face_data_t *data = (hb_uniscribe_shaper_face_data_t *) calloc (1, sizeof (hb_uniscribe_shaper_face_data_t));
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (unlikely (!data))
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
434f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  data->funcs = hb_uniscribe_shaper_get_funcs ();
435f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (unlikely (!data->funcs))
436f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  {
437f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    free (data);
438f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return NULL;
439f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
440f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hb_blob_t *blob = hb_face_reference_blob (face);
442f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (unlikely (!hb_blob_get_length (blob)))
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DEBUG_MSG (UNISCRIBE, face, "Face has empty blob");
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  blob = _hb_rename_font (blob, data->face_name);
446f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (unlikely (!blob))
447f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  {
448f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    free (data);
449f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return NULL;
450f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
451f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD num_fonts_installed;
453f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  data->fh = AddFontMemResourceEx ((void *) hb_blob_get_data (blob, NULL),
454f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				   hb_blob_get_length (blob),
455f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				   0, &num_fonts_installed);
456f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (unlikely (!data->fh))
457f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  {
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DEBUG_MSG (UNISCRIBE, face, "Face AddFontMemResourceEx() failed");
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    free (data);
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return data;
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_hb_uniscribe_shaper_face_data_destroy (hb_uniscribe_shaper_face_data_t *data)
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RemoveFontMemResourceEx (data->fh);
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  free (data);
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * shaper font data
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct hb_uniscribe_shaper_font_data_t {
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HDC hdc;
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOGFONTW log_font;
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HFONT hfont;
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SCRIPT_CACHE script_cache;
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)populate_log_font (LOGFONTW  *lf,
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		   hb_font_t *font)
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset (lf, 0, sizeof (*lf));
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  lf->lfHeight = -font->y_scale;
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  lf->lfCharSet = DEFAULT_CHARSET;
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
493f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  hb_face_t *face = font->face;
494f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  hb_uniscribe_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
496f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  memcpy (lf->lfFaceName, face_data->face_name, sizeof (lf->lfFaceName));
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_uniscribe_shaper_font_data_t *
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_hb_uniscribe_shaper_font_data_create (hb_font_t *font)
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (unlikely (!hb_uniscribe_shaper_face_data_ensure (font->face))) return NULL;
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hb_uniscribe_shaper_font_data_t *data = (hb_uniscribe_shaper_font_data_t *) calloc (1, sizeof (hb_uniscribe_shaper_font_data_t));
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (unlikely (!data))
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data->hdc = GetDC (NULL);
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (unlikely (!populate_log_font (&data->log_font, font))) {
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DEBUG_MSG (UNISCRIBE, font, "Font populate_log_font() failed");
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    _hb_uniscribe_shaper_font_data_destroy (data);
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data->hfont = CreateFontIndirectW (&data->log_font);
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (unlikely (!data->hfont)) {
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DEBUG_MSG (UNISCRIBE, font, "Font CreateFontIndirectW() failed");
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    _hb_uniscribe_shaper_font_data_destroy (data);
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     return NULL;
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!SelectObject (data->hdc, data->hfont)) {
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DEBUG_MSG (UNISCRIBE, font, "Font SelectObject() failed");
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    _hb_uniscribe_shaper_font_data_destroy (data);
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     return NULL;
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return data;
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_hb_uniscribe_shaper_font_data_destroy (hb_uniscribe_shaper_font_data_t *data)
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (data->hdc)
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReleaseDC (NULL, data->hdc);
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (data->hfont)
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DeleteObject (data->hfont);
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (data->script_cache)
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ScriptFreeCache (&data->script_cache);
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  free (data);
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)LOGFONTW *
5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)hb_uniscribe_font_get_logfontw (hb_font_t *font)
5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (unlikely (!hb_uniscribe_shaper_font_data_ensure (font))) return NULL;
5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  hb_uniscribe_shaper_font_data_t *font_data =  HB_SHAPER_DATA_GET (font);
5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return &font_data->log_font;
5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)HFONT
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)hb_uniscribe_font_get_hfont (hb_font_t *font)
5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (unlikely (!hb_uniscribe_shaper_font_data_ensure (font))) return NULL;
5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  hb_uniscribe_shaper_font_data_t *font_data =  HB_SHAPER_DATA_GET (font);
5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return font_data->hfont;
5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * shaper shape_plan data
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct hb_uniscribe_shaper_shape_plan_data_t {};
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_uniscribe_shaper_shape_plan_data_t *
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_hb_uniscribe_shaper_shape_plan_data_create (hb_shape_plan_t    *shape_plan HB_UNUSED,
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					     const hb_feature_t *user_features HB_UNUSED,
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					     unsigned int        num_user_features HB_UNUSED)
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (hb_uniscribe_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_hb_uniscribe_shaper_shape_plan_data_destroy (hb_uniscribe_shaper_shape_plan_data_t *data HB_UNUSED)
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * shaper
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_bool_t
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_hb_uniscribe_shape (hb_shape_plan_t    *shape_plan,
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     hb_font_t          *font,
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     hb_buffer_t        *buffer,
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     const hb_feature_t *features,
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     unsigned int        num_features)
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hb_face_t *face = font->face;
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hb_uniscribe_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hb_uniscribe_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font);
598f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  hb_uniscribe_shaper_funcs_t *funcs = face_data->funcs;
599f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
600f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  /*
601f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)   * Set up features.
602f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)   */
603f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  hb_auto_array_t<OPENTYPE_FEATURE_RECORD> feature_records;
604f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  hb_auto_array_t<range_record_t> range_records;
605f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (num_features)
606f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  {
607f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    /* Sort features by start/end events. */
608f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    hb_auto_array_t<feature_event_t> feature_events;
609f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    for (unsigned int i = 0; i < num_features; i++)
610f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    {
611f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      active_feature_t feature;
612f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      feature.rec.tagFeature = hb_uint32_swap (features[i].tag);
613f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      feature.rec.lParameter = features[i].value;
614f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      feature.order = i;
615f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
616f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      feature_event_t *event;
617f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
618f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      event = feature_events.push ();
619f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (unlikely (!event))
620f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	goto fail_features;
621f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      event->index = features[i].start;
622f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      event->start = true;
623f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      event->feature = feature;
624f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
625f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      event = feature_events.push ();
626f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (unlikely (!event))
627f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	goto fail_features;
628f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      event->index = features[i].end;
629f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      event->start = false;
630f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      event->feature = feature;
631f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
6325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    feature_events.qsort ();
633f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    /* Add a strategic final event. */
634f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    {
635f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      active_feature_t feature;
636f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      feature.rec.tagFeature = 0;
637f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      feature.rec.lParameter = 0;
638f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      feature.order = num_features + 1;
639f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
640f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      feature_event_t *event = feature_events.push ();
641f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (unlikely (!event))
642f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	goto fail_features;
643f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      event->index = 0; /* This value does magic. */
644f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      event->start = false;
645f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      event->feature = feature;
646f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
647f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
648f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    /* Scan events and save features for each range. */
649f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    hb_auto_array_t<active_feature_t> active_features;
650f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    unsigned int last_index = 0;
651f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    for (unsigned int i = 0; i < feature_events.len; i++)
652f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    {
653f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      feature_event_t *event = &feature_events[i];
654f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
655f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (event->index != last_index)
656f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      {
657f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        /* Save a snapshot of active features and the range. */
658f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	range_record_t *range = range_records.push ();
659f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	if (unlikely (!range))
660f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	  goto fail_features;
661f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
662f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	unsigned int offset = feature_records.len;
663f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
6645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	active_features.qsort ();
665f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	for (unsigned int j = 0; j < active_features.len; j++)
666f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	{
667f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	  if (!j || active_features[j].rec.tagFeature != feature_records[feature_records.len - 1].tagFeature)
668f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	  {
669f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	    OPENTYPE_FEATURE_RECORD *feature = feature_records.push ();
670f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	    if (unlikely (!feature))
671f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	      goto fail_features;
672f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	    *feature = active_features[j].rec;
673f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	  }
674f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	  else
675f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	  {
676f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	    /* Overrides value for existing feature. */
677f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	    feature_records[feature_records.len - 1].lParameter = active_features[j].rec.lParameter;
678f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	  }
679f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	}
680f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
681f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	/* Will convert to pointer after all is ready, since feature_records.array
682f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	 * may move as we grow it. */
683f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	range->props.potfRecords = reinterpret_cast<OPENTYPE_FEATURE_RECORD *> (offset);
684f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	range->props.cotfRecords = feature_records.len - offset;
685f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	range->index_first = last_index;
686f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	range->index_last  = event->index - 1;
687f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
688f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	last_index = event->index;
689f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
690f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
691f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (event->start) {
692f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        active_feature_t *feature = active_features.push ();
693f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	if (unlikely (!feature))
694f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	  goto fail_features;
695f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	*feature = event->feature;
696f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      } else {
697f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        active_feature_t *feature = active_features.find (&event->feature);
698f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	if (feature)
699f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	  active_features.remove (feature - active_features.array);
700f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
701f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
702f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
703f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (!range_records.len) /* No active feature found. */
704f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      goto fail_features;
705f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
706f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    /* Fixup the pointers. */
707f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    for (unsigned int i = 0; i < range_records.len; i++)
708f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    {
709f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      range_record_t *range = &range_records[i];
71023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      range->props.potfRecords = feature_records.array + reinterpret_cast<uintptr_t> (range->props.potfRecords);
711f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
712f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
713f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  else
714f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  {
715f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  fail_features:
716f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    num_features = 0;
717f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define FAIL(...) \
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HB_STMT_START { \
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DEBUG_MSG (UNISCRIBE, NULL, __VA_ARGS__); \
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false; \
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } HB_STMT_END;
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HRESULT hr;
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)retry:
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int scratch_size;
730f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  hb_buffer_t::scratch_buffer_t *scratch = buffer->get_scratch_buffer (&scratch_size);
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define ALLOCATE_ARRAY(Type, name, len) \
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Type *name = (Type *) scratch; \
734f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  { \
735f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    unsigned int _consumed = DIV_CEIL ((len) * sizeof (Type), sizeof (*scratch)); \
736f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    assert (_consumed <= scratch_size); \
737f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    scratch += _consumed; \
738f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    scratch_size -= _consumed; \
739f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define utf16_index() var1.u32
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
743f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ALLOCATE_ARRAY (WCHAR, pchars, buffer->len * 2);
744f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int chars_len = 0;
746f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (unsigned int i = 0; i < buffer->len; i++)
747f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  {
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hb_codepoint_t c = buffer->info[i].codepoint;
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buffer->info[i].utf16_index() = chars_len;
7505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (likely (c <= 0xFFFFu))
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pchars[chars_len++] = c;
7525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    else if (unlikely (c > 0x10FFFFu))
7535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      pchars[chars_len++] = 0xFFFDu;
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else {
7555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      pchars[chars_len++] = 0xD800u + ((c - 0x10000u) >> 10);
7565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      pchars[chars_len++] = 0xDC00u + ((c - 0x10000u) & ((1 << 10) - 1));
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ALLOCATE_ARRAY (WORD, log_clusters, chars_len);
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ALLOCATE_ARRAY (SCRIPT_CHARPROP, char_props, chars_len);
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
763f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (num_features)
764f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  {
765f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    /* Need log_clusters to assign features. */
766f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    chars_len = 0;
767f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    for (unsigned int i = 0; i < buffer->len; i++)
768f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    {
769f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      hb_codepoint_t c = buffer->info[i].codepoint;
770f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      unsigned int cluster = buffer->info[i].cluster;
771f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      log_clusters[chars_len++] = cluster;
7725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if (hb_in_range (c, 0x10000u, 0x10FFFFu))
773f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	log_clusters[chars_len++] = cluster; /* Surrogates. */
774f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
775f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
776f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
77723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  /* The -2 in the following is to compensate for possible
77823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)   * alignment needed after the WORD array.  sizeof(WORD) == 2. */
77923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  unsigned int glyphs_size = (scratch_size * sizeof (int) - 2)
78023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)			   / (sizeof (WORD) +
78123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)			      sizeof (SCRIPT_GLYPHPROP) +
78223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)			      sizeof (int) +
78323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)			      sizeof (GOFFSET) +
78423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)			      sizeof (uint32_t));
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ALLOCATE_ARRAY (WORD, glyphs, glyphs_size);
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ALLOCATE_ARRAY (SCRIPT_GLYPHPROP, glyph_props, glyphs_size);
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ALLOCATE_ARRAY (int, advances, glyphs_size);
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ALLOCATE_ARRAY (GOFFSET, offsets, glyphs_size);
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ALLOCATE_ARRAY (uint32_t, vis_clusters, glyphs_size);
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
792f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  /* Note:
793f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)   * We can't touch the contents of glyph_props.  Our fallback
794f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)   * implementations of Shape and Place functions use that buffer
795f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)   * by casting it to a different type.  It works because they
796f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)   * both agree about it, but if we want to access it here we
797f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)   * need address that issue first.
798f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)   */
799f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef ALLOCATE_ARRAY
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MAX_ITEMS 256
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SCRIPT_ITEM items[MAX_ITEMS + 1];
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SCRIPT_CONTROL bidi_control = {0};
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SCRIPT_STATE bidi_state = {0};
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ULONG script_tags[MAX_ITEMS];
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int item_count;
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* MinGW32 doesn't define fMergeNeutralItems, so we bruteforce */
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //bidi_control.fMergeNeutralItems = true;
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *(uint32_t*)&bidi_control |= 1<<24;
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bidi_state.uBidiLevel = HB_DIRECTION_IS_FORWARD (buffer->props.direction) ? 0 : 1;
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bidi_state.fOverrideDirection = 1;
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
817f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  hr = funcs->ScriptItemizeOpenType (pchars,
818f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				     chars_len,
819f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				     MAX_ITEMS,
820f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				     &bidi_control,
821f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				     &bidi_state,
822f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				     items,
823f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				     script_tags,
824f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				     &item_count);
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (unlikely (FAILED (hr)))
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FAIL ("ScriptItemizeOpenType() failed: 0x%08xL", hr);
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef MAX_ITEMS
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OPENTYPE_TAG language_tag = hb_uint32_swap (hb_ot_tag_from_language (buffer->props.language));
831f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  hb_auto_array_t<TEXTRANGE_PROPERTIES*> range_properties;
832f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  hb_auto_array_t<int> range_char_counts;
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int glyphs_offset = 0;
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int glyphs_len;
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
837f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (unsigned int i = 0; i < item_count; i++)
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int chars_offset = items[i].iCharPos;
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int item_chars_len = items[i + 1].iCharPos - chars_offset;
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
842f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (num_features)
843f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    {
844f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      range_properties.shrink (0);
845f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      range_char_counts.shrink (0);
846f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
847f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      range_record_t *last_range = &range_records[0];
848f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
849f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      for (unsigned int k = chars_offset; k < chars_offset + item_chars_len; k++)
850f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      {
851f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	range_record_t *range = last_range;
852f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	while (log_clusters[k] < range->index_first)
853f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	  range--;
854f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	while (log_clusters[k] > range->index_last)
855f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	  range++;
856f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	if (!range_properties.len ||
857f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	    &range->props != range_properties[range_properties.len - 1])
858f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	{
859f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	  TEXTRANGE_PROPERTIES **props = range_properties.push ();
860f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	  int *c = range_char_counts.push ();
861f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	  if (unlikely (!props || !c))
862f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	  {
863f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	    range_properties.shrink (0);
864f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	    range_char_counts.shrink (0);
865f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	    break;
866f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	  }
867f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	  *props = &range->props;
868f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	  *c = 1;
869f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	}
870f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	else
871f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	{
872f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	  range_char_counts[range_char_counts.len - 1]++;
873f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	}
874f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
875f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	last_range = range;
876f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
877f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
878f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
879f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    /* Asking for glyphs in logical order circumvents at least
880f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)     * one bug in Uniscribe. */
881f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    items[i].a.fLogicalOrder = true;
882f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  retry_shape:
884f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    hr = funcs->ScriptShapeOpenType (font_data->hdc,
885f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				     &font_data->script_cache,
886f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				     &items[i].a,
887f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				     script_tags[i],
888f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				     language_tag,
889f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				     range_char_counts.array,
890f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				     range_properties.array,
891f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				     range_properties.len,
892f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				     pchars + chars_offset,
893f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				     item_chars_len,
894f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				     glyphs_size - glyphs_offset,
895f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				     /* out */
896f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				     log_clusters + chars_offset,
897f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				     char_props + chars_offset,
898f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				     glyphs + glyphs_offset,
899f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				     glyph_props + glyphs_offset,
900f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				     (int *) &glyphs_len);
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (items[i].a.fNoGlyphIndex))
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FAIL ("ScriptShapeOpenType() set fNoGlyphIndex");
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (hr == E_OUTOFMEMORY))
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
90603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      if (unlikely (!buffer->ensure (buffer->allocated * 2)))
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	FAIL ("Buffer resize failed");
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      goto retry;
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (hr == USP_E_SCRIPT_NOT_IN_FONT))
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (items[i].a.eScript == SCRIPT_UNDEFINED)
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	FAIL ("ScriptShapeOpenType() failed: Font doesn't support script");
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      items[i].a.eScript = SCRIPT_UNDEFINED;
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      goto retry_shape;
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (FAILED (hr)))
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FAIL ("ScriptShapeOpenType() failed: 0x%08xL", hr);
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int j = chars_offset; j < chars_offset + item_chars_len; j++)
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      log_clusters[j] += glyphs_offset;
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    hr = funcs->ScriptPlaceOpenType (font_data->hdc,
926f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				     &font_data->script_cache,
927f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				     &items[i].a,
928f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				     script_tags[i],
929f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				     language_tag,
930f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				     range_char_counts.array,
931f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				     range_properties.array,
932f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				     range_properties.len,
933f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				     pchars + chars_offset,
934f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				     log_clusters + chars_offset,
935f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				     char_props + chars_offset,
936f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				     item_chars_len,
937f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				     glyphs + glyphs_offset,
938f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				     glyph_props + glyphs_offset,
939f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				     glyphs_len,
940f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				     /* out */
941f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				     advances + glyphs_offset,
942f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				     offsets + glyphs_offset,
943f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				     NULL);
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (FAILED (hr)))
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FAIL ("ScriptPlaceOpenType() failed: 0x%08xL", hr);
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
947f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (DEBUG_ENABLED (UNISCRIBE))
948f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      fprintf (stderr, "Item %d RTL %d LayoutRTL %d LogicalOrder %d ScriptTag %c%c%c%c\n",
949f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	       i,
950f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	       items[i].a.fRTL,
951f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	       items[i].a.fLayoutRTL,
952f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	       items[i].a.fLogicalOrder,
953f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	       HB_UNTAG (hb_uint32_swap (script_tags[i])));
954f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    glyphs_offset += glyphs_len;
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  glyphs_len = glyphs_offset;
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Ok, we've got everything we need, now compose output buffer,
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * very, *very*, carefully! */
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Calculate visual-clusters.  That's what we ship. */
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (unsigned int i = 0; i < glyphs_len; i++)
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    vis_clusters[i] = -1;
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (unsigned int i = 0; i < buffer->len; i++) {
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32_t *p = &vis_clusters[log_clusters[buffer->info[i].utf16_index()]];
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *p = MIN (*p, buffer->info[i].cluster);
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
969f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (unsigned int i = 1; i < glyphs_len; i++)
970f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (vis_clusters[i] == -1)
971f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      vis_clusters[i] = vis_clusters[i - 1];
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef utf16_index
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
97503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (unlikely (!buffer->ensure (glyphs_len)))
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FAIL ("Buffer in error");
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef FAIL
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Set glyph infos */
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  buffer->len = 0;
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (unsigned int i = 0; i < glyphs_len; i++)
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hb_glyph_info_t *info = &buffer->info[buffer->len++];
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    info->codepoint = glyphs[i];
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    info->cluster = vis_clusters[i];
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* The rest is crap.  Let's store position info there for now. */
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    info->mask = advances[i];
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    info->var1.u32 = offsets[i].du;
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    info->var2.u32 = offsets[i].dv;
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Set glyph positions */
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  buffer->clear_positions ();
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (unsigned int i = 0; i < glyphs_len; i++)
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hb_glyph_info_t *info = &buffer->info[i];
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hb_glyph_position_t *pos = &buffer->pos[i];
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* TODO vertical */
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pos->x_advance = info->mask;
1004f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    pos->x_offset = backward ? -info->var1.u32 : info->var1.u32;
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pos->y_offset = info->var2.u32;
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1008f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (backward)
1009f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    hb_buffer_reverse (buffer);
1010f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Wow, done! */
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1016