hb-coretext.cc revision ac2085d4b391b0a72473ecac3dd6c22efe66833f
1aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew/* 2aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew * Copyright © 2012 Mozilla Foundation. 3aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew * 4aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew * This is part of HarfBuzz, a text shaping library. 5aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew * 6aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew * Permission is hereby granted, without written agreement and without 7aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew * license or royalty fees, to use, copy, modify, and distribute this 8aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew * software and its documentation for any purpose, provided that the 9aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew * above copyright notice and the following two paragraphs appear in 10aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew * all copies of this software. 11aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew * 12aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 13aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 14aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 15aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 16aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew * DAMAGE. 17aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew * 18aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 19aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 20aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 21aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 22aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 23aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew * 24aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew * Mozilla Author(s): Jonathan Kew 25aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew */ 26aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 27aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew#include "hb-private.hh" 28aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 29aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew#define GlyphID GlyphID_mac 30aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew#include <ApplicationServices/ApplicationServices.h> 31aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew#undef GlyphID 32aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 33aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew#include "hb-coretext.h" 34aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 35aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew#include "hb-ot-name-table.hh" 36aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew#include "hb-ot-tag.h" 37aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 38aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew#include "hb-font-private.hh" 39aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew#include "hb-buffer-private.hh" 40aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 41aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 42aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew#ifndef HB_DEBUG_CORETEXT 43aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew#define HB_DEBUG_CORETEXT (HB_DEBUG+0) 44aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew#endif 45aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 46aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 47aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kewstatic hb_user_data_key_t hb_coretext_data_key; 48aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 49aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kewstatic struct hb_coretext_face_data_t { 50aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew CGFontRef cg_font; 51aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew} _hb_coretext_face_data_nil = {0}; 52aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 53aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kewstatic void 54aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew_hb_coretext_face_data_destroy (hb_coretext_face_data_t *data) 55aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew{ 56aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew if (data->cg_font) 57aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew CFRelease (data->cg_font); 58aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew free (data); 59aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew} 60aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 61aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kewstatic void 62aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kewrelease_data (void *info, const void *data, size_t size) 63aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew{ 64aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew assert (hb_blob_get_length ((hb_blob_t *) info) == size && 65aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew hb_blob_get_data ((hb_blob_t *) info, NULL) == data); 66aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 67aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew hb_blob_destroy ((hb_blob_t *) info); 68aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew} 69aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 70aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kewstatic hb_coretext_face_data_t * 71aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew_hb_coretext_face_get_data (hb_face_t *face) 72aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew{ 73aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew hb_coretext_face_data_t *data = (hb_coretext_face_data_t *) hb_face_get_user_data (face, &hb_coretext_data_key); 74aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew if (likely (data)) return data; 75aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 76aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew data = (hb_coretext_face_data_t *) calloc (1, sizeof (hb_coretext_face_data_t)); 77aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew if (unlikely (!data)) 78aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew return &_hb_coretext_face_data_nil; 79aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 80aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 81aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew hb_blob_t *blob = hb_face_reference_blob (face); 82aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew unsigned int blob_length; 83aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew const char *blob_data = hb_blob_get_data (blob, &blob_length); 84aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew if (unlikely (!blob_length)) 85aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew DEBUG_MSG (CORETEXT, face, "Face has empty blob"); 86aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 87aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew CGDataProviderRef provider = CGDataProviderCreateWithData (blob, blob_data, blob_length, &release_data); 88aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew data->cg_font = CGFontCreateWithDataProvider (provider); 89aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew CGDataProviderRelease (provider); 90aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 91aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew if (unlikely (!data->cg_font)) 92aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew DEBUG_MSG (CORETEXT, face, "Face CGFontCreateWithDataProvider() failed"); 93aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 94aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 95aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew if (unlikely (!hb_face_set_user_data (face, &hb_coretext_data_key, data, 96aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew (hb_destroy_func_t) _hb_coretext_face_data_destroy, 97aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew false))) 98aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew { 99aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew _hb_coretext_face_data_destroy (data); 100aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew data = (hb_coretext_face_data_t *) hb_face_get_user_data (face, &hb_coretext_data_key); 101aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew if (data) 102aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew return data; 103aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew else 104aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew return &_hb_coretext_face_data_nil; 105aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew } 106aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 107aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew return data; 108aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew} 109aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 110aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 111aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kewstatic struct hb_coretext_font_data_t { 112aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew CTFontRef ct_font; 113aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew} _hb_coretext_font_data_nil = {0}; 114aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 115aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kewstatic void 116aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew_hb_coretext_font_data_destroy (hb_coretext_font_data_t *data) 117aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew{ 118aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew if (data->ct_font) 119aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew CFRelease (data->ct_font); 120aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew free (data); 121aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew} 122aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 123aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kewstatic hb_coretext_font_data_t * 124aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew_hb_coretext_font_get_data (hb_font_t *font) 125aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew{ 126aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew hb_coretext_font_data_t *data = (hb_coretext_font_data_t *) hb_font_get_user_data (font, &hb_coretext_data_key); 127aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew if (likely (data)) return data; 128aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 129aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew data = (hb_coretext_font_data_t *) calloc (1, sizeof (hb_coretext_font_data_t)); 130aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew if (unlikely (!data)) 131aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew return &_hb_coretext_font_data_nil; 132aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 133aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew hb_coretext_face_data_t *face_data = _hb_coretext_face_get_data (font->face); 134aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 135aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew data->ct_font = CTFontCreateWithGraphicsFont (face_data->cg_font, font->y_scale, NULL, NULL); 136aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew if (unlikely (!data->ct_font)) 137aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew DEBUG_MSG (CORETEXT, font, "Font CTFontCreateWithGraphicsFont() failed"); 138aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 139aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew if (unlikely (!hb_font_set_user_data (font, &hb_coretext_data_key, data, 140aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew (hb_destroy_func_t) _hb_coretext_font_data_destroy, 141aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew false))) 142aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew { 143aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew _hb_coretext_font_data_destroy (data); 144aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew data = (hb_coretext_font_data_t *) hb_font_get_user_data (font, &hb_coretext_data_key); 145aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew if (data) 146aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew return data; 147aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew else 148aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew return &_hb_coretext_font_data_nil; 149aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew } 150aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 151aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew return data; 152aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew} 153aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 154aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan KewCTFontRef 155aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kewhb_coretext_font_get_ct_font (hb_font_t *font) 156aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew{ 157aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew hb_coretext_font_data_t *font_data = _hb_coretext_font_get_data (font); 158aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew if (unlikely (!font_data)) 159aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew return 0; 160aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew return font_data->ct_font; 161aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew} 162aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 163aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 164aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kewhb_bool_t 165aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew_hb_coretext_shape (hb_font_t *font, 166aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew hb_buffer_t *buffer, 167aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew const hb_feature_t *features, 168aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew unsigned int num_features) 169aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew{ 170aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew buffer->guess_properties (); 171aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 172aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew#define FAIL(...) \ 173aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew HB_STMT_START { \ 174aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew DEBUG_MSG (CORETEXT, NULL, __VA_ARGS__); \ 175aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew return false; \ 176aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew } HB_STMT_END; 177aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 178aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew hb_coretext_face_data_t *face_data = _hb_coretext_face_get_data (font->face); 179aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew if (unlikely (!face_data->cg_font)) 180aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew FAIL ("Couldn't get face data"); 181aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 182aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew hb_coretext_font_data_t *font_data = _hb_coretext_font_get_data (font); 183aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew if (unlikely (!font_data->ct_font)) 184aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew FAIL ("Couldn't get font font"); 185aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 186aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew if (unlikely (!buffer->len)) 187aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew return true; 188aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 189aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew unsigned int scratch_size; 190aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew char *scratch = (char *) buffer->get_scratch_buffer (&scratch_size); 191aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 192aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew#define utf16_index() var1.u32 193aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 194aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew UniChar *pchars = (UniChar *) scratch; 195aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew unsigned int chars_len = 0; 196aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew for (unsigned int i = 0; i < buffer->len; i++) { 197aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew hb_codepoint_t c = buffer->info[i].codepoint; 198aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew buffer->info[i].utf16_index() = chars_len; 199aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew if (likely (c < 0x10000)) 200aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew pchars[chars_len++] = c; 201aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew else if (unlikely (c >= 0x110000)) 202aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew pchars[chars_len++] = 0xFFFD; 203aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew else { 204aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew pchars[chars_len++] = 0xD800 + ((c - 0x10000) >> 10); 205aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew pchars[chars_len++] = 0xDC00 + ((c - 0x10000) & ((1 << 10) - 1)); 206aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew } 207aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew } 208aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 209aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew#undef utf16_index 210aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 211aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew CFStringRef string_ref = CFStringCreateWithCharactersNoCopy (kCFAllocatorDefault, 212aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew pchars, chars_len, 213aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew kCFAllocatorNull); 214aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 215aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew CFDictionaryRef attrs = CFDictionaryCreate (kCFAllocatorDefault, 216aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew (const void**) &kCTFontAttributeName, 217aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew (const void**) &font_data->ct_font, 218aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 1, // count of attributes 219aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew &kCFTypeDictionaryKeyCallBacks, 220aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew &kCFTypeDictionaryValueCallBacks); 221aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 222aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew // TODO: support features 223aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 224aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew // Now we can create an attributed string 225aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew CFAttributedStringRef attr_string = CFAttributedStringCreate (kCFAllocatorDefault, string_ref, attrs); 226aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew CFRelease (string_ref); 227aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew CFRelease (attrs); 228aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 229aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew // Create the CoreText line from our string, then we're done with it 230aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew CTLineRef line = CTLineCreateWithAttributedString (attr_string); 231aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew CFRelease (attr_string); 232aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 233aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew // and finally retrieve the glyph data and store into the gfxTextRun 234aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew CFArrayRef glyph_runs = CTLineGetGlyphRuns (line); 235aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew unsigned int num_runs = CFArrayGetCount (glyph_runs); 236aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 237aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew // Iterate through the glyph runs. 238aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew bool success = true; 239aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew buffer->len = 0; 240aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 241aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew const CFRange range_all = CFRangeMake (0, 0); 242aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 243aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew for (unsigned int i = 0; i < num_runs; i++) { 244aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew CTRunRef run = (CTRunRef) CFArrayGetValueAtIndex (glyph_runs, i); 245aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 246aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew unsigned int num_glyphs = CTRunGetGlyphCount (run); 247aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew if (num_glyphs == 0) 248aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew continue; 249aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 250aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew buffer->ensure (buffer->len + num_glyphs); 251aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 252aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew // retrieve the laid-out glyph data from the CTRun 253aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 254aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew // Testing indicates that CTRunGetGlyphsPtr (almost?) always succeeds, 255aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew // and so copying data to our own buffer with CTRunGetGlyphs will be 256aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew // extremely rare. 257aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 258aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew unsigned int scratch_size; 259aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew char *scratch = (char *) buffer->get_scratch_buffer (&scratch_size); 260aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 261aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew#define ALLOCATE_ARRAY(Type, name, len) \ 262aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew Type *name = (Type *) scratch; \ 263441d3bb7de311d54b9f0a5210344f9a96e97e153Behdad Esfahbod scratch += (len) * sizeof ((name)[0]); \ 264441d3bb7de311d54b9f0a5210344f9a96e97e153Behdad Esfahbod scratch_size -= (len) * sizeof ((name)[0]); 265aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 266aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew const CGGlyph* glyphs = CTRunGetGlyphsPtr (run); 267aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew if (!glyphs) { 268aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew ALLOCATE_ARRAY (CGGlyph, glyph_buf, num_glyphs); 269aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew CTRunGetGlyphs (run, range_all, glyph_buf); 270aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew glyphs = glyph_buf; 271aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew } 272aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 273aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew const CGPoint* positions = CTRunGetPositionsPtr (run); 274aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew if (!positions) { 275aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew ALLOCATE_ARRAY (CGPoint, position_buf, num_glyphs); 276aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew CTRunGetPositions (run, range_all, position_buf); 277aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew positions = position_buf; 278aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew } 279aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 280aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew const CFIndex* string_indices = CTRunGetStringIndicesPtr (run); 281aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew if (!string_indices) { 282aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew ALLOCATE_ARRAY (CFIndex, index_buf, num_glyphs); 283aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew CTRunGetStringIndices (run, range_all, index_buf); 284aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew string_indices = index_buf; 285aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew } 286aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 287aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew#undef ALLOCATE_ARRAY 288aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 289aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew double run_width = CTRunGetTypographicBounds (run, range_all, NULL, NULL, NULL); 290aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 291aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew for (unsigned int j = 0; j < num_glyphs; j++) { 292aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew double advance = (j + 1 < num_glyphs ? positions[j + 1].x : positions[0].x + run_width) - positions[j].x; 293aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 294aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew hb_glyph_info_t *info = &buffer->info[buffer->len]; 295aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew hb_glyph_position_t *pos = &buffer->pos[buffer->len]; 296aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 297aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew info->codepoint = glyphs[j]; 298aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew info->cluster = string_indices[j]; 299aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 300aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew // currently, we do all x-positioning by setting the advance, we never use x-offset 301aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew info->mask = advance; 302aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew info->var1.u32 = 0; 303aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew info->var2.u32 = positions[j].y; 304aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 305aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew buffer->len++; 306aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew } 307aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew } 308aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 309aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew buffer->clear_positions (); 310aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 311aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew unsigned int count = buffer->len; 312aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew for (unsigned int i = 0; i < count; ++i) { 313aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew hb_glyph_info_t *info = &buffer->info[i]; 314aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew hb_glyph_position_t *pos = &buffer->pos[i]; 315aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 316aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew /* TODO vertical */ 317aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew pos->x_advance = info->mask; 318aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew pos->x_offset = info->var1.u32; 319aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew pos->y_offset = info->var2.u32; 320aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew } 321aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew 322ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew // Fix up clusters so that we never return out-of-order indices; 323ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew // if core text has reordered glyphs, we'll merge them to the 324ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew // beginning of the reordered cluster. 325ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew // This does *not* mean we'll form the same clusters as Uniscribe 326ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew // or the native OT backend, only that the cluster indices will be 327ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew // non-decreasing in the output buffer. 328ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew if (HB_DIRECTION_IS_FORWARD (buffer->props.direction)) { 329ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew unsigned int prev_cluster = 0; 330ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew for (unsigned int i = 0; i < count; i++) { 331ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew unsigned int curr_cluster = buffer->info[i].cluster; 332ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew if (curr_cluster < prev_cluster) { 333ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew for (unsigned int j = i; j > 0; j--) { 334ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew if (buffer->info[j - 1].cluster > curr_cluster) 335ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew buffer->info[j - 1].cluster = curr_cluster; 336ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew else 337ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew break; 338ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew } 339ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew } 340ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew prev_cluster = curr_cluster; 341ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew } 342ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew } else { 343ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew // For RTL runs, we make them non-increasing instead. 344ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew unsigned int prev_cluster = (unsigned int)-1; 345ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew for (unsigned int i = 0; i < count; i++) { 346ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew unsigned int curr_cluster = buffer->info[i].cluster; 347ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew if (curr_cluster > prev_cluster) { 348ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew for (unsigned int j = i; j > 0; j--) { 349ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew if (buffer->info[j - 1].cluster < curr_cluster) 350ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew buffer->info[j - 1].cluster = curr_cluster; 351ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew else 352ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew break; 353ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew } 354ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew } 355ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew prev_cluster = curr_cluster; 356ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew } 357ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew } 358ac2085d4b391b0a72473ecac3dd6c22efe66833fJonathan Kew 359aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew return true; 360aa6d849838d5231465ae1a25a4dd5ea1e9380ff9Jonathan Kew} 361