hb-coretext.cc revision c29993a181c2139eaec97b5f6225824040ca3ac9
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 40301168dae77a63ee25adfb26ce2b54a708f83791Behdad EsfahbodHB_SHAPER_DATA_ENSURE_DECLARE(coretext, face) 41301168dae77a63ee25adfb26ce2b54a708f83791Behdad EsfahbodHB_SHAPER_DATA_ENSURE_DECLARE(coretext, font) 42aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 43aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 44301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod/* 45301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod * shaper face data 46301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod */ 47301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod 48301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbodstruct hb_coretext_shaper_face_data_t { 49301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod CGFontRef cg_font; 50301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod}; 51aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 52aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kewstatic void 53aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kewrelease_data (void *info, const void *data, size_t size) 54aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew{ 55aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew assert (hb_blob_get_length ((hb_blob_t *) info) == size && 56aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew hb_blob_get_data ((hb_blob_t *) info, NULL) == data); 57aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 58aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew hb_blob_destroy ((hb_blob_t *) info); 59aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew} 60aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 61301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbodhb_coretext_shaper_face_data_t * 62301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod_hb_coretext_shaper_face_data_create (hb_face_t *face) 63aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew{ 64301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod hb_coretext_shaper_face_data_t *data = (hb_coretext_shaper_face_data_t *) calloc (1, sizeof (hb_coretext_shaper_face_data_t)); 65aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew if (unlikely (!data)) 66301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod return NULL; 67aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 68aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew hb_blob_t *blob = hb_face_reference_blob (face); 69aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew unsigned int blob_length; 70aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew const char *blob_data = hb_blob_get_data (blob, &blob_length); 71aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew if (unlikely (!blob_length)) 72aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew DEBUG_MSG (CORETEXT, face, "Face has empty blob"); 73aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 74aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew CGDataProviderRef provider = CGDataProviderCreateWithData (blob, blob_data, blob_length, &release_data); 75aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew data->cg_font = CGFontCreateWithDataProvider (provider); 76aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew CGDataProviderRelease (provider); 77aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 78301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod if (unlikely (!data->cg_font)) { 79aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew DEBUG_MSG (CORETEXT, face, "Face CGFontCreateWithDataProvider() failed"); 80301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod free (data); 81301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod return NULL; 82aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew } 83aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 84aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew return data; 85aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew} 86aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 87301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbodvoid 88301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod_hb_coretext_shaper_face_data_destroy (hb_coretext_shaper_face_data_t *data) 89aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew{ 90301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod CFRelease (data->cg_font); 91aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew free (data); 92aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew} 93aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 949a8395824bf51c2ff2cfe0887ecad52b3d2c02e2Behdad EsfahbodCGFontRef 95e923e6487b25ab86f6f629af480b291e8e5407b5Behdad Esfahbodhb_coretext_face_get_cg_font (hb_face_t *face) 969a8395824bf51c2ff2cfe0887ecad52b3d2c02e2Behdad Esfahbod{ 979a8395824bf51c2ff2cfe0887ecad52b3d2c02e2Behdad Esfahbod if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return NULL; 989a8395824bf51c2ff2cfe0887ecad52b3d2c02e2Behdad Esfahbod hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face); 999a8395824bf51c2ff2cfe0887ecad52b3d2c02e2Behdad Esfahbod return face_data->cg_font; 1009a8395824bf51c2ff2cfe0887ecad52b3d2c02e2Behdad Esfahbod} 1019a8395824bf51c2ff2cfe0887ecad52b3d2c02e2Behdad Esfahbod 102301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod 103301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod/* 104301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod * shaper font data 105301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod */ 106301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod 107301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbodstruct hb_coretext_shaper_font_data_t { 108301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod CTFontRef ct_font; 109301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod}; 110301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod 111301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbodhb_coretext_shaper_font_data_t * 112301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod_hb_coretext_shaper_font_data_create (hb_font_t *font) 113aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew{ 114301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod if (unlikely (!hb_coretext_shaper_face_data_ensure (font->face))) return NULL; 115aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 116301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod hb_coretext_shaper_font_data_t *data = (hb_coretext_shaper_font_data_t *) calloc (1, sizeof (hb_coretext_shaper_font_data_t)); 117aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew if (unlikely (!data)) 118301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod return NULL; 119aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 120301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod hb_face_t *face = font->face; 121301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face); 122aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 123aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew data->ct_font = CTFontCreateWithGraphicsFont (face_data->cg_font, font->y_scale, NULL, NULL); 124301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod if (unlikely (!data->ct_font)) { 125aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew DEBUG_MSG (CORETEXT, font, "Font CTFontCreateWithGraphicsFont() failed"); 126301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod free (data); 127301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod return NULL; 128aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew } 129aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 130aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew return data; 131aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew} 132aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 133301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbodvoid 134301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod_hb_coretext_shaper_font_data_destroy (hb_coretext_shaper_font_data_t *data) 135301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod{ 136301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod CFRelease (data->ct_font); 137301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod free (data); 138301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod} 139301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod 140301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod 141301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod/* 142301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod * shaper shape_plan data 143301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod */ 144301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod 145301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbodstruct hb_coretext_shaper_shape_plan_data_t {}; 146301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod 147301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbodhb_coretext_shaper_shape_plan_data_t * 14845c1383cc7315f89c23c0ed388b99e87224884e7Behdad Esfahbod_hb_coretext_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED, 14945c1383cc7315f89c23c0ed388b99e87224884e7Behdad Esfahbod const hb_feature_t *user_features HB_UNUSED, 15045c1383cc7315f89c23c0ed388b99e87224884e7Behdad Esfahbod unsigned int num_user_features HB_UNUSED) 151301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod{ 152301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod return (hb_coretext_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED; 153301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod} 154301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod 155301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbodvoid 15645c1383cc7315f89c23c0ed388b99e87224884e7Behdad Esfahbod_hb_coretext_shaper_shape_plan_data_destroy (hb_coretext_shaper_shape_plan_data_t *data HB_UNUSED) 157301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod{ 158301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod} 159301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod 160aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan KewCTFontRef 161aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kewhb_coretext_font_get_ct_font (hb_font_t *font) 162aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew{ 1639a8395824bf51c2ff2cfe0887ecad52b3d2c02e2Behdad Esfahbod if (unlikely (!hb_coretext_shaper_font_data_ensure (font))) return NULL; 164301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod hb_coretext_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font); 165aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew return font_data->ct_font; 166aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew} 167aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 1689a8395824bf51c2ff2cfe0887ecad52b3d2c02e2Behdad Esfahbod 1699a8395824bf51c2ff2cfe0887ecad52b3d2c02e2Behdad Esfahbod/* 1709a8395824bf51c2ff2cfe0887ecad52b3d2c02e2Behdad Esfahbod * shaper 1719a8395824bf51c2ff2cfe0887ecad52b3d2c02e2Behdad Esfahbod */ 1729a8395824bf51c2ff2cfe0887ecad52b3d2c02e2Behdad Esfahbod 1733613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbodstruct feature_record_t { 1743613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod unsigned int feature; 1753613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod unsigned int setting; 1763613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod}; 1773613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 1783613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbodstruct active_feature_t { 1793613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod feature_record_t rec; 1803613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod unsigned int order; 1813613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 1823613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod static int cmp (const active_feature_t *a, const active_feature_t *b) { 1833613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod return a->rec.feature < b->rec.feature ? -1 : a->rec.feature > b->rec.feature ? 1 : 1843613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod a->order < b->order ? -1 : a->order > b->order ? 1 : 1853613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod a->rec.setting < b->rec.setting ? -1 : a->rec.setting > b->rec.setting ? 1 : 1863613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 0; 1873613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod } 1883613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod bool operator== (const active_feature_t *f) { 1893613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod return cmp (this, f) == 0; 1903613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod } 1913613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod}; 1923613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 1933613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbodstruct feature_event_t { 1943613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod unsigned int index; 1953613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod bool start; 1963613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod active_feature_t feature; 1973613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 1983613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod static int cmp (const feature_event_t *a, const feature_event_t *b) { 1993613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod return a->index < b->index ? -1 : a->index > b->index ? 1 : 2003613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod a->start < b->start ? -1 : a->start > b->start ? 1 : 2013613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod active_feature_t::cmp (&a->feature, &b->feature); 2023613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod } 2033613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod}; 2043613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 2053613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbodstruct range_record_t { 2063613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod CTFontRef font; 2073613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod unsigned int index_first; /* == start */ 2083613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod unsigned int index_last; /* == end - 1 */ 2093613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod}; 2103613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 2113613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 2123613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod/* The following enum members are added in OS X 10.8. */ 2133613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kAltHalfWidthTextSelector 6 2143613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kAltProportionalTextSelector 5 2153613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kAlternateHorizKanaOffSelector 1 2163613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kAlternateHorizKanaOnSelector 0 2173613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kAlternateKanaType 34 2183613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kAlternateVertKanaOffSelector 3 2193613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kAlternateVertKanaOnSelector 2 2203613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kCaseSensitiveLayoutOffSelector 1 2213613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kCaseSensitiveLayoutOnSelector 0 2223613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kCaseSensitiveLayoutType 33 2233613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kCaseSensitiveSpacingOffSelector 3 2243613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kCaseSensitiveSpacingOnSelector 2 2253613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kContextualAlternatesOffSelector 1 2263613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kContextualAlternatesOnSelector 0 2273613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kContextualAlternatesType 36 2283613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kContextualLigaturesOffSelector 19 2293613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kContextualLigaturesOnSelector 18 2303613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kContextualSwashAlternatesOffSelector 5 2313613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kContextualSwashAlternatesOnSelector 4 2323613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kDefaultLowerCaseSelector 0 2333613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kDefaultUpperCaseSelector 0 2343613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kHistoricalLigaturesOffSelector 21 2353613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kHistoricalLigaturesOnSelector 20 2363613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kHojoCharactersSelector 12 2373613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kJIS2004CharactersSelector 11 2383613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kLowerCasePetiteCapsSelector 2 2393613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kLowerCaseSmallCapsSelector 1 2403613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kLowerCaseType 37 2413613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kMathematicalGreekOffSelector 11 2423613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kMathematicalGreekOnSelector 10 2433613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kNLCCharactersSelector 13 2443613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kQuarterWidthTextSelector 4 2453613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kScientificInferiorsSelector 4 2463613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltEightOffSelector 17 2473613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltEightOnSelector 16 2483613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltEighteenOffSelector 37 2493613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltEighteenOnSelector 36 2503613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltElevenOffSelector 23 2513613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltElevenOnSelector 22 2523613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltFifteenOffSelector 31 2533613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltFifteenOnSelector 30 2543613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltFiveOffSelector 11 2553613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltFiveOnSelector 10 2563613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltFourOffSelector 9 2573613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltFourOnSelector 8 2583613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltFourteenOffSelector 29 2593613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltFourteenOnSelector 28 2603613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltNineOffSelector 19 2613613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltNineOnSelector 18 2623613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltNineteenOffSelector 39 2633613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltNineteenOnSelector 38 2643613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltOneOffSelector 3 2653613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltOneOnSelector 2 2663613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltSevenOffSelector 15 2673613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltSevenOnSelector 14 2683613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltSeventeenOffSelector 35 2693613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltSeventeenOnSelector 34 2703613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltSixOffSelector 13 2713613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltSixOnSelector 12 2723613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltSixteenOffSelector 33 2733613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltSixteenOnSelector 32 2743613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltTenOffSelector 21 2753613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltTenOnSelector 20 2763613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltThirteenOffSelector 27 2773613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltThirteenOnSelector 26 2783613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltThreeOffSelector 7 2793613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltThreeOnSelector 6 2803613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltTwelveOffSelector 25 2813613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltTwelveOnSelector 24 2823613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltTwentyOffSelector 41 2833613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltTwentyOnSelector 40 2843613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltTwoOffSelector 5 2853613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAltTwoOnSelector 4 2863613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kStylisticAlternativesType 35 2873613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kSwashAlternatesOffSelector 3 2883613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kSwashAlternatesOnSelector 2 2893613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kThirdWidthTextSelector 3 2903613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kTraditionalNamesCharactersSelector 14 2913613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kUpperCasePetiteCapsSelector 2 2923613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kUpperCaseSmallCapsSelector 1 2933613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod#define kUpperCaseType 38 2943613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 2953613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod/* Table data courtesy of Apple. */ 2963613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbodstruct feature_mapping_t { 2973613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod FourCharCode otFeatureTag; 2983613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod uint16_t aatFeatureType; 2993613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod uint16_t selectorToEnable; 3003613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod uint16_t selectorToDisable; 3013613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod} feature_mappings[] = { 3023613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'c2pc', kUpperCaseType, kUpperCasePetiteCapsSelector, kDefaultUpperCaseSelector }, 3033613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'c2sc', kUpperCaseType, kUpperCaseSmallCapsSelector, kDefaultUpperCaseSelector }, 3043613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'calt', kContextualAlternatesType, kContextualAlternatesOnSelector, kContextualAlternatesOffSelector }, 3053613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'case', kCaseSensitiveLayoutType, kCaseSensitiveLayoutOnSelector, kCaseSensitiveLayoutOffSelector }, 3063613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'clig', kLigaturesType, kContextualLigaturesOnSelector, kContextualLigaturesOffSelector }, 3073613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'cpsp', kCaseSensitiveLayoutType, kCaseSensitiveSpacingOnSelector, kCaseSensitiveSpacingOffSelector }, 3083613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'cswh', kContextualAlternatesType, kContextualSwashAlternatesOnSelector, kContextualSwashAlternatesOffSelector }, 3093613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'dlig', kLigaturesType, kRareLigaturesOnSelector, kRareLigaturesOffSelector }, 3103613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'expt', kCharacterShapeType, kExpertCharactersSelector, 16 }, 3113613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'frac', kFractionsType, kDiagonalFractionsSelector, kNoFractionsSelector }, 3123613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'fwid', kTextSpacingType, kMonospacedTextSelector, 7 }, 3133613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'halt', kTextSpacingType, kAltHalfWidthTextSelector, 7 }, 3143613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'hist', kLigaturesType, kHistoricalLigaturesOnSelector, kHistoricalLigaturesOffSelector }, 3153613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'hkna', kAlternateKanaType, kAlternateHorizKanaOnSelector, kAlternateHorizKanaOffSelector, }, 3163613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'hlig', kLigaturesType, kHistoricalLigaturesOnSelector, kHistoricalLigaturesOffSelector }, 3173613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'hngl', kTransliterationType, kHanjaToHangulSelector, kNoTransliterationSelector }, 3183613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'hojo', kCharacterShapeType, kHojoCharactersSelector, 16 }, 3193613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'hwid', kTextSpacingType, kHalfWidthTextSelector, 7 }, 3203613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'ital', kItalicCJKRomanType, kCJKItalicRomanOnSelector, kCJKItalicRomanOffSelector }, 3213613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'jp04', kCharacterShapeType, kJIS2004CharactersSelector, 16 }, 3223613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'jp78', kCharacterShapeType, kJIS1978CharactersSelector, 16 }, 3233613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'jp83', kCharacterShapeType, kJIS1983CharactersSelector, 16 }, 3243613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'jp90', kCharacterShapeType, kJIS1990CharactersSelector, 16 }, 3253613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'liga', kLigaturesType, kCommonLigaturesOnSelector, kCommonLigaturesOffSelector }, 3263613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'lnum', kNumberCaseType, kUpperCaseNumbersSelector, 2 }, 3273613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'mgrk', kMathematicalExtrasType, kMathematicalGreekOnSelector, kMathematicalGreekOffSelector }, 3283613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'nlck', kCharacterShapeType, kNLCCharactersSelector, 16 }, 3293613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'onum', kNumberCaseType, kLowerCaseNumbersSelector, 2 }, 3303613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'ordn', kVerticalPositionType, kOrdinalsSelector, kNormalPositionSelector }, 3313613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'palt', kTextSpacingType, kAltProportionalTextSelector, 7 }, 3323613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'pcap', kLowerCaseType, kLowerCasePetiteCapsSelector, kDefaultLowerCaseSelector }, 3333613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'pkna', kTextSpacingType, kProportionalTextSelector, 7 }, 3343613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'pnum', kNumberSpacingType, kProportionalNumbersSelector, 4 }, 3353613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'pwid', kTextSpacingType, kProportionalTextSelector, 7 }, 3363613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'qwid', kTextSpacingType, kQuarterWidthTextSelector, 7 }, 3373613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'ruby', kRubyKanaType, kRubyKanaOnSelector, kRubyKanaOffSelector }, 3383613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'sinf', kVerticalPositionType, kScientificInferiorsSelector, kNormalPositionSelector }, 3393613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'smcp', kLowerCaseType, kLowerCaseSmallCapsSelector, kDefaultLowerCaseSelector }, 3403613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'smpl', kCharacterShapeType, kSimplifiedCharactersSelector, 16 }, 3413613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'ss01', kStylisticAlternativesType, kStylisticAltOneOnSelector, kStylisticAltOneOffSelector }, 3423613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'ss02', kStylisticAlternativesType, kStylisticAltTwoOnSelector, kStylisticAltTwoOffSelector }, 3433613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'ss03', kStylisticAlternativesType, kStylisticAltThreeOnSelector, kStylisticAltThreeOffSelector }, 3443613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'ss04', kStylisticAlternativesType, kStylisticAltFourOnSelector, kStylisticAltFourOffSelector }, 3453613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'ss05', kStylisticAlternativesType, kStylisticAltFiveOnSelector, kStylisticAltFiveOffSelector }, 3463613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'ss06', kStylisticAlternativesType, kStylisticAltSixOnSelector, kStylisticAltSixOffSelector }, 3473613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'ss07', kStylisticAlternativesType, kStylisticAltSevenOnSelector, kStylisticAltSevenOffSelector }, 3483613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'ss08', kStylisticAlternativesType, kStylisticAltEightOnSelector, kStylisticAltEightOffSelector }, 3493613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'ss09', kStylisticAlternativesType, kStylisticAltNineOnSelector, kStylisticAltNineOffSelector }, 3503613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'ss10', kStylisticAlternativesType, kStylisticAltTenOnSelector, kStylisticAltTenOffSelector }, 3513613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'ss11', kStylisticAlternativesType, kStylisticAltElevenOnSelector, kStylisticAltElevenOffSelector }, 3523613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'ss12', kStylisticAlternativesType, kStylisticAltTwelveOnSelector, kStylisticAltTwelveOffSelector }, 3533613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'ss13', kStylisticAlternativesType, kStylisticAltThirteenOnSelector, kStylisticAltThirteenOffSelector }, 3543613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'ss14', kStylisticAlternativesType, kStylisticAltFourteenOnSelector, kStylisticAltFourteenOffSelector }, 3553613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'ss15', kStylisticAlternativesType, kStylisticAltFifteenOnSelector, kStylisticAltFifteenOffSelector }, 3563613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'ss16', kStylisticAlternativesType, kStylisticAltSixteenOnSelector, kStylisticAltSixteenOffSelector }, 3573613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'ss17', kStylisticAlternativesType, kStylisticAltSeventeenOnSelector, kStylisticAltSeventeenOffSelector }, 3583613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'ss18', kStylisticAlternativesType, kStylisticAltEighteenOnSelector, kStylisticAltEighteenOffSelector }, 3593613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'ss19', kStylisticAlternativesType, kStylisticAltNineteenOnSelector, kStylisticAltNineteenOffSelector }, 3603613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'ss20', kStylisticAlternativesType, kStylisticAltTwentyOnSelector, kStylisticAltTwentyOffSelector }, 3613613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'subs', kVerticalPositionType, kInferiorsSelector, kNormalPositionSelector }, 3623613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'sups', kVerticalPositionType, kSuperiorsSelector, kNormalPositionSelector }, 3633613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'swsh', kContextualAlternatesType, kSwashAlternatesOnSelector, kSwashAlternatesOffSelector }, 3643613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'titl', kStyleOptionsType, kTitlingCapsSelector, kNoStyleOptionsSelector }, 3653613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'tnam', kCharacterShapeType, kTraditionalNamesCharactersSelector, 16 }, 3663613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'tnum', kNumberSpacingType, kMonospacedNumbersSelector, 4 }, 3673613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'trad', kCharacterShapeType, kTraditionalCharactersSelector, 16 }, 3683613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'twid', kTextSpacingType, kThirdWidthTextSelector, 7 }, 3693613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'unic', kLetterCaseType, 14, 15 }, 3703613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'valt', kTextSpacingType, kAltProportionalTextSelector, 7 }, 3713613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'vert', kVerticalSubstitutionType, kSubstituteVerticalFormsOnSelector, kSubstituteVerticalFormsOffSelector }, 3723613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'vhal', kTextSpacingType, kAltHalfWidthTextSelector, 7 }, 3733613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'vkna', kAlternateKanaType, kAlternateVertKanaOnSelector, kAlternateVertKanaOffSelector }, 3743613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'vpal', kTextSpacingType, kAltProportionalTextSelector, 7 }, 3753613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'vrt2', kVerticalSubstitutionType, kSubstituteVerticalFormsOnSelector, kSubstituteVerticalFormsOffSelector }, 3763613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 'zero', kTypographicExtrasType, kSlashedZeroOnSelector, kSlashedZeroOffSelector }, 3773613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod}; 3783613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 3793613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbodstatic int 3803613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod_hb_feature_mapping_cmp (const void *key_, const void *entry_) 3813613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod{ 3823613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod unsigned int key = * (unsigned int *) key_; 3833613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod const feature_mapping_t * entry = (const feature_mapping_t *) entry_; 3843613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod return key < entry->otFeatureTag ? -1 : 3853613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod key > entry->otFeatureTag ? 1 : 3863613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 0; 3873613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod} 3883613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 389aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kewhb_bool_t 390301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod_hb_coretext_shape (hb_shape_plan_t *shape_plan, 391301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod hb_font_t *font, 392aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew hb_buffer_t *buffer, 393aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew const hb_feature_t *features, 394aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew unsigned int num_features) 395aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew{ 396301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod hb_face_t *face = font->face; 39758cc233e8b5fdc9dce603acc1b968540a2dea3e1Behdad Esfahbod hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face); 398301168dae77a63ee25adfb26ce2b54a708f83791Behdad Esfahbod hb_coretext_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font); 399aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 4003613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod /* 4013613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod * Set up features. 4023613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod * (copied + modified from code from hb-uniscribe.cc) 4033613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod */ 4043613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod hb_auto_array_t<feature_record_t> feature_records; 4053613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod hb_auto_array_t<range_record_t> range_records; 4063613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod if (num_features) 4073613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 4083613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod /* Sort features by start/end events. */ 4093613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod hb_auto_array_t<feature_event_t> feature_events; 4103613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod for (unsigned int i = 0; i < num_features; i++) 4113613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 4123613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod const feature_mapping_t * mapping = (const feature_mapping_t *) bsearch (&features[i].tag, 4133613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod feature_mappings, 4143613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod ARRAY_LENGTH (feature_mappings), 4153613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod sizeof (feature_mappings[0]), 4163613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod _hb_feature_mapping_cmp); 4173613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod if (!mapping) 4183613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod continue; 4193613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 4203613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod active_feature_t feature; 4213613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod feature.rec.feature = mapping->aatFeatureType; 4223613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod feature.rec.setting = features[i].value ? mapping->selectorToEnable : mapping->selectorToDisable; 4233613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod feature.order = i; 4243613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 4253613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod feature_event_t *event; 4263613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 4273613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod event = feature_events.push (); 4283613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod if (unlikely (!event)) 4293613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod goto fail_features; 4303613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod event->index = features[i].start; 4313613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod event->start = true; 4323613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod event->feature = feature; 4333613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 4343613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod event = feature_events.push (); 4353613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod if (unlikely (!event)) 4363613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod goto fail_features; 4373613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod event->index = features[i].end; 4383613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod event->start = false; 4393613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod event->feature = feature; 4403613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod } 4413613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod feature_events.sort (); 4423613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod /* Add a strategic final event. */ 4433613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 4443613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod active_feature_t feature; 4453613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod feature.rec.feature = HB_TAG_NONE; 4463613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod feature.rec.setting = 0; 4473613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod feature.order = num_features + 1; 4483613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 4493613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod feature_event_t *event = feature_events.push (); 4503613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod if (unlikely (!event)) 4513613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod goto fail_features; 4523613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod event->index = 0; /* This value does magic. */ 4533613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod event->start = false; 4543613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod event->feature = feature; 4553613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod } 4563613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 4573613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod /* Scan events and save features for each range. */ 4583613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod hb_auto_array_t<active_feature_t> active_features; 4593613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod unsigned int last_index = 0; 4603613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod for (unsigned int i = 0; i < feature_events.len; i++) 4613613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 4623613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod feature_event_t *event = &feature_events[i]; 4633613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 4643613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod if (event->index != last_index) 4653613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 4663613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod /* Save a snapshot of active features and the range. */ 4673613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod range_record_t *range = range_records.push (); 4683613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod if (unlikely (!range)) 4693613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod goto fail_features; 4703613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 4713613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod unsigned int offset = feature_records.len; 4723613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 4733613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod if (active_features.len) 4743613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 4753613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod CFMutableArrayRef features_array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); 4763613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 4773613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod /* TODO sort and resolve conflicting features? */ 4783613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod /* active_features.sort (); */ 4793613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod for (unsigned int j = 0; j < active_features.len; j++) 4803613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 4813613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod CFStringRef keys[2] = { 4823613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod kCTFontFeatureTypeIdentifierKey, 4833613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod kCTFontFeatureSelectorIdentifierKey 4843613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod }; 4853613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod CFNumberRef values[2] = { 4863613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &active_features[j].rec.feature), 4873613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &active_features[j].rec.setting) 4883613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod }; 4893613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod CFDictionaryRef dict = CFDictionaryCreate (kCFAllocatorDefault, 4903613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod (const void **) keys, 4913613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod (const void **) values, 4923613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 2, 4933613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod &kCFTypeDictionaryKeyCallBacks, 4943613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod &kCFTypeDictionaryValueCallBacks); 4953613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod CFRelease (values[0]); 4963613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod CFRelease (values[1]); 4973613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 4983613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod CFArrayAppendValue (features_array, dict); 4993613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod CFRelease (dict); 5003613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 5013613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod } 5023613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 5033613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod CFDictionaryRef attributes = CFDictionaryCreate (kCFAllocatorDefault, 5043613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod (const void **) &kCTFontFeatureSettingsAttribute, 5053613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod (const void **) &features_array, 5063613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 1, 5073613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod &kCFTypeDictionaryKeyCallBacks, 5083613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod &kCFTypeDictionaryValueCallBacks); 5093613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod CFRelease (features_array); 5103613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 5113613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod CTFontDescriptorRef font_desc = CTFontDescriptorCreateWithAttributes (attributes); 5123613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod CFRelease (attributes); 5133613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 5143613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod range->font = CTFontCreateCopyWithAttributes (font_data->ct_font, 0.0, NULL, font_desc); 5153613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 5163613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod CFRelease (font_desc); 5173613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod } 5183613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod else 5193613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 5203613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod range->font = NULL; 5213613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod } 5223613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 5233613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod range->index_first = last_index; 5243613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod range->index_last = event->index - 1; 5253613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 5263613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod last_index = event->index; 5273613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod } 5283613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 5293613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod if (event->start) { 5303613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod active_feature_t *feature = active_features.push (); 5313613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod if (unlikely (!feature)) 5323613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod goto fail_features; 5333613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod *feature = event->feature; 5343613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod } else { 5353613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod active_feature_t *feature = active_features.find (&event->feature); 5363613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod if (feature) 5373613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod active_features.remove (feature - active_features.array); 5383613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod } 5393613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod } 5403613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 5413613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod if (!range_records.len) /* No active feature found. */ 5423613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod goto fail_features; 5433613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod } 5443613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod else 5453613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 5463613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod fail_features: 5473613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod num_features = 0; 5483613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod } 5493613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 550aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew#define FAIL(...) \ 551aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew HB_STMT_START { \ 552aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew DEBUG_MSG (CORETEXT, NULL, __VA_ARGS__); \ 553aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew return false; \ 554aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew } HB_STMT_END; 555aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 556aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew unsigned int scratch_size; 55768c372ed2eac76a6d347811293fe2ba2fd6a1eedBehdad Esfahbod hb_buffer_t::scratch_buffer_t *scratch = buffer->get_scratch_buffer (&scratch_size); 5588fcadb9cf9418345610e3f4e38c28c12b768b589Behdad Esfahbod 5598fcadb9cf9418345610e3f4e38c28c12b768b589Behdad Esfahbod#define ALLOCATE_ARRAY(Type, name, len) \ 5608fcadb9cf9418345610e3f4e38c28c12b768b589Behdad Esfahbod Type *name = (Type *) scratch; \ 5618fcadb9cf9418345610e3f4e38c28c12b768b589Behdad Esfahbod { \ 5628fcadb9cf9418345610e3f4e38c28c12b768b589Behdad Esfahbod unsigned int _consumed = DIV_CEIL ((len) * sizeof (Type), sizeof (*scratch)); \ 5638fcadb9cf9418345610e3f4e38c28c12b768b589Behdad Esfahbod assert (_consumed <= scratch_size); \ 5648fcadb9cf9418345610e3f4e38c28c12b768b589Behdad Esfahbod scratch += _consumed; \ 5658fcadb9cf9418345610e3f4e38c28c12b768b589Behdad Esfahbod scratch_size -= _consumed; \ 5668fcadb9cf9418345610e3f4e38c28c12b768b589Behdad Esfahbod } 567aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 568aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew#define utf16_index() var1.u32 569aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 5708fcadb9cf9418345610e3f4e38c28c12b768b589Behdad Esfahbod ALLOCATE_ARRAY (UniChar, pchars, buffer->len * 2); 5718fcadb9cf9418345610e3f4e38c28c12b768b589Behdad Esfahbod 572aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew unsigned int chars_len = 0; 573aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew for (unsigned int i = 0; i < buffer->len; i++) { 574aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew hb_codepoint_t c = buffer->info[i].codepoint; 575aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew buffer->info[i].utf16_index() = chars_len; 576aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew if (likely (c < 0x10000)) 577aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew pchars[chars_len++] = c; 578aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew else if (unlikely (c >= 0x110000)) 579aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew pchars[chars_len++] = 0xFFFD; 580aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew else { 581aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew pchars[chars_len++] = 0xD800 + ((c - 0x10000) >> 10); 582aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew pchars[chars_len++] = 0xDC00 + ((c - 0x10000) & ((1 << 10) - 1)); 583aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew } 584aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew } 585aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 586aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew#undef utf16_index 587aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 588a782a5e9a37c8733ac2830410a514d38635b543aBehdad Esfahbod CFStringRef string_ref = CFStringCreateWithCharactersNoCopy (NULL, 589aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew pchars, chars_len, 590aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew kCFAllocatorNull); 591aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 592a782a5e9a37c8733ac2830410a514d38635b543aBehdad Esfahbod CFMutableAttributedStringRef attr_string = CFAttributedStringCreateMutable (NULL, chars_len); 593a782a5e9a37c8733ac2830410a514d38635b543aBehdad Esfahbod CFAttributedStringReplaceString (attr_string, CFRangeMake (0, 0), string_ref); 594a782a5e9a37c8733ac2830410a514d38635b543aBehdad Esfahbod CFAttributedStringSetAttribute (attr_string, CFRangeMake (0, chars_len), 595a782a5e9a37c8733ac2830410a514d38635b543aBehdad Esfahbod kCTFontAttributeName, font_data->ct_font); 596a782a5e9a37c8733ac2830410a514d38635b543aBehdad Esfahbod 5973613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod if (num_features) 598a782a5e9a37c8733ac2830410a514d38635b543aBehdad Esfahbod { 5998fcadb9cf9418345610e3f4e38c28c12b768b589Behdad Esfahbod ALLOCATE_ARRAY (unsigned int, log_clusters, chars_len); 600a782a5e9a37c8733ac2830410a514d38635b543aBehdad Esfahbod 6013613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod /* Need log_clusters to assign features. */ 6023613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod chars_len = 0; 6033613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod for (unsigned int i = 0; i < buffer->len; i++) 604a782a5e9a37c8733ac2830410a514d38635b543aBehdad Esfahbod { 6053613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod hb_codepoint_t c = buffer->info[i].codepoint; 6063613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod unsigned int cluster = buffer->info[i].cluster; 6073613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod log_clusters[chars_len++] = cluster; 6083613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod if (c >= 0x10000 && c < 0x110000) 6093613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod log_clusters[chars_len++] = cluster; /* Surrogates. */ 610a782a5e9a37c8733ac2830410a514d38635b543aBehdad Esfahbod } 611aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 6123613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod unsigned int start = 0; 6133613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod range_record_t *last_range = &range_records[0]; 6143613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod for (unsigned int k = 0; k < chars_len; k++) 615a782a5e9a37c8733ac2830410a514d38635b543aBehdad Esfahbod { 6163613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod range_record_t *range = last_range; 6173613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod while (log_clusters[k] < range->index_first) 6183613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod range--; 6193613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod while (log_clusters[k] > range->index_last) 6203613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod range++; 6213613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod if (range != last_range) 6223613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod { 6233613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod if (last_range->font) 6243613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod CFAttributedStringSetAttribute (attr_string, CFRangeMake (start, k - start), 6253613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod kCTFontAttributeName, last_range->font); 6263613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 6273613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod start = k; 6283613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod } 6293613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 6303613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod last_range = range; 631a782a5e9a37c8733ac2830410a514d38635b543aBehdad Esfahbod } 6323613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod if (start != chars_len && last_range->font) 6333613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod CFAttributedStringSetAttribute (attr_string, CFRangeMake (start, chars_len - start - 1), 6343613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod kCTFontAttributeName, last_range->font); 6353613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod 6363613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod for (unsigned int i = 0; i < range_records.len; i++) 6373613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod if (range_records[i].font) 6383613696b57225111507a3f4263f5fa6937d0bc72Behdad Esfahbod CFRelease (range_records[i].font); 639a782a5e9a37c8733ac2830410a514d38635b543aBehdad Esfahbod } 640aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 641aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew CTLineRef line = CTLineCreateWithAttributedString (attr_string); 642aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew CFRelease (attr_string); 643aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 644aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew CFArrayRef glyph_runs = CTLineGetGlyphRuns (line); 645aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew unsigned int num_runs = CFArrayGetCount (glyph_runs); 646aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 647aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew buffer->len = 0; 648aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 649aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew const CFRange range_all = CFRangeMake (0, 0); 650aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 65158cc233e8b5fdc9dce603acc1b968540a2dea3e1Behdad Esfahbod for (unsigned int i = 0; i < num_runs; i++) 65258cc233e8b5fdc9dce603acc1b968540a2dea3e1Behdad Esfahbod { 653aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew CTRunRef run = (CTRunRef) CFArrayGetValueAtIndex (glyph_runs, i); 654aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 655c8213c6198abff97822e29a6d565722cfbb43832Khaled Hosny /* CoreText does automatic font fallback (AKA "cascading") for characters 656c8213c6198abff97822e29a6d565722cfbb43832Khaled Hosny * not supported by the requested font, and provides no way to turn it off, 657c8213c6198abff97822e29a6d565722cfbb43832Khaled Hosny * so we detect if the returned run uses a font other than the requested 658c8213c6198abff97822e29a6d565722cfbb43832Khaled Hosny * one and fill in the buffer with .notdef glyphs instead of random glyph 659c8213c6198abff97822e29a6d565722cfbb43832Khaled Hosny * indices from a different font. 660c8213c6198abff97822e29a6d565722cfbb43832Khaled Hosny */ 661c8213c6198abff97822e29a6d565722cfbb43832Khaled Hosny CFDictionaryRef attributes = CTRunGetAttributes (run); 662c8213c6198abff97822e29a6d565722cfbb43832Khaled Hosny CTFontRef run_ct_font = static_cast<CTFontRef>(CFDictionaryGetValue (attributes, kCTFontAttributeName)); 663c8213c6198abff97822e29a6d565722cfbb43832Khaled Hosny CGFontRef run_cg_font = CTFontCopyGraphicsFont (run_ct_font, 0); 66458cc233e8b5fdc9dce603acc1b968540a2dea3e1Behdad Esfahbod if (!CFEqual (run_cg_font, face_data->cg_font)) 66558cc233e8b5fdc9dce603acc1b968540a2dea3e1Behdad Esfahbod { 666c8213c6198abff97822e29a6d565722cfbb43832Khaled Hosny CFRelease (run_cg_font); 66758cc233e8b5fdc9dce603acc1b968540a2dea3e1Behdad Esfahbod 66858cc233e8b5fdc9dce603acc1b968540a2dea3e1Behdad Esfahbod CFRange range = CTRunGetStringRange (run); 66958cc233e8b5fdc9dce603acc1b968540a2dea3e1Behdad Esfahbod buffer->ensure (buffer->len + range.length); 67058cc233e8b5fdc9dce603acc1b968540a2dea3e1Behdad Esfahbod if (buffer->in_error) 67158cc233e8b5fdc9dce603acc1b968540a2dea3e1Behdad Esfahbod FAIL ("Buffer resize failed"); 67258cc233e8b5fdc9dce603acc1b968540a2dea3e1Behdad Esfahbod hb_glyph_info_t *info = buffer->info + buffer->len; 67358cc233e8b5fdc9dce603acc1b968540a2dea3e1Behdad Esfahbod 674748b2782e4898420003a3bbc041dcccbe9e3edc2Behdad Esfahbod CGGlyph notdef = 0; 675748b2782e4898420003a3bbc041dcccbe9e3edc2Behdad Esfahbod double advance = CTFontGetAdvancesForGlyphs (font_data->ct_font, kCTFontHorizontalOrientation, ¬def, NULL, 1); 676748b2782e4898420003a3bbc041dcccbe9e3edc2Behdad Esfahbod 677c29993a181c2139eaec97b5f6225824040ca3ac9Behdad Esfahbod for (CFIndex j = range.location; j < range.location + range.length; j++) 67858cc233e8b5fdc9dce603acc1b968540a2dea3e1Behdad Esfahbod { 679c29993a181c2139eaec97b5f6225824040ca3ac9Behdad Esfahbod UniChar ch = CFStringGetCharacterAtIndex (string_ref, j); 680c29993a181c2139eaec97b5f6225824040ca3ac9Behdad Esfahbod if (hb_in_range<UniChar> (ch, 0xDC00, 0xDFFF) && range.location < j) 681c29993a181c2139eaec97b5f6225824040ca3ac9Behdad Esfahbod { 682c29993a181c2139eaec97b5f6225824040ca3ac9Behdad Esfahbod ch = CFStringGetCharacterAtIndex (string_ref, j - 1); 683c29993a181c2139eaec97b5f6225824040ca3ac9Behdad Esfahbod if (hb_in_range<UniChar> (ch, 0xD800, 0xDBFF)) 684c29993a181c2139eaec97b5f6225824040ca3ac9Behdad Esfahbod /* This is the second of a surrogate pair. Don't need .notdef 685c29993a181c2139eaec97b5f6225824040ca3ac9Behdad Esfahbod * for this one. */ 686c29993a181c2139eaec97b5f6225824040ca3ac9Behdad Esfahbod continue; 687c29993a181c2139eaec97b5f6225824040ca3ac9Behdad Esfahbod } 688c29993a181c2139eaec97b5f6225824040ca3ac9Behdad Esfahbod 689c8213c6198abff97822e29a6d565722cfbb43832Khaled Hosny info->codepoint = notdef; 690aec468f01e866c99e65a8f764a792c74c96840d7Behdad Esfahbod /* TODO We have to fixup clusters later. See vis_clusters in 691aec468f01e866c99e65a8f764a792c74c96840d7Behdad Esfahbod * hb-uniscribe.cc for example. */ 692c29993a181c2139eaec97b5f6225824040ca3ac9Behdad Esfahbod info->cluster = j; 693c8213c6198abff97822e29a6d565722cfbb43832Khaled Hosny 694c8213c6198abff97822e29a6d565722cfbb43832Khaled Hosny info->mask = advance; 695c8213c6198abff97822e29a6d565722cfbb43832Khaled Hosny info->var1.u32 = 0; 696c8213c6198abff97822e29a6d565722cfbb43832Khaled Hosny info->var2.u32 = 0; 697c8213c6198abff97822e29a6d565722cfbb43832Khaled Hosny 69858cc233e8b5fdc9dce603acc1b968540a2dea3e1Behdad Esfahbod info++; 699c29993a181c2139eaec97b5f6225824040ca3ac9Behdad Esfahbod buffer->len++; 700c8213c6198abff97822e29a6d565722cfbb43832Khaled Hosny } 701c8213c6198abff97822e29a6d565722cfbb43832Khaled Hosny continue; 702c8213c6198abff97822e29a6d565722cfbb43832Khaled Hosny } 703c8213c6198abff97822e29a6d565722cfbb43832Khaled Hosny CFRelease (run_cg_font); 704c8213c6198abff97822e29a6d565722cfbb43832Khaled Hosny 705aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew unsigned int num_glyphs = CTRunGetGlyphCount (run); 706aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew if (num_glyphs == 0) 707aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew continue; 708aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 709aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew buffer->ensure (buffer->len + num_glyphs); 710aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 71168c372ed2eac76a6d347811293fe2ba2fd6a1eedBehdad Esfahbod scratch = buffer->get_scratch_buffer (&scratch_size); 712aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 71316f175cb2e081e605fe7f9cd01bbe8c24380278aBehdad Esfahbod /* Testing indicates that CTRunGetGlyphsPtr, etc (almost?) always 71416f175cb2e081e605fe7f9cd01bbe8c24380278aBehdad Esfahbod * succeed, and so copying data to our own buffer will be rare. */ 715aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 716aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew const CGGlyph* glyphs = CTRunGetGlyphsPtr (run); 717aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew if (!glyphs) { 718aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew ALLOCATE_ARRAY (CGGlyph, glyph_buf, num_glyphs); 719aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew CTRunGetGlyphs (run, range_all, glyph_buf); 720aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew glyphs = glyph_buf; 721aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew } 722aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 723aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew const CGPoint* positions = CTRunGetPositionsPtr (run); 724aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew if (!positions) { 725aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew ALLOCATE_ARRAY (CGPoint, position_buf, num_glyphs); 726aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew CTRunGetPositions (run, range_all, position_buf); 727aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew positions = position_buf; 728aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew } 729aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 730aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew const CFIndex* string_indices = CTRunGetStringIndicesPtr (run); 731aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew if (!string_indices) { 732aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew ALLOCATE_ARRAY (CFIndex, index_buf, num_glyphs); 733aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew CTRunGetStringIndices (run, range_all, index_buf); 734aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew string_indices = index_buf; 735aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew } 736aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 737aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew#undef ALLOCATE_ARRAY 738aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 739aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew double run_width = CTRunGetTypographicBounds (run, range_all, NULL, NULL, NULL); 740aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 741aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew for (unsigned int j = 0; j < num_glyphs; j++) { 742aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew double advance = (j + 1 < num_glyphs ? positions[j + 1].x : positions[0].x + run_width) - positions[j].x; 743aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 744aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew hb_glyph_info_t *info = &buffer->info[buffer->len]; 745aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 746aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew info->codepoint = glyphs[j]; 747aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew info->cluster = string_indices[j]; 748aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 7497d52e6601f0e695690cd168a288466746cf25300Behdad Esfahbod /* Currently, we do all x-positioning by setting the advance, we never use x-offset. */ 750aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew info->mask = advance; 751aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew info->var1.u32 = 0; 752aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew info->var2.u32 = positions[j].y; 753aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 754aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew buffer->len++; 755aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew } 756aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew } 757aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 758aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew buffer->clear_positions (); 759aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 760aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew unsigned int count = buffer->len; 761aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew for (unsigned int i = 0; i < count; ++i) { 762aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew hb_glyph_info_t *info = &buffer->info[i]; 763aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew hb_glyph_position_t *pos = &buffer->pos[i]; 764aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 765aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew /* TODO vertical */ 766aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew pos->x_advance = info->mask; 767aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew pos->x_offset = info->var1.u32; 768aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew pos->y_offset = info->var2.u32; 769aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew } 770aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 7717d52e6601f0e695690cd168a288466746cf25300Behdad Esfahbod /* Fix up clusters so that we never return out-of-order indices; 7727d52e6601f0e695690cd168a288466746cf25300Behdad Esfahbod * if core text has reordered glyphs, we'll merge them to the 7737d52e6601f0e695690cd168a288466746cf25300Behdad Esfahbod * beginning of the reordered cluster. 7747d52e6601f0e695690cd168a288466746cf25300Behdad Esfahbod * 7757d52e6601f0e695690cd168a288466746cf25300Behdad Esfahbod * This does *not* mean we'll form the same clusters as Uniscribe 7767d52e6601f0e695690cd168a288466746cf25300Behdad Esfahbod * or the native OT backend, only that the cluster indices will be 7777d52e6601f0e695690cd168a288466746cf25300Behdad Esfahbod * monotonic in the output buffer. */ 778ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew if (HB_DIRECTION_IS_FORWARD (buffer->props.direction)) { 779ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew unsigned int prev_cluster = 0; 780ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew for (unsigned int i = 0; i < count; i++) { 781ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew unsigned int curr_cluster = buffer->info[i].cluster; 782ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew if (curr_cluster < prev_cluster) { 783ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew for (unsigned int j = i; j > 0; j--) { 784ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew if (buffer->info[j - 1].cluster > curr_cluster) 785ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew buffer->info[j - 1].cluster = curr_cluster; 786ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew else 787ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew break; 788ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew } 789ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew } 790ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew prev_cluster = curr_cluster; 791ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew } 792ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew } else { 793ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew unsigned int prev_cluster = (unsigned int)-1; 794ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew for (unsigned int i = 0; i < count; i++) { 795ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew unsigned int curr_cluster = buffer->info[i].cluster; 796ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew if (curr_cluster > prev_cluster) { 797ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew for (unsigned int j = i; j > 0; j--) { 798ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew if (buffer->info[j - 1].cluster < curr_cluster) 799ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew buffer->info[j - 1].cluster = curr_cluster; 800ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew else 801ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew break; 802ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew } 803ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew } 804ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew prev_cluster = curr_cluster; 805ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew } 806ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew } 807ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew 808c29993a181c2139eaec97b5f6225824040ca3ac9Behdad Esfahbod CFRelease (string_ref); 809c461371419d186811d4bfc768e26535f48a807f4Behdad Esfahbod CFRelease (line); 810c461371419d186811d4bfc768e26535f48a807f4Behdad Esfahbod 811aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew return true; 812aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew} 813