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