1aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew/* 23613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod * Copyright © 2012,2013 Mozilla Foundation. 33613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod * Copyright © 2012,2013 Google, Inc. 4aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew * 5aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew * This is part of HarfBuzz, a text shaping library. 6aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew * 7aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew * Permission is hereby granted, without written agreement and without 8aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew * license or royalty fees, to use, copy, modify, and distribute this 9aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew * software and its documentation for any purpose, provided that the 10aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew * above copyright notice and the following two paragraphs appear in 11aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew * all copies of this software. 12aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew * 13aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 14aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 15aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 16aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 17aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew * DAMAGE. 18aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew * 19aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 20aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 21aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 22aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 23aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 24aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew * 25aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew * Mozilla Author(s): Jonathan Kew 26301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod * Google Author(s): Behdad Esfahbod 27aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew */ 28aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 29027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod#define HB_SHAPER coretext 30301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod#include "hb-shaper-impl-private.hh" 31aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 32aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew#include "hb-coretext.h" 33aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 34aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 35aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew#ifndef HB_DEBUG_CORETEXT 36aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew#define HB_DEBUG_CORETEXT (HB_DEBUG+0) 37aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew#endif 38aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 39aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 40a9e25e90a4ca05746fda4a598ad698db1d2c5c1aBehdad Esfahbodstatic void 41a9e25e90a4ca05746fda4a598ad698db1d2c5c1aBehdad Esfahbodrelease_table_data (void *user_data) 42a9e25e90a4ca05746fda4a598ad698db1d2c5c1aBehdad Esfahbod{ 43a9e25e90a4ca05746fda4a598ad698db1d2c5c1aBehdad Esfahbod CFDataRef cf_data = reinterpret_cast<CFDataRef> (user_data); 44a9e25e90a4ca05746fda4a598ad698db1d2c5c1aBehdad Esfahbod CFRelease(cf_data); 45a9e25e90a4ca05746fda4a598ad698db1d2c5c1aBehdad Esfahbod} 46a9e25e90a4ca05746fda4a598ad698db1d2c5c1aBehdad Esfahbod 47a9e25e90a4ca05746fda4a598ad698db1d2c5c1aBehdad Esfahbodstatic hb_blob_t * 48a9e25e90a4ca05746fda4a598ad698db1d2c5c1aBehdad Esfahbodreference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data) 49a9e25e90a4ca05746fda4a598ad698db1d2c5c1aBehdad Esfahbod{ 50a9e25e90a4ca05746fda4a598ad698db1d2c5c1aBehdad Esfahbod CGFontRef cg_font = reinterpret_cast<CGFontRef> (user_data); 51a9e25e90a4ca05746fda4a598ad698db1d2c5c1aBehdad Esfahbod CFDataRef cf_data = CGFontCopyTableForTag (cg_font, tag); 52a9e25e90a4ca05746fda4a598ad698db1d2c5c1aBehdad Esfahbod if (unlikely (!cf_data)) 53a9e25e90a4ca05746fda4a598ad698db1d2c5c1aBehdad Esfahbod return NULL; 54a9e25e90a4ca05746fda4a598ad698db1d2c5c1aBehdad Esfahbod 55a9e25e90a4ca05746fda4a598ad698db1d2c5c1aBehdad Esfahbod const char *data = reinterpret_cast<const char*> (CFDataGetBytePtr (cf_data)); 56a9e25e90a4ca05746fda4a598ad698db1d2c5c1aBehdad Esfahbod const size_t length = CFDataGetLength (cf_data); 57a9e25e90a4ca05746fda4a598ad698db1d2c5c1aBehdad Esfahbod if (!data || !length) 58a9e25e90a4ca05746fda4a598ad698db1d2c5c1aBehdad Esfahbod return NULL; 59a9e25e90a4ca05746fda4a598ad698db1d2c5c1aBehdad Esfahbod 60a9e25e90a4ca05746fda4a598ad698db1d2c5c1aBehdad Esfahbod return hb_blob_create (data, length, HB_MEMORY_MODE_READONLY, 61a9e25e90a4ca05746fda4a598ad698db1d2c5c1aBehdad Esfahbod reinterpret_cast<void *> (const_cast<__CFData *> (cf_data)), 62a9e25e90a4ca05746fda4a598ad698db1d2c5c1aBehdad Esfahbod release_table_data); 63a9e25e90a4ca05746fda4a598ad698db1d2c5c1aBehdad Esfahbod} 64a9e25e90a4ca05746fda4a598ad698db1d2c5c1aBehdad Esfahbod 65a9e25e90a4ca05746fda4a598ad698db1d2c5c1aBehdad Esfahbodhb_face_t * 66a9e25e90a4ca05746fda4a598ad698db1d2c5c1aBehdad Esfahbodhb_coretext_face_create (CGFontRef cg_font) 67a9e25e90a4ca05746fda4a598ad698db1d2c5c1aBehdad Esfahbod{ 68a9e25e90a4ca05746fda4a598ad698db1d2c5c1aBehdad Esfahbod return hb_face_create_for_tables (reference_table, CGFontRetain (cg_font), (hb_destroy_func_t) CGFontRelease); 69a9e25e90a4ca05746fda4a598ad698db1d2c5c1aBehdad Esfahbod} 70a9e25e90a4ca05746fda4a598ad698db1d2c5c1aBehdad Esfahbod 71a9e25e90a4ca05746fda4a598ad698db1d2c5c1aBehdad Esfahbod 72301168dae77a63ee25adfb26ce2b54a708f83791Behdad EsfahbodHB_SHAPER_DATA_ENSURE_DECLARE(coretext, face) 73301168dae77a63ee25adfb26ce2b54a708f83791Behdad EsfahbodHB_SHAPER_DATA_ENSURE_DECLARE(coretext, font) 74aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 75aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 76301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod/* 77301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod * shaper face data 78301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod */ 79301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod 80301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbodstruct hb_coretext_shaper_face_data_t { 81301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod CGFontRef cg_font; 82301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod}; 83aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 84aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kewstatic void 85aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kewrelease_data (void *info, const void *data, size_t size) 86aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew{ 87aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew assert (hb_blob_get_length ((hb_blob_t *) info) == size && 88aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew hb_blob_get_data ((hb_blob_t *) info, NULL) == data); 89aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 90aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew hb_blob_destroy ((hb_blob_t *) info); 91aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew} 92aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 93301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbodhb_coretext_shaper_face_data_t * 94301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod_hb_coretext_shaper_face_data_create (hb_face_t *face) 95aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew{ 96301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod hb_coretext_shaper_face_data_t *data = (hb_coretext_shaper_face_data_t *) calloc (1, sizeof (hb_coretext_shaper_face_data_t)); 97aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew if (unlikely (!data)) 98301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod return NULL; 99aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 100a9e25e90a4ca05746fda4a598ad698db1d2c5c1aBehdad Esfahbod if (face->destroy == (hb_destroy_func_t) CGFontRelease) 101a9e25e90a4ca05746fda4a598ad698db1d2c5c1aBehdad Esfahbod { 102a9e25e90a4ca05746fda4a598ad698db1d2c5c1aBehdad Esfahbod data->cg_font = CGFontRetain ((CGFontRef) face->user_data); 103a9e25e90a4ca05746fda4a598ad698db1d2c5c1aBehdad Esfahbod } 104a9e25e90a4ca05746fda4a598ad698db1d2c5c1aBehdad Esfahbod else 105a9e25e90a4ca05746fda4a598ad698db1d2c5c1aBehdad Esfahbod { 106a9e25e90a4ca05746fda4a598ad698db1d2c5c1aBehdad Esfahbod hb_blob_t *blob = hb_face_reference_blob (face); 107a9e25e90a4ca05746fda4a598ad698db1d2c5c1aBehdad Esfahbod unsigned int blob_length; 108a9e25e90a4ca05746fda4a598ad698db1d2c5c1aBehdad Esfahbod const char *blob_data = hb_blob_get_data (blob, &blob_length); 109a9e25e90a4ca05746fda4a598ad698db1d2c5c1aBehdad Esfahbod if (unlikely (!blob_length)) 110a9e25e90a4ca05746fda4a598ad698db1d2c5c1aBehdad Esfahbod DEBUG_MSG (CORETEXT, face, "Face has empty blob"); 111a9e25e90a4ca05746fda4a598ad698db1d2c5c1aBehdad Esfahbod 112a9e25e90a4ca05746fda4a598ad698db1d2c5c1aBehdad Esfahbod CGDataProviderRef provider = CGDataProviderCreateWithData (blob, blob_data, blob_length, &release_data); 113a9e25e90a4ca05746fda4a598ad698db1d2c5c1aBehdad Esfahbod data->cg_font = CGFontCreateWithDataProvider (provider); 114a9e25e90a4ca05746fda4a598ad698db1d2c5c1aBehdad Esfahbod CGDataProviderRelease (provider); 115a9e25e90a4ca05746fda4a598ad698db1d2c5c1aBehdad Esfahbod } 116aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 117301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod if (unlikely (!data->cg_font)) { 118aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew DEBUG_MSG (CORETEXT, face, "Face CGFontCreateWithDataProvider() failed"); 119301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod free (data); 120301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod return NULL; 121aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew } 122aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 123aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew return data; 124aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew} 125aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 126301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbodvoid 127301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod_hb_coretext_shaper_face_data_destroy (hb_coretext_shaper_face_data_t *data) 128aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew{ 129301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod CFRelease (data->cg_font); 130aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew free (data); 131aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew} 132aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 1339a8395824bf51c2ff2cfe0887ecad52b3d2c02e2Behdad EsfahbodCGFontRef 134e923e6487b25ab86f6f629af480b291e8e5407b5Behdad Esfahbodhb_coretext_face_get_cg_font (hb_face_t *face) 1359a8395824bf51c2ff2cfe0887ecad52b3d2c02e2Behdad Esfahbod{ 1369a8395824bf51c2ff2cfe0887ecad52b3d2c02e2Behdad Esfahbod if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return NULL; 1379a8395824bf51c2ff2cfe0887ecad52b3d2c02e2Behdad Esfahbod hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face); 1389a8395824bf51c2ff2cfe0887ecad52b3d2c02e2Behdad Esfahbod return face_data->cg_font; 1399a8395824bf51c2ff2cfe0887ecad52b3d2c02e2Behdad Esfahbod} 1409a8395824bf51c2ff2cfe0887ecad52b3d2c02e2Behdad Esfahbod 141301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod 142301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod/* 143301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod * shaper font data 144301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod */ 145301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod 146301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbodstruct hb_coretext_shaper_font_data_t { 147301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod CTFontRef ct_font; 148301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod}; 149301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod 150301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbodhb_coretext_shaper_font_data_t * 151301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod_hb_coretext_shaper_font_data_create (hb_font_t *font) 152aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew{ 153301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod if (unlikely (!hb_coretext_shaper_face_data_ensure (font->face))) return NULL; 154aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 155301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod hb_coretext_shaper_font_data_t *data = (hb_coretext_shaper_font_data_t *) calloc (1, sizeof (hb_coretext_shaper_font_data_t)); 156aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew if (unlikely (!data)) 157301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod return NULL; 158aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 159301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod hb_face_t *face = font->face; 160301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face); 161aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 162aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew data->ct_font = CTFontCreateWithGraphicsFont (face_data->cg_font, font->y_scale, NULL, NULL); 163301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod if (unlikely (!data->ct_font)) { 164aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew DEBUG_MSG (CORETEXT, font, "Font CTFontCreateWithGraphicsFont() failed"); 165301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod free (data); 166301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod return NULL; 167aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew } 168aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 169aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew return data; 170aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew} 171aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 172301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbodvoid 173301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod_hb_coretext_shaper_font_data_destroy (hb_coretext_shaper_font_data_t *data) 174301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod{ 175301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod CFRelease (data->ct_font); 176301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod free (data); 177301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod} 178301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod 179301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod 180301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod/* 181301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod * shaper shape_plan data 182301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod */ 183301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod 184301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbodstruct hb_coretext_shaper_shape_plan_data_t {}; 185301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod 186301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbodhb_coretext_shaper_shape_plan_data_t * 18745c1383cc7315f89c23c0ed388b99e87224884e7Behdad Esfahbod_hb_coretext_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED, 18845c1383cc7315f89c23c0ed388b99e87224884e7Behdad Esfahbod const hb_feature_t *user_features HB_UNUSED, 18945c1383cc7315f89c23c0ed388b99e87224884e7Behdad Esfahbod unsigned int num_user_features HB_UNUSED) 190301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod{ 191301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod return (hb_coretext_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED; 192301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod} 193301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod 194301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbodvoid 19545c1383cc7315f89c23c0ed388b99e87224884e7Behdad Esfahbod_hb_coretext_shaper_shape_plan_data_destroy (hb_coretext_shaper_shape_plan_data_t *data HB_UNUSED) 196301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod{ 197301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod} 198301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod 199aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan KewCTFontRef 200aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kewhb_coretext_font_get_ct_font (hb_font_t *font) 201aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew{ 2029a8395824bf51c2ff2cfe0887ecad52b3d2c02e2Behdad Esfahbod if (unlikely (!hb_coretext_shaper_font_data_ensure (font))) return NULL; 203301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod hb_coretext_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font); 204aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew return font_data->ct_font; 205aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew} 206aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 2079a8395824bf51c2ff2cfe0887ecad52b3d2c02e2Behdad Esfahbod 2089a8395824bf51c2ff2cfe0887ecad52b3d2c02e2Behdad Esfahbod/* 2099a8395824bf51c2ff2cfe0887ecad52b3d2c02e2Behdad Esfahbod * shaper 2109a8395824bf51c2ff2cfe0887ecad52b3d2c02e2Behdad Esfahbod */ 2119a8395824bf51c2ff2cfe0887ecad52b3d2c02e2Behdad Esfahbod 2123613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbodstruct feature_record_t { 2133613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod unsigned int feature; 2143613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod unsigned int setting; 2153613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod}; 2163613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 2173613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbodstruct active_feature_t { 2183613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod feature_record_t rec; 2193613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod unsigned int order; 2203613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 2213613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod static int cmp (const active_feature_t *a, const active_feature_t *b) { 2223613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod return a->rec.feature < b->rec.feature ? -1 : a->rec.feature > b->rec.feature ? 1 : 2233613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod a->order < b->order ? -1 : a->order > b->order ? 1 : 2243613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod a->rec.setting < b->rec.setting ? -1 : a->rec.setting > b->rec.setting ? 1 : 2253613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 0; 2263613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod } 2273613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod bool operator== (const active_feature_t *f) { 2283613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod return cmp (this, f) == 0; 2293613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod } 2303613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod}; 2313613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 2323613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbodstruct feature_event_t { 2333613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod unsigned int index; 2343613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod bool start; 2353613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod active_feature_t feature; 2363613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 2373613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod static int cmp (const feature_event_t *a, const feature_event_t *b) { 2383613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod return a->index < b->index ? -1 : a->index > b->index ? 1 : 2393613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod a->start < b->start ? -1 : a->start > b->start ? 1 : 2403613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod active_feature_t::cmp (&a->feature, &b->feature); 2413613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod } 2423613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod}; 2433613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 2443613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbodstruct range_record_t { 2453613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod CTFontRef font; 2463613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod unsigned int index_first; /* == start */ 2473613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod unsigned int index_last; /* == end - 1 */ 2483613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod}; 2493613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 2503613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 2513613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod/* The following enum members are added in OS X 10.8. */ 2523613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kAltHalfWidthTextSelector 6 2533613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kAltProportionalTextSelector 5 2543613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kAlternateHorizKanaOffSelector 1 2553613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kAlternateHorizKanaOnSelector 0 2563613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kAlternateKanaType 34 2573613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kAlternateVertKanaOffSelector 3 2583613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kAlternateVertKanaOnSelector 2 2593613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kCaseSensitiveLayoutOffSelector 1 2603613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kCaseSensitiveLayoutOnSelector 0 2613613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kCaseSensitiveLayoutType 33 2623613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kCaseSensitiveSpacingOffSelector 3 2633613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kCaseSensitiveSpacingOnSelector 2 2643613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kContextualAlternatesOffSelector 1 2653613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kContextualAlternatesOnSelector 0 2663613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kContextualAlternatesType 36 2673613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kContextualLigaturesOffSelector 19 2683613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kContextualLigaturesOnSelector 18 2693613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kContextualSwashAlternatesOffSelector 5 2703613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kContextualSwashAlternatesOnSelector 4 2713613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kDefaultLowerCaseSelector 0 2723613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kDefaultUpperCaseSelector 0 2733613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kHistoricalLigaturesOffSelector 21 2743613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kHistoricalLigaturesOnSelector 20 2753613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kHojoCharactersSelector 12 2763613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kJIS2004CharactersSelector 11 2773613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kLowerCasePetiteCapsSelector 2 2783613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kLowerCaseSmallCapsSelector 1 2793613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kLowerCaseType 37 2803613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kMathematicalGreekOffSelector 11 2813613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kMathematicalGreekOnSelector 10 2823613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kNLCCharactersSelector 13 2833613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kQuarterWidthTextSelector 4 2843613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kScientificInferiorsSelector 4 2853613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltEightOffSelector 17 2863613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltEightOnSelector 16 2873613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltEighteenOffSelector 37 2883613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltEighteenOnSelector 36 2893613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltElevenOffSelector 23 2903613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltElevenOnSelector 22 2913613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltFifteenOffSelector 31 2923613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltFifteenOnSelector 30 2933613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltFiveOffSelector 11 2943613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltFiveOnSelector 10 2953613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltFourOffSelector 9 2963613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltFourOnSelector 8 2973613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltFourteenOffSelector 29 2983613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltFourteenOnSelector 28 2993613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltNineOffSelector 19 3003613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltNineOnSelector 18 3013613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltNineteenOffSelector 39 3023613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltNineteenOnSelector 38 3033613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltOneOffSelector 3 3043613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltOneOnSelector 2 3053613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltSevenOffSelector 15 3063613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltSevenOnSelector 14 3073613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltSeventeenOffSelector 35 3083613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltSeventeenOnSelector 34 3093613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltSixOffSelector 13 3103613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltSixOnSelector 12 3113613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltSixteenOffSelector 33 3123613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltSixteenOnSelector 32 3133613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltTenOffSelector 21 3143613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltTenOnSelector 20 3153613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltThirteenOffSelector 27 3163613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltThirteenOnSelector 26 3173613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltThreeOffSelector 7 3183613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltThreeOnSelector 6 3193613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltTwelveOffSelector 25 3203613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltTwelveOnSelector 24 3213613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltTwentyOffSelector 41 3223613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltTwentyOnSelector 40 3233613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltTwoOffSelector 5 3243613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltTwoOnSelector 4 3253613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAlternativesType 35 3263613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kSwashAlternatesOffSelector 3 3273613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kSwashAlternatesOnSelector 2 3283613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kThirdWidthTextSelector 3 3293613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kTraditionalNamesCharactersSelector 14 3303613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kUpperCasePetiteCapsSelector 2 3313613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kUpperCaseSmallCapsSelector 1 3323613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kUpperCaseType 38 3333613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 3343613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod/* Table data courtesy of Apple. */ 3353613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbodstruct feature_mapping_t { 3363613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod FourCharCode otFeatureTag; 3373613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod uint16_t aatFeatureType; 3383613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod uint16_t selectorToEnable; 3393613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod uint16_t selectorToDisable; 3403613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod} feature_mappings[] = { 3413613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'c2pc', kUpperCaseType, kUpperCasePetiteCapsSelector, kDefaultUpperCaseSelector }, 3423613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'c2sc', kUpperCaseType, kUpperCaseSmallCapsSelector, kDefaultUpperCaseSelector }, 3433613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'calt', kContextualAlternatesType, kContextualAlternatesOnSelector, kContextualAlternatesOffSelector }, 3443613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'case', kCaseSensitiveLayoutType, kCaseSensitiveLayoutOnSelector, kCaseSensitiveLayoutOffSelector }, 3453613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'clig', kLigaturesType, kContextualLigaturesOnSelector, kContextualLigaturesOffSelector }, 3463613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'cpsp', kCaseSensitiveLayoutType, kCaseSensitiveSpacingOnSelector, kCaseSensitiveSpacingOffSelector }, 3473613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'cswh', kContextualAlternatesType, kContextualSwashAlternatesOnSelector, kContextualSwashAlternatesOffSelector }, 3483613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'dlig', kLigaturesType, kRareLigaturesOnSelector, kRareLigaturesOffSelector }, 3493613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'expt', kCharacterShapeType, kExpertCharactersSelector, 16 }, 3503613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'frac', kFractionsType, kDiagonalFractionsSelector, kNoFractionsSelector }, 3513613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'fwid', kTextSpacingType, kMonospacedTextSelector, 7 }, 3523613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'halt', kTextSpacingType, kAltHalfWidthTextSelector, 7 }, 3533613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'hist', kLigaturesType, kHistoricalLigaturesOnSelector, kHistoricalLigaturesOffSelector }, 3543613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'hkna', kAlternateKanaType, kAlternateHorizKanaOnSelector, kAlternateHorizKanaOffSelector, }, 3553613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'hlig', kLigaturesType, kHistoricalLigaturesOnSelector, kHistoricalLigaturesOffSelector }, 3563613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'hngl', kTransliterationType, kHanjaToHangulSelector, kNoTransliterationSelector }, 3573613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'hojo', kCharacterShapeType, kHojoCharactersSelector, 16 }, 3583613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'hwid', kTextSpacingType, kHalfWidthTextSelector, 7 }, 3593613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'ital', kItalicCJKRomanType, kCJKItalicRomanOnSelector, kCJKItalicRomanOffSelector }, 3603613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'jp04', kCharacterShapeType, kJIS2004CharactersSelector, 16 }, 3613613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'jp78', kCharacterShapeType, kJIS1978CharactersSelector, 16 }, 3623613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'jp83', kCharacterShapeType, kJIS1983CharactersSelector, 16 }, 3633613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'jp90', kCharacterShapeType, kJIS1990CharactersSelector, 16 }, 3643613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'liga', kLigaturesType, kCommonLigaturesOnSelector, kCommonLigaturesOffSelector }, 3653613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'lnum', kNumberCaseType, kUpperCaseNumbersSelector, 2 }, 3663613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'mgrk', kMathematicalExtrasType, kMathematicalGreekOnSelector, kMathematicalGreekOffSelector }, 3673613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'nlck', kCharacterShapeType, kNLCCharactersSelector, 16 }, 3683613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'onum', kNumberCaseType, kLowerCaseNumbersSelector, 2 }, 3693613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'ordn', kVerticalPositionType, kOrdinalsSelector, kNormalPositionSelector }, 3703613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'palt', kTextSpacingType, kAltProportionalTextSelector, 7 }, 3713613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'pcap', kLowerCaseType, kLowerCasePetiteCapsSelector, kDefaultLowerCaseSelector }, 3723613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'pkna', kTextSpacingType, kProportionalTextSelector, 7 }, 3733613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'pnum', kNumberSpacingType, kProportionalNumbersSelector, 4 }, 3743613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'pwid', kTextSpacingType, kProportionalTextSelector, 7 }, 3753613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'qwid', kTextSpacingType, kQuarterWidthTextSelector, 7 }, 3763613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'ruby', kRubyKanaType, kRubyKanaOnSelector, kRubyKanaOffSelector }, 3773613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'sinf', kVerticalPositionType, kScientificInferiorsSelector, kNormalPositionSelector }, 3783613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'smcp', kLowerCaseType, kLowerCaseSmallCapsSelector, kDefaultLowerCaseSelector }, 3793613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'smpl', kCharacterShapeType, kSimplifiedCharactersSelector, 16 }, 3803613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'ss01', kStylisticAlternativesType, kStylisticAltOneOnSelector, kStylisticAltOneOffSelector }, 3813613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'ss02', kStylisticAlternativesType, kStylisticAltTwoOnSelector, kStylisticAltTwoOffSelector }, 3823613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'ss03', kStylisticAlternativesType, kStylisticAltThreeOnSelector, kStylisticAltThreeOffSelector }, 3833613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'ss04', kStylisticAlternativesType, kStylisticAltFourOnSelector, kStylisticAltFourOffSelector }, 3843613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'ss05', kStylisticAlternativesType, kStylisticAltFiveOnSelector, kStylisticAltFiveOffSelector }, 3853613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'ss06', kStylisticAlternativesType, kStylisticAltSixOnSelector, kStylisticAltSixOffSelector }, 3863613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'ss07', kStylisticAlternativesType, kStylisticAltSevenOnSelector, kStylisticAltSevenOffSelector }, 3873613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'ss08', kStylisticAlternativesType, kStylisticAltEightOnSelector, kStylisticAltEightOffSelector }, 3883613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'ss09', kStylisticAlternativesType, kStylisticAltNineOnSelector, kStylisticAltNineOffSelector }, 3893613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'ss10', kStylisticAlternativesType, kStylisticAltTenOnSelector, kStylisticAltTenOffSelector }, 3903613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'ss11', kStylisticAlternativesType, kStylisticAltElevenOnSelector, kStylisticAltElevenOffSelector }, 3913613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'ss12', kStylisticAlternativesType, kStylisticAltTwelveOnSelector, kStylisticAltTwelveOffSelector }, 3923613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'ss13', kStylisticAlternativesType, kStylisticAltThirteenOnSelector, kStylisticAltThirteenOffSelector }, 3933613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'ss14', kStylisticAlternativesType, kStylisticAltFourteenOnSelector, kStylisticAltFourteenOffSelector }, 3943613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'ss15', kStylisticAlternativesType, kStylisticAltFifteenOnSelector, kStylisticAltFifteenOffSelector }, 3953613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'ss16', kStylisticAlternativesType, kStylisticAltSixteenOnSelector, kStylisticAltSixteenOffSelector }, 3963613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'ss17', kStylisticAlternativesType, kStylisticAltSeventeenOnSelector, kStylisticAltSeventeenOffSelector }, 3973613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'ss18', kStylisticAlternativesType, kStylisticAltEighteenOnSelector, kStylisticAltEighteenOffSelector }, 3983613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'ss19', kStylisticAlternativesType, kStylisticAltNineteenOnSelector, kStylisticAltNineteenOffSelector }, 3993613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'ss20', kStylisticAlternativesType, kStylisticAltTwentyOnSelector, kStylisticAltTwentyOffSelector }, 4003613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'subs', kVerticalPositionType, kInferiorsSelector, kNormalPositionSelector }, 4013613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'sups', kVerticalPositionType, kSuperiorsSelector, kNormalPositionSelector }, 4023613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'swsh', kContextualAlternatesType, kSwashAlternatesOnSelector, kSwashAlternatesOffSelector }, 4033613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'titl', kStyleOptionsType, kTitlingCapsSelector, kNoStyleOptionsSelector }, 4043613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'tnam', kCharacterShapeType, kTraditionalNamesCharactersSelector, 16 }, 4053613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'tnum', kNumberSpacingType, kMonospacedNumbersSelector, 4 }, 4063613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'trad', kCharacterShapeType, kTraditionalCharactersSelector, 16 }, 4073613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'twid', kTextSpacingType, kThirdWidthTextSelector, 7 }, 4083613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'unic', kLetterCaseType, 14, 15 }, 4093613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'valt', kTextSpacingType, kAltProportionalTextSelector, 7 }, 4103613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'vert', kVerticalSubstitutionType, kSubstituteVerticalFormsOnSelector, kSubstituteVerticalFormsOffSelector }, 4113613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'vhal', kTextSpacingType, kAltHalfWidthTextSelector, 7 }, 4123613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'vkna', kAlternateKanaType, kAlternateVertKanaOnSelector, kAlternateVertKanaOffSelector }, 4133613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'vpal', kTextSpacingType, kAltProportionalTextSelector, 7 }, 4143613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'vrt2', kVerticalSubstitutionType, kSubstituteVerticalFormsOnSelector, kSubstituteVerticalFormsOffSelector }, 4153613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'zero', kTypographicExtrasType, kSlashedZeroOnSelector, kSlashedZeroOffSelector }, 4163613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod}; 4173613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 4183613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbodstatic int 4193613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod_hb_feature_mapping_cmp (const void *key_, const void *entry_) 4203613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod{ 4213613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod unsigned int key = * (unsigned int *) key_; 4223613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod const feature_mapping_t * entry = (const feature_mapping_t *) entry_; 4233613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod return key < entry->otFeatureTag ? -1 : 4243613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod key > entry->otFeatureTag ? 1 : 4253613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 0; 4263613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod} 4273613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 428aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kewhb_bool_t 429301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod_hb_coretext_shape (hb_shape_plan_t *shape_plan, 430301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod hb_font_t *font, 431aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew hb_buffer_t *buffer, 432aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew const hb_feature_t *features, 433aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew unsigned int num_features) 434aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew{ 435301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod hb_face_t *face = font->face; 43658cc233e8b5fdc9dce603acc1b968540a2dea3e1Behdad Esfahbod hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face); 437301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod hb_coretext_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font); 438aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 4393613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod /* 4403613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod * Set up features. 4413613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod * (copied + modified from code from hb-uniscribe.cc) 4423613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod */ 4433613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod hb_auto_array_t<feature_record_t> feature_records; 4443613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod hb_auto_array_t<range_record_t> range_records; 4453613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod if (num_features) 4463613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 4473613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod /* Sort features by start/end events. */ 4483613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod hb_auto_array_t<feature_event_t> feature_events; 4493613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod for (unsigned int i = 0; i < num_features; i++) 4503613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 4513613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod const feature_mapping_t * mapping = (const feature_mapping_t *) bsearch (&features[i].tag, 4523613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod feature_mappings, 4533613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod ARRAY_LENGTH (feature_mappings), 4543613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod sizeof (feature_mappings[0]), 4553613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod _hb_feature_mapping_cmp); 4563613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod if (!mapping) 4573613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod continue; 4583613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 4593613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod active_feature_t feature; 4603613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod feature.rec.feature = mapping->aatFeatureType; 4613613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod feature.rec.setting = features[i].value ? mapping->selectorToEnable : mapping->selectorToDisable; 4623613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod feature.order = i; 4633613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 4643613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod feature_event_t *event; 4653613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 4663613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod event = feature_events.push (); 4673613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod if (unlikely (!event)) 4683613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod goto fail_features; 4693613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod event->index = features[i].start; 4703613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod event->start = true; 4713613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod event->feature = feature; 4723613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 4733613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod event = feature_events.push (); 4743613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod if (unlikely (!event)) 4753613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod goto fail_features; 4763613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod event->index = features[i].end; 4773613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod event->start = false; 4783613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod event->feature = feature; 4793613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod } 480fb8cc86ff99c08064ac58a559bb66cc340693b92Behdad Esfahbod feature_events.qsort (); 4813613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod /* Add a strategic final event. */ 4823613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 4833613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod active_feature_t feature; 4843613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod feature.rec.feature = HB_TAG_NONE; 4853613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod feature.rec.setting = 0; 4863613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod feature.order = num_features + 1; 4873613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 4883613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod feature_event_t *event = feature_events.push (); 4893613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod if (unlikely (!event)) 4903613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod goto fail_features; 4913613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod event->index = 0; /* This value does magic. */ 4923613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod event->start = false; 4933613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod event->feature = feature; 4943613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod } 4953613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 4963613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod /* Scan events and save features for each range. */ 4973613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod hb_auto_array_t<active_feature_t> active_features; 4983613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod unsigned int last_index = 0; 4993613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod for (unsigned int i = 0; i < feature_events.len; i++) 5003613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 5013613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod feature_event_t *event = &feature_events[i]; 5023613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 5033613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod if (event->index != last_index) 5043613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 5053613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod /* Save a snapshot of active features and the range. */ 5063613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod range_record_t *range = range_records.push (); 5073613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod if (unlikely (!range)) 5083613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod goto fail_features; 5093613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 5103613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod if (active_features.len) 5113613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 5123613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod CFMutableArrayRef features_array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); 5133613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 5143613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod /* TODO sort and resolve conflicting features? */ 515fb8cc86ff99c08064ac58a559bb66cc340693b92Behdad Esfahbod /* active_features.qsort (); */ 5163613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod for (unsigned int j = 0; j < active_features.len; j++) 5173613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 5183613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod CFStringRef keys[2] = { 5193613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod kCTFontFeatureTypeIdentifierKey, 5203613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod kCTFontFeatureSelectorIdentifierKey 5213613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod }; 5223613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod CFNumberRef values[2] = { 5233613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &active_features[j].rec.feature), 5243613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &active_features[j].rec.setting) 5253613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod }; 5263613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod CFDictionaryRef dict = CFDictionaryCreate (kCFAllocatorDefault, 5273613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod (const void **) keys, 5283613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod (const void **) values, 5293613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 2, 5303613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod &kCFTypeDictionaryKeyCallBacks, 5313613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod &kCFTypeDictionaryValueCallBacks); 5323613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod CFRelease (values[0]); 5333613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod CFRelease (values[1]); 5343613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 5353613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod CFArrayAppendValue (features_array, dict); 5363613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod CFRelease (dict); 5373613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 5383613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod } 5393613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 5403613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod CFDictionaryRef attributes = CFDictionaryCreate (kCFAllocatorDefault, 5413613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod (const void **) &kCTFontFeatureSettingsAttribute, 5423613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod (const void **) &features_array, 5433613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 1, 5443613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod &kCFTypeDictionaryKeyCallBacks, 5453613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod &kCFTypeDictionaryValueCallBacks); 5463613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod CFRelease (features_array); 5473613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 5483613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod CTFontDescriptorRef font_desc = CTFontDescriptorCreateWithAttributes (attributes); 5493613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod CFRelease (attributes); 5503613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 5513613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod range->font = CTFontCreateCopyWithAttributes (font_data->ct_font, 0.0, NULL, font_desc); 5523613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 5533613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod CFRelease (font_desc); 5543613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod } 5553613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod else 5563613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 5573613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod range->font = NULL; 5583613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod } 5593613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 5603613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod range->index_first = last_index; 5613613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod range->index_last = event->index - 1; 5623613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 5633613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod last_index = event->index; 5643613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod } 5653613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 5663613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod if (event->start) { 5673613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod active_feature_t *feature = active_features.push (); 5683613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod if (unlikely (!feature)) 5693613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod goto fail_features; 5703613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod *feature = event->feature; 5713613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod } else { 5723613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod active_feature_t *feature = active_features.find (&event->feature); 5733613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod if (feature) 5743613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod active_features.remove (feature - active_features.array); 5753613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod } 5763613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod } 5773613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 5783613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod if (!range_records.len) /* No active feature found. */ 5793613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod goto fail_features; 5803613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod } 5813613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod else 5823613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 5833613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod fail_features: 5843613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod num_features = 0; 5853613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod } 5863613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 587aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew#define FAIL(...) \ 588aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew HB_STMT_START { \ 589aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew DEBUG_MSG (CORETEXT, NULL, __VA_ARGS__); \ 590aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew return false; \ 591aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew } HB_STMT_END; 592aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 593aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew unsigned int scratch_size; 59468c372ed2eac76a6d347811293fe2ba2fd6a1eedBehdad Esfahbod hb_buffer_t::scratch_buffer_t *scratch = buffer->get_scratch_buffer (&scratch_size); 5958fcadb9cf9418345610e3f4e38c28c12b768b589Behdad Esfahbod 5968fcadb9cf9418345610e3f4e38c28c12b768b589Behdad Esfahbod#define ALLOCATE_ARRAY(Type, name, len) \ 5978fcadb9cf9418345610e3f4e38c28c12b768b589Behdad Esfahbod Type *name = (Type *) scratch; \ 5988fcadb9cf9418345610e3f4e38c28c12b768b589Behdad Esfahbod { \ 5998fcadb9cf9418345610e3f4e38c28c12b768b589Behdad Esfahbod unsigned int _consumed = DIV_CEIL ((len) * sizeof (Type), sizeof (*scratch)); \ 6008fcadb9cf9418345610e3f4e38c28c12b768b589Behdad Esfahbod assert (_consumed <= scratch_size); \ 6018fcadb9cf9418345610e3f4e38c28c12b768b589Behdad Esfahbod scratch += _consumed; \ 6028fcadb9cf9418345610e3f4e38c28c12b768b589Behdad Esfahbod scratch_size -= _consumed; \ 6038fcadb9cf9418345610e3f4e38c28c12b768b589Behdad Esfahbod } 604aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 605aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew#define utf16_index() var1.u32 606aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 6078fcadb9cf9418345610e3f4e38c28c12b768b589Behdad Esfahbod ALLOCATE_ARRAY (UniChar, pchars, buffer->len * 2); 6088fcadb9cf9418345610e3f4e38c28c12b768b589Behdad Esfahbod 609aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew unsigned int chars_len = 0; 610aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew for (unsigned int i = 0; i < buffer->len; i++) { 611aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew hb_codepoint_t c = buffer->info[i].codepoint; 612aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew buffer->info[i].utf16_index() = chars_len; 6137627100f428ac0ec8509d961d368d2d25d8f0b6eBehdad Esfahbod if (likely (c <= 0xFFFFu)) 614aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew pchars[chars_len++] = c; 6157627100f428ac0ec8509d961d368d2d25d8f0b6eBehdad Esfahbod else if (unlikely (c > 0x10FFFFu)) 6167627100f428ac0ec8509d961d368d2d25d8f0b6eBehdad Esfahbod pchars[chars_len++] = 0xFFFDu; 617aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew else { 6187627100f428ac0ec8509d961d368d2d25d8f0b6eBehdad Esfahbod pchars[chars_len++] = 0xD800u + ((c - 0x10000u) >> 10); 6197627100f428ac0ec8509d961d368d2d25d8f0b6eBehdad Esfahbod pchars[chars_len++] = 0xDC00u + ((c - 0x10000u) & ((1 << 10) - 1)); 620aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew } 621aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew } 622aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 623aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew#undef utf16_index 624aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 625a782a5e9a37c8733ac2830410a514d38635b543aBehdad Esfahbod CFStringRef string_ref = CFStringCreateWithCharactersNoCopy (NULL, 626aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew pchars, chars_len, 627aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew kCFAllocatorNull); 628aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 629a782a5e9a37c8733ac2830410a514d38635b543aBehdad Esfahbod CFMutableAttributedStringRef attr_string = CFAttributedStringCreateMutable (NULL, chars_len); 630a782a5e9a37c8733ac2830410a514d38635b543aBehdad Esfahbod CFAttributedStringReplaceString (attr_string, CFRangeMake (0, 0), string_ref); 631a782a5e9a37c8733ac2830410a514d38635b543aBehdad Esfahbod CFAttributedStringSetAttribute (attr_string, CFRangeMake (0, chars_len), 632a782a5e9a37c8733ac2830410a514d38635b543aBehdad Esfahbod kCTFontAttributeName, font_data->ct_font); 633a782a5e9a37c8733ac2830410a514d38635b543aBehdad Esfahbod 6343613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod if (num_features) 635a782a5e9a37c8733ac2830410a514d38635b543aBehdad Esfahbod { 6368fcadb9cf9418345610e3f4e38c28c12b768b589Behdad Esfahbod ALLOCATE_ARRAY (unsigned int, log_clusters, chars_len); 637a782a5e9a37c8733ac2830410a514d38635b543aBehdad Esfahbod 6383613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod /* Need log_clusters to assign features. */ 6393613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod chars_len = 0; 6403613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod for (unsigned int i = 0; i < buffer->len; i++) 641a782a5e9a37c8733ac2830410a514d38635b543aBehdad Esfahbod { 6423613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod hb_codepoint_t c = buffer->info[i].codepoint; 6433613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod unsigned int cluster = buffer->info[i].cluster; 6443613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod log_clusters[chars_len++] = cluster; 6457627100f428ac0ec8509d961d368d2d25d8f0b6eBehdad Esfahbod if (hb_in_range (c, 0x10000u, 0x10FFFFu)) 6463613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod log_clusters[chars_len++] = cluster; /* Surrogates. */ 647a782a5e9a37c8733ac2830410a514d38635b543aBehdad Esfahbod } 648aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 6493613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod unsigned int start = 0; 6503613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod range_record_t *last_range = &range_records[0]; 6513613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod for (unsigned int k = 0; k < chars_len; k++) 652a782a5e9a37c8733ac2830410a514d38635b543aBehdad Esfahbod { 6533613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod range_record_t *range = last_range; 6543613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod while (log_clusters[k] < range->index_first) 6553613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod range--; 6563613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod while (log_clusters[k] > range->index_last) 6573613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod range++; 6583613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod if (range != last_range) 6593613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 6603613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod if (last_range->font) 6613613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod CFAttributedStringSetAttribute (attr_string, CFRangeMake (start, k - start), 6623613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod kCTFontAttributeName, last_range->font); 6633613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 6643613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod start = k; 6653613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod } 6663613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 6673613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod last_range = range; 668a782a5e9a37c8733ac2830410a514d38635b543aBehdad Esfahbod } 6693613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod if (start != chars_len && last_range->font) 6703613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod CFAttributedStringSetAttribute (attr_string, CFRangeMake (start, chars_len - start - 1), 6713613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod kCTFontAttributeName, last_range->font); 6723613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 6733613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod for (unsigned int i = 0; i < range_records.len; i++) 6743613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod if (range_records[i].font) 6753613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod CFRelease (range_records[i].font); 676a782a5e9a37c8733ac2830410a514d38635b543aBehdad Esfahbod } 677aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 678aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew CTLineRef line = CTLineCreateWithAttributedString (attr_string); 679aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew CFRelease (attr_string); 680aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 681aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew CFArrayRef glyph_runs = CTLineGetGlyphRuns (line); 682aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew unsigned int num_runs = CFArrayGetCount (glyph_runs); 683aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 684aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew buffer->len = 0; 685aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 686aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew const CFRange range_all = CFRangeMake (0, 0); 687aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 68858cc233e8b5fdc9dce603acc1b968540a2dea3e1Behdad Esfahbod for (unsigned int i = 0; i < num_runs; i++) 68958cc233e8b5fdc9dce603acc1b968540a2dea3e1Behdad Esfahbod { 690aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew CTRunRef run = (CTRunRef) CFArrayGetValueAtIndex (glyph_runs, i); 691aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 692c8213c6198abff97822e29a6d565722cfbb43832Khaled Hosny /* CoreText does automatic font fallback (AKA "cascading") for characters 693c8213c6198abff97822e29a6d565722cfbb43832Khaled Hosny * not supported by the requested font, and provides no way to turn it off, 694c8213c6198abff97822e29a6d565722cfbb43832Khaled Hosny * so we detect if the returned run uses a font other than the requested 695c8213c6198abff97822e29a6d565722cfbb43832Khaled Hosny * one and fill in the buffer with .notdef glyphs instead of random glyph 696c8213c6198abff97822e29a6d565722cfbb43832Khaled Hosny * indices from a different font. 697c8213c6198abff97822e29a6d565722cfbb43832Khaled Hosny */ 698c8213c6198abff97822e29a6d565722cfbb43832Khaled Hosny CFDictionaryRef attributes = CTRunGetAttributes (run); 699c8213c6198abff97822e29a6d565722cfbb43832Khaled Hosny CTFontRef run_ct_font = static_cast<CTFontRef>(CFDictionaryGetValue (attributes, kCTFontAttributeName)); 700c8213c6198abff97822e29a6d565722cfbb43832Khaled Hosny CGFontRef run_cg_font = CTFontCopyGraphicsFont (run_ct_font, 0); 70158cc233e8b5fdc9dce603acc1b968540a2dea3e1Behdad Esfahbod if (!CFEqual (run_cg_font, face_data->cg_font)) 70258cc233e8b5fdc9dce603acc1b968540a2dea3e1Behdad Esfahbod { 703c8213c6198abff97822e29a6d565722cfbb43832Khaled Hosny CFRelease (run_cg_font); 70458cc233e8b5fdc9dce603acc1b968540a2dea3e1Behdad Esfahbod 70558cc233e8b5fdc9dce603acc1b968540a2dea3e1Behdad Esfahbod CFRange range = CTRunGetStringRange (run); 70658cc233e8b5fdc9dce603acc1b968540a2dea3e1Behdad Esfahbod buffer->ensure (buffer->len + range.length); 70758cc233e8b5fdc9dce603acc1b968540a2dea3e1Behdad Esfahbod if (buffer->in_error) 70858cc233e8b5fdc9dce603acc1b968540a2dea3e1Behdad Esfahbod FAIL ("Buffer resize failed"); 70958cc233e8b5fdc9dce603acc1b968540a2dea3e1Behdad Esfahbod hb_glyph_info_t *info = buffer->info + buffer->len; 71058cc233e8b5fdc9dce603acc1b968540a2dea3e1Behdad Esfahbod 711748b2782e4898420003a3bbc041dcccbe9e3edc2Behdad Esfahbod CGGlyph notdef = 0; 712748b2782e4898420003a3bbc041dcccbe9e3edc2Behdad Esfahbod double advance = CTFontGetAdvancesForGlyphs (font_data->ct_font, kCTFontHorizontalOrientation, ¬def, NULL, 1); 713748b2782e4898420003a3bbc041dcccbe9e3edc2Behdad Esfahbod 714c29993a181c2139eaec97b5f6225824040ca3ac9Behdad Esfahbod for (CFIndex j = range.location; j < range.location + range.length; j++) 71558cc233e8b5fdc9dce603acc1b968540a2dea3e1Behdad Esfahbod { 716c29993a181c2139eaec97b5f6225824040ca3ac9Behdad Esfahbod UniChar ch = CFStringGetCharacterAtIndex (string_ref, j); 7177627100f428ac0ec8509d961d368d2d25d8f0b6eBehdad Esfahbod if (hb_in_range<UniChar> (ch, 0xDC00u, 0xDFFFu) && range.location < j) 718c29993a181c2139eaec97b5f6225824040ca3ac9Behdad Esfahbod { 719c29993a181c2139eaec97b5f6225824040ca3ac9Behdad Esfahbod ch = CFStringGetCharacterAtIndex (string_ref, j - 1); 7207627100f428ac0ec8509d961d368d2d25d8f0b6eBehdad Esfahbod if (hb_in_range<UniChar> (ch, 0xD800u, 0xDBFFu)) 721c29993a181c2139eaec97b5f6225824040ca3ac9Behdad Esfahbod /* This is the second of a surrogate pair. Don't need .notdef 722c29993a181c2139eaec97b5f6225824040ca3ac9Behdad Esfahbod * for this one. */ 723c29993a181c2139eaec97b5f6225824040ca3ac9Behdad Esfahbod continue; 724c29993a181c2139eaec97b5f6225824040ca3ac9Behdad Esfahbod } 725c29993a181c2139eaec97b5f6225824040ca3ac9Behdad Esfahbod 726c8213c6198abff97822e29a6d565722cfbb43832Khaled Hosny info->codepoint = notdef; 727aec468f01e866c99e65a8f764a792c74c96840d7Behdad Esfahbod /* TODO We have to fixup clusters later. See vis_clusters in 728aec468f01e866c99e65a8f764a792c74c96840d7Behdad Esfahbod * hb-uniscribe.cc for example. */ 729c29993a181c2139eaec97b5f6225824040ca3ac9Behdad Esfahbod info->cluster = j; 730c8213c6198abff97822e29a6d565722cfbb43832Khaled Hosny 731c8213c6198abff97822e29a6d565722cfbb43832Khaled Hosny info->mask = advance; 732c8213c6198abff97822e29a6d565722cfbb43832Khaled Hosny info->var1.u32 = 0; 733c8213c6198abff97822e29a6d565722cfbb43832Khaled Hosny info->var2.u32 = 0; 734c8213c6198abff97822e29a6d565722cfbb43832Khaled Hosny 73558cc233e8b5fdc9dce603acc1b968540a2dea3e1Behdad Esfahbod info++; 736c29993a181c2139eaec97b5f6225824040ca3ac9Behdad Esfahbod buffer->len++; 737c8213c6198abff97822e29a6d565722cfbb43832Khaled Hosny } 738c8213c6198abff97822e29a6d565722cfbb43832Khaled Hosny continue; 739c8213c6198abff97822e29a6d565722cfbb43832Khaled Hosny } 740c8213c6198abff97822e29a6d565722cfbb43832Khaled Hosny CFRelease (run_cg_font); 741c8213c6198abff97822e29a6d565722cfbb43832Khaled Hosny 742aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew unsigned int num_glyphs = CTRunGetGlyphCount (run); 743aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew if (num_glyphs == 0) 744aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew continue; 745aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 746aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew buffer->ensure (buffer->len + num_glyphs); 747aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 74868c372ed2eac76a6d347811293fe2ba2fd6a1eedBehdad Esfahbod scratch = buffer->get_scratch_buffer (&scratch_size); 749aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 75016f175cb2e081e605fe7f9cd01bbe8c24380278aBehdad Esfahbod /* Testing indicates that CTRunGetGlyphsPtr, etc (almost?) always 75116f175cb2e081e605fe7f9cd01bbe8c24380278aBehdad Esfahbod * succeed, and so copying data to our own buffer will be rare. */ 752aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 753aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew const CGGlyph* glyphs = CTRunGetGlyphsPtr (run); 754aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew if (!glyphs) { 755aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew ALLOCATE_ARRAY (CGGlyph, glyph_buf, num_glyphs); 756aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew CTRunGetGlyphs (run, range_all, glyph_buf); 757aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew glyphs = glyph_buf; 758aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew } 759aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 760aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew const CGPoint* positions = CTRunGetPositionsPtr (run); 761aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew if (!positions) { 762aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew ALLOCATE_ARRAY (CGPoint, position_buf, num_glyphs); 763aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew CTRunGetPositions (run, range_all, position_buf); 764aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew positions = position_buf; 765aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew } 766aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 767aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew const CFIndex* string_indices = CTRunGetStringIndicesPtr (run); 768aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew if (!string_indices) { 769aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew ALLOCATE_ARRAY (CFIndex, index_buf, num_glyphs); 770aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew CTRunGetStringIndices (run, range_all, index_buf); 771aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew string_indices = index_buf; 772aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew } 773aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 774aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew#undef ALLOCATE_ARRAY 775aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 776aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew double run_width = CTRunGetTypographicBounds (run, range_all, NULL, NULL, NULL); 777aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 778aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew for (unsigned int j = 0; j < num_glyphs; j++) { 779aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew double advance = (j + 1 < num_glyphs ? positions[j + 1].x : positions[0].x + run_width) - positions[j].x; 780aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 781aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew hb_glyph_info_t *info = &buffer->info[buffer->len]; 782aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 783aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew info->codepoint = glyphs[j]; 784aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew info->cluster = string_indices[j]; 785aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 7867d52e6601f0e695690cd168a288466746cf25300Behdad Esfahbod /* Currently, we do all x-positioning by setting the advance, we never use x-offset. */ 787aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew info->mask = advance; 788aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew info->var1.u32 = 0; 789aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew info->var2.u32 = positions[j].y; 790aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 791aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew buffer->len++; 792aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew } 793aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew } 794aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 795aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew buffer->clear_positions (); 796aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 797aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew unsigned int count = buffer->len; 798aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew for (unsigned int i = 0; i < count; ++i) { 799aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew hb_glyph_info_t *info = &buffer->info[i]; 800aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew hb_glyph_position_t *pos = &buffer->pos[i]; 801aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 802aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew /* TODO vertical */ 803aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew pos->x_advance = info->mask; 804aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew pos->x_offset = info->var1.u32; 805aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew pos->y_offset = info->var2.u32; 806aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew } 807aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 8087d52e6601f0e695690cd168a288466746cf25300Behdad Esfahbod /* Fix up clusters so that we never return out-of-order indices; 8097d52e6601f0e695690cd168a288466746cf25300Behdad Esfahbod * if core text has reordered glyphs, we'll merge them to the 8107d52e6601f0e695690cd168a288466746cf25300Behdad Esfahbod * beginning of the reordered cluster. 8117d52e6601f0e695690cd168a288466746cf25300Behdad Esfahbod * 8127d52e6601f0e695690cd168a288466746cf25300Behdad Esfahbod * This does *not* mean we'll form the same clusters as Uniscribe 8137d52e6601f0e695690cd168a288466746cf25300Behdad Esfahbod * or the native OT backend, only that the cluster indices will be 8147d52e6601f0e695690cd168a288466746cf25300Behdad Esfahbod * monotonic in the output buffer. */ 815ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew if (HB_DIRECTION_IS_FORWARD (buffer->props.direction)) { 816ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew unsigned int prev_cluster = 0; 817ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew for (unsigned int i = 0; i < count; i++) { 818ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew unsigned int curr_cluster = buffer->info[i].cluster; 819ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew if (curr_cluster < prev_cluster) { 820ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew for (unsigned int j = i; j > 0; j--) { 821ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew if (buffer->info[j - 1].cluster > curr_cluster) 822ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew buffer->info[j - 1].cluster = curr_cluster; 823ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew else 824ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew break; 825ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew } 826ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew } 827ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew prev_cluster = curr_cluster; 828ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew } 829ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew } else { 830ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew unsigned int prev_cluster = (unsigned int)-1; 831ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew for (unsigned int i = 0; i < count; i++) { 832ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew unsigned int curr_cluster = buffer->info[i].cluster; 833ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew if (curr_cluster > prev_cluster) { 834ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew for (unsigned int j = i; j > 0; j--) { 835ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew if (buffer->info[j - 1].cluster < curr_cluster) 836ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew buffer->info[j - 1].cluster = curr_cluster; 837ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew else 838ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew break; 839ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew } 840ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew } 841ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew prev_cluster = curr_cluster; 842ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew } 843ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew } 844ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew 845c29993a181c2139eaec97b5f6225824040ca3ac9Behdad Esfahbod CFRelease (string_ref); 846c461371419d186811d4bfc768e26535f48a807f4Behdad Esfahbod CFRelease (line); 847c461371419d186811d4bfc768e26535f48a807f4Behdad Esfahbod 848aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew return true; 849aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew} 850c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod 851c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod 852c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod/* 853c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod * AAT shaper 854c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod */ 855c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod 856c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad EsfahbodHB_SHAPER_DATA_ENSURE_DECLARE(coretext_aat, face) 857c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad EsfahbodHB_SHAPER_DATA_ENSURE_DECLARE(coretext_aat, font) 858c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod 859c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod 860c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod/* 861c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod * shaper face data 862c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod */ 863c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod 864c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbodstruct hb_coretext_aat_shaper_face_data_t {}; 865c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod 866c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbodhb_coretext_aat_shaper_face_data_t * 867c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod_hb_coretext_aat_shaper_face_data_create (hb_face_t *face) 868c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod{ 869c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod hb_blob_t *mort_blob = face->reference_table (HB_CORETEXT_TAG_MORT); 870c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod /* Umm, we just reference the table to check whether it exists. 871c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod * Maybe add better API for this? */ 872c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod if (!hb_blob_get_length (mort_blob)) 873c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod { 874c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod hb_blob_destroy (mort_blob); 875c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod mort_blob = face->reference_table (HB_CORETEXT_TAG_MORX); 876c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod if (!hb_blob_get_length (mort_blob)) 877c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod { 878c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod hb_blob_destroy (mort_blob); 879c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod return NULL; 880c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod } 881c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod } 882c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod hb_blob_destroy (mort_blob); 883c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod 884c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod return hb_coretext_shaper_face_data_ensure (face) ? (hb_coretext_aat_shaper_face_data_t *) HB_SHAPER_DATA_SUCCEEDED : NULL; 885c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod} 886c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod 887c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbodvoid 888c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod_hb_coretext_aat_shaper_face_data_destroy (hb_coretext_aat_shaper_face_data_t *data HB_UNUSED) 889c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod{ 890c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod} 891c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod 892c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod 893c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod/* 894c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod * shaper font data 895c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod */ 896c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod 897c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbodstruct hb_coretext_aat_shaper_font_data_t {}; 898c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod 899c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbodhb_coretext_aat_shaper_font_data_t * 900c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod_hb_coretext_aat_shaper_font_data_create (hb_font_t *font) 901c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod{ 902c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod return hb_coretext_shaper_font_data_ensure (font) ? (hb_coretext_aat_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED : NULL; 903c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod} 904c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod 905c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbodvoid 906c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod_hb_coretext_aat_shaper_font_data_destroy (hb_coretext_aat_shaper_font_data_t *data HB_UNUSED) 907c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod{ 908c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod} 909c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod 910c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod 911c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod/* 912c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod * shaper shape_plan data 913c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod */ 914c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod 915c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbodstruct hb_coretext_aat_shaper_shape_plan_data_t {}; 916c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod 917c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbodhb_coretext_aat_shaper_shape_plan_data_t * 918c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod_hb_coretext_aat_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED, 919c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod const hb_feature_t *user_features HB_UNUSED, 920c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod unsigned int num_user_features HB_UNUSED) 921c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod{ 922c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod return (hb_coretext_aat_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED; 923c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod} 924c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod 925c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbodvoid 926c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod_hb_coretext_aat_shaper_shape_plan_data_destroy (hb_coretext_aat_shaper_shape_plan_data_t *data HB_UNUSED) 927c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod{ 928c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod} 929c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod 930c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod 931c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod/* 932c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod * shaper 933c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod */ 934c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod 935c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbodhb_bool_t 936c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod_hb_coretext_aat_shape (hb_shape_plan_t *shape_plan, 937c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod hb_font_t *font, 938c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod hb_buffer_t *buffer, 939c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod const hb_feature_t *features, 940c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod unsigned int num_features) 941c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod{ 942c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod return _hb_coretext_shape (shape_plan, font, buffer, features, num_features); 943c79865f90f62309dc64c8d3f2f503ec2aa4b7ec1Behdad Esfahbod} 944