1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/harfbuzz/src/hb-icu-le.cc Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,215 @@ 1.4 +/* 1.5 + * Copyright © 2012 Google, Inc. 1.6 + * 1.7 + * This is part of HarfBuzz, a text shaping library. 1.8 + * 1.9 + * Permission is hereby granted, without written agreement and without 1.10 + * license or royalty fees, to use, copy, modify, and distribute this 1.11 + * software and its documentation for any purpose, provided that the 1.12 + * above copyright notice and the following two paragraphs appear in 1.13 + * all copies of this software. 1.14 + * 1.15 + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 1.16 + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 1.17 + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 1.18 + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 1.19 + * DAMAGE. 1.20 + * 1.21 + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 1.22 + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 1.23 + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 1.24 + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 1.25 + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 1.26 + * 1.27 + * Google Author(s): Behdad Esfahbod 1.28 + */ 1.29 + 1.30 +#define HB_SHAPER icu_le 1.31 +#define hb_icu_le_shaper_font_data_t PortableFontInstance 1.32 +#include "hb-shaper-impl-private.hh" 1.33 + 1.34 +#include "hb-icu-le/PortableFontInstance.h" 1.35 + 1.36 +#include "layout/loengine.h" 1.37 +#include "unicode/unistr.h" 1.38 + 1.39 +#include "hb-icu.h" 1.40 + 1.41 + 1.42 +/* 1.43 + * shaper face data 1.44 + */ 1.45 + 1.46 +struct hb_icu_le_shaper_face_data_t {}; 1.47 + 1.48 +hb_icu_le_shaper_face_data_t * 1.49 +_hb_icu_le_shaper_face_data_create (hb_face_t *face HB_UNUSED) 1.50 +{ 1.51 + return (hb_icu_le_shaper_face_data_t *) HB_SHAPER_DATA_SUCCEEDED; 1.52 +} 1.53 + 1.54 +void 1.55 +_hb_icu_le_shaper_face_data_destroy (hb_icu_le_shaper_face_data_t *data HB_UNUSED) 1.56 +{ 1.57 +} 1.58 + 1.59 + 1.60 +/* 1.61 + * shaper font data 1.62 + */ 1.63 + 1.64 +hb_icu_le_shaper_font_data_t * 1.65 +_hb_icu_le_shaper_font_data_create (hb_font_t *font) 1.66 +{ 1.67 + LEErrorCode status = LE_NO_ERROR; 1.68 + hb_icu_le_shaper_font_data_t *data = new PortableFontInstance (font->face, 1.69 + font->x_scale, 1.70 + font->y_scale, 1.71 + status); 1.72 + if (status != LE_NO_ERROR) { 1.73 + delete (data); 1.74 + return NULL; 1.75 + } 1.76 + 1.77 + return data; 1.78 +} 1.79 + 1.80 +void 1.81 +_hb_icu_le_shaper_font_data_destroy (hb_icu_le_shaper_font_data_t *data) 1.82 +{ 1.83 + delete (data); 1.84 +} 1.85 + 1.86 + 1.87 +/* 1.88 + * shaper shape_plan data 1.89 + */ 1.90 + 1.91 +struct hb_icu_le_shaper_shape_plan_data_t {}; 1.92 + 1.93 +hb_icu_le_shaper_shape_plan_data_t * 1.94 +_hb_icu_le_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED, 1.95 + const hb_feature_t *user_features, 1.96 + unsigned int num_user_features) 1.97 +{ 1.98 + return (hb_icu_le_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED; 1.99 +} 1.100 + 1.101 +void 1.102 +_hb_icu_le_shaper_shape_plan_data_destroy (hb_icu_le_shaper_shape_plan_data_t *data) 1.103 +{ 1.104 +} 1.105 + 1.106 + 1.107 +/* 1.108 + * shaper 1.109 + */ 1.110 + 1.111 +hb_bool_t 1.112 +_hb_icu_le_shape (hb_shape_plan_t *shape_plan, 1.113 + hb_font_t *font, 1.114 + hb_buffer_t *buffer, 1.115 + const hb_feature_t *features, 1.116 + unsigned int num_features) 1.117 +{ 1.118 + LEFontInstance *font_instance = HB_SHAPER_DATA_GET (font); 1.119 + le_int32 script_code = hb_icu_script_from_script (shape_plan->props.script); 1.120 + le_int32 language_code = -1 /* TODO */; 1.121 + le_int32 typography_flags = 3; /* Needed for ligatures and kerning */ 1.122 + LEErrorCode status = LE_NO_ERROR; 1.123 + le_engine *le = le_create ((const le_font *) font_instance, 1.124 + script_code, 1.125 + language_code, 1.126 + typography_flags, 1.127 + &status); 1.128 + if (status != LE_NO_ERROR) 1.129 + { le_close (le); return false; } 1.130 + 1.131 +retry: 1.132 + 1.133 + unsigned int scratch_size; 1.134 + char *scratch = (char *) buffer->get_scratch_buffer (&scratch_size); 1.135 + 1.136 +#define ALLOCATE_ARRAY(Type, name, len) \ 1.137 + Type *name = (Type *) scratch; \ 1.138 + scratch += (len) * sizeof ((name)[0]); \ 1.139 + scratch_size -= (len) * sizeof ((name)[0]); 1.140 + 1.141 + ALLOCATE_ARRAY (LEUnicode, chars, buffer->len); 1.142 + ALLOCATE_ARRAY (unsigned int, clusters, buffer->len); 1.143 + 1.144 + /* XXX Use UTF-16 decoder! */ 1.145 + for (unsigned int i = 0; i < buffer->len; i++) { 1.146 + chars[i] = buffer->info[i].codepoint; 1.147 + clusters[i] = buffer->info[i].cluster; 1.148 + } 1.149 + 1.150 + unsigned int glyph_count = le_layoutChars (le, 1.151 + chars, 1.152 + 0, 1.153 + buffer->len, 1.154 + buffer->len, 1.155 + HB_DIRECTION_IS_BACKWARD (buffer->props.direction), 1.156 + 0., 0., 1.157 + &status); 1.158 + if (status != LE_NO_ERROR) 1.159 + { le_close (le); return false; } 1.160 + 1.161 + unsigned int num_glyphs = scratch_size / (sizeof (LEGlyphID) + 1.162 + sizeof (le_int32) + 1.163 + sizeof (float) * 2); 1.164 + 1.165 + if (unlikely (glyph_count >= num_glyphs || glyph_count > buffer->allocated)) { 1.166 + buffer->ensure (buffer->allocated * 2); 1.167 + if (buffer->in_error) 1.168 + { le_close (le); return false; } 1.169 + goto retry; 1.170 + } 1.171 + 1.172 + ALLOCATE_ARRAY (LEGlyphID, glyphs, glyph_count); 1.173 + ALLOCATE_ARRAY (le_int32, indices, glyph_count); 1.174 + ALLOCATE_ARRAY (float, positions, glyph_count * 2 + 2); 1.175 + 1.176 + le_getGlyphs (le, glyphs, &status); 1.177 + le_getCharIndices (le, indices, &status); 1.178 + le_getGlyphPositions (le, positions, &status); 1.179 + 1.180 +#undef ALLOCATE_ARRAY 1.181 + 1.182 + /* Ok, we've got everything we need, now compose output buffer, 1.183 + * very, *very*, carefully! */ 1.184 + 1.185 + unsigned int j = 0; 1.186 + hb_glyph_info_t *info = buffer->info; 1.187 + for (unsigned int i = 0; i < glyph_count; i++) 1.188 + { 1.189 + if (glyphs[i] >= 0xFFFE) 1.190 + continue; 1.191 + 1.192 + info[j].codepoint = glyphs[i]; 1.193 + info[j].cluster = clusters[indices[i]]; 1.194 + 1.195 + /* icu-le doesn't seem to have separate advance values. */ 1.196 + info[j].mask = positions[2 * i + 2] - positions[2 * i]; 1.197 + info[j].var1.u32 = 0; 1.198 + info[j].var2.u32 = -positions[2 * i + 1]; 1.199 + 1.200 + j++; 1.201 + } 1.202 + buffer->len = j; 1.203 + 1.204 + buffer->clear_positions (); 1.205 + 1.206 + for (unsigned int i = 0; i < buffer->len; i++) { 1.207 + hb_glyph_info_t *info = &buffer->info[i]; 1.208 + hb_glyph_position_t *pos = &buffer->pos[i]; 1.209 + 1.210 + /* TODO vertical */ 1.211 + pos->x_advance = info->mask; 1.212 + pos->x_offset = info->var1.u32; 1.213 + pos->y_offset = info->var2.u32; 1.214 + } 1.215 + 1.216 + le_close (le); 1.217 + return true; 1.218 +}