1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/harfbuzz/src/hb-old.cc Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,410 @@ 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 old 1.31 +#define hb_old_shaper_face_data_t HB_FaceRec_ 1.32 +#define hb_old_shaper_font_data_t HB_Font_ 1.33 +#include "hb-shaper-impl-private.hh" 1.34 + 1.35 +#include <harfbuzz.h> 1.36 + 1.37 + 1.38 +#ifndef HB_DEBUG_OLD 1.39 +#define HB_DEBUG_OLD (HB_DEBUG+0) 1.40 +#endif 1.41 + 1.42 + 1.43 +static HB_Script 1.44 +hb_old_script_from_script (hb_script_t script) 1.45 +{ 1.46 + switch ((hb_tag_t) script) 1.47 + { 1.48 + default: 1.49 + case HB_SCRIPT_COMMON: return HB_Script_Common; 1.50 + case HB_SCRIPT_GREEK: return HB_Script_Greek; 1.51 + case HB_SCRIPT_CYRILLIC: return HB_Script_Cyrillic; 1.52 + case HB_SCRIPT_ARMENIAN: return HB_Script_Armenian; 1.53 + case HB_SCRIPT_HEBREW: return HB_Script_Hebrew; 1.54 + case HB_SCRIPT_ARABIC: return HB_Script_Arabic; 1.55 + case HB_SCRIPT_SYRIAC: return HB_Script_Syriac; 1.56 + case HB_SCRIPT_THAANA: return HB_Script_Thaana; 1.57 + case HB_SCRIPT_DEVANAGARI: return HB_Script_Devanagari; 1.58 + case HB_SCRIPT_BENGALI: return HB_Script_Bengali; 1.59 + case HB_SCRIPT_GURMUKHI: return HB_Script_Gurmukhi; 1.60 + case HB_SCRIPT_GUJARATI: return HB_Script_Gujarati; 1.61 + case HB_SCRIPT_ORIYA: return HB_Script_Oriya; 1.62 + case HB_SCRIPT_TAMIL: return HB_Script_Tamil; 1.63 + case HB_SCRIPT_TELUGU: return HB_Script_Telugu; 1.64 + case HB_SCRIPT_KANNADA: return HB_Script_Kannada; 1.65 + case HB_SCRIPT_MALAYALAM: return HB_Script_Malayalam; 1.66 + case HB_SCRIPT_SINHALA: return HB_Script_Sinhala; 1.67 + case HB_SCRIPT_THAI: return HB_Script_Thai; 1.68 + case HB_SCRIPT_LAO: return HB_Script_Lao; 1.69 + case HB_SCRIPT_TIBETAN: return HB_Script_Tibetan; 1.70 + case HB_SCRIPT_MYANMAR: return HB_Script_Myanmar; 1.71 + case HB_SCRIPT_GEORGIAN: return HB_Script_Georgian; 1.72 + case HB_SCRIPT_HANGUL: return HB_Script_Hangul; 1.73 + case HB_SCRIPT_OGHAM: return HB_Script_Ogham; 1.74 + case HB_SCRIPT_RUNIC: return HB_Script_Runic; 1.75 + case HB_SCRIPT_KHMER: return HB_Script_Khmer; 1.76 + case HB_SCRIPT_NKO: return HB_Script_Nko; 1.77 + case HB_SCRIPT_INHERITED: return HB_Script_Inherited; 1.78 + } 1.79 +} 1.80 + 1.81 + 1.82 +static HB_Bool 1.83 +hb_old_convertStringToGlyphIndices (HB_Font old_font, 1.84 + const HB_UChar16 *string, 1.85 + hb_uint32 length, 1.86 + HB_Glyph *glyphs, 1.87 + hb_uint32 *numGlyphs, 1.88 + HB_Bool rightToLeft) 1.89 +{ 1.90 + hb_font_t *font = (hb_font_t *) old_font->userData; 1.91 + 1.92 + for (unsigned int i = 0; i < length; i++) 1.93 + { 1.94 + hb_codepoint_t u; 1.95 + 1.96 + /* XXX Handle UTF-16. Ugh */ 1.97 + u = string[i]; 1.98 + 1.99 + if (rightToLeft) 1.100 + u = hb_unicode_funcs_get_default ()->mirroring (u); 1.101 + 1.102 + font->get_glyph (u, 0, &u); /* TODO Variation selectors */ 1.103 + 1.104 + glyphs[i] = u; 1.105 + } 1.106 + *numGlyphs = length; /* XXX */ 1.107 + 1.108 + return true; 1.109 +} 1.110 + 1.111 +static void 1.112 +hb_old_getGlyphAdvances (HB_Font old_font, 1.113 + const HB_Glyph *glyphs, 1.114 + hb_uint32 numGlyphs, 1.115 + HB_Fixed *advances, 1.116 + int flags /*HB_ShaperFlag*/ HB_UNUSED) 1.117 +{ 1.118 + hb_font_t *font = (hb_font_t *) old_font->userData; 1.119 + 1.120 + for (unsigned int i = 0; i < numGlyphs; i++) 1.121 + advances[i] = font->get_glyph_h_advance (glyphs[i]); 1.122 +} 1.123 + 1.124 +static HB_Bool 1.125 +hb_old_canRender (HB_Font old_font, 1.126 + const HB_UChar16 *string, 1.127 + hb_uint32 length) 1.128 +{ 1.129 + return true; /* TODO */ 1.130 +} 1.131 + 1.132 +static HB_Error 1.133 +hb_old_getPointInOutline (HB_Font old_font, 1.134 + HB_Glyph glyph, 1.135 + int flags /*HB_ShaperFlag*/, 1.136 + hb_uint32 point, 1.137 + HB_Fixed *xpos, 1.138 + HB_Fixed *ypos, 1.139 + hb_uint32 *nPoints) 1.140 +{ 1.141 + return HB_Err_Ok; /* TODO */ 1.142 +} 1.143 + 1.144 +static void 1.145 +hb_old_getGlyphMetrics (HB_Font old_font, 1.146 + HB_Glyph glyph, 1.147 + HB_GlyphMetrics *metrics) 1.148 +{ 1.149 + hb_font_t *font = (hb_font_t *) old_font->userData; 1.150 + 1.151 + hb_glyph_extents_t extents; 1.152 + 1.153 + font->get_glyph_extents (glyph, &extents); 1.154 + 1.155 + metrics->x = extents.x_bearing; 1.156 + metrics->y = extents.y_bearing; 1.157 + metrics->width = extents.width; 1.158 + metrics->height = extents.height; 1.159 + metrics->xOffset = font->get_glyph_h_advance (glyph); 1.160 + metrics->yOffset = 0; 1.161 +} 1.162 + 1.163 +static HB_Fixed 1.164 +hb_old_getFontMetric (HB_Font old_font, 1.165 + HB_FontMetric metric) 1.166 +{ 1.167 + hb_font_t *font = (hb_font_t *) old_font->userData; 1.168 + 1.169 + switch (metric) 1.170 + { 1.171 + case HB_FontAscent: 1.172 + return font->y_scale; /* XXX We don't have ascent data yet. */ 1.173 + 1.174 + default: 1.175 + return 0; 1.176 + } 1.177 +} 1.178 + 1.179 +static const HB_FontClass hb_old_font_class = { 1.180 + hb_old_convertStringToGlyphIndices, 1.181 + hb_old_getGlyphAdvances, 1.182 + hb_old_canRender, 1.183 + hb_old_getPointInOutline, 1.184 + hb_old_getGlyphMetrics, 1.185 + hb_old_getFontMetric 1.186 +}; 1.187 + 1.188 + 1.189 + 1.190 +static HB_Error 1.191 +table_func (void *font, HB_Tag tag, HB_Byte *buffer, HB_UInt *length) 1.192 +{ 1.193 + hb_face_t *face = (hb_face_t *) font; 1.194 + hb_blob_t *blob = face->reference_table ((hb_tag_t) tag); 1.195 + unsigned int capacity = *length; 1.196 + *length = hb_blob_get_length (blob); 1.197 + memcpy (buffer, hb_blob_get_data (blob, NULL), MIN (capacity, *length)); 1.198 + hb_blob_destroy (blob); 1.199 + return HB_Err_Ok; 1.200 +} 1.201 + 1.202 + 1.203 +/* 1.204 + * shaper face data 1.205 + */ 1.206 + 1.207 +hb_old_shaper_face_data_t * 1.208 +_hb_old_shaper_face_data_create (hb_face_t *face) 1.209 +{ 1.210 + return HB_NewFace (face, table_func); 1.211 +} 1.212 + 1.213 +void 1.214 +_hb_old_shaper_face_data_destroy (hb_old_shaper_face_data_t *data) 1.215 +{ 1.216 + HB_FreeFace (data); 1.217 +} 1.218 + 1.219 + 1.220 +/* 1.221 + * shaper font data 1.222 + */ 1.223 + 1.224 +hb_old_shaper_font_data_t * 1.225 +_hb_old_shaper_font_data_create (hb_font_t *font) 1.226 +{ 1.227 + HB_FontRec *data = (HB_FontRec *) calloc (1, sizeof (HB_FontRec)); 1.228 + if (unlikely (!data)) { 1.229 + DEBUG_MSG (OLD, font, "malloc()ing HB_Font failed"); 1.230 + return NULL; 1.231 + } 1.232 + 1.233 + data->klass = &hb_old_font_class; 1.234 + data->x_ppem = font->x_ppem; 1.235 + data->y_ppem = font->y_ppem; 1.236 + data->x_scale = font->x_scale; /* XXX */ 1.237 + data->y_scale = font->y_scale; /* XXX */ 1.238 + data->userData = font; 1.239 + 1.240 + return data; 1.241 +} 1.242 + 1.243 +void 1.244 +_hb_old_shaper_font_data_destroy (hb_old_shaper_font_data_t *data) 1.245 +{ 1.246 + free (data); 1.247 +} 1.248 + 1.249 + 1.250 +/* 1.251 + * shaper shape_plan data 1.252 + */ 1.253 + 1.254 +struct hb_old_shaper_shape_plan_data_t {}; 1.255 + 1.256 +hb_old_shaper_shape_plan_data_t * 1.257 +_hb_old_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED, 1.258 + const hb_feature_t *user_features HB_UNUSED, 1.259 + unsigned int num_user_features HB_UNUSED) 1.260 +{ 1.261 + return (hb_old_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED; 1.262 +} 1.263 + 1.264 +void 1.265 +_hb_old_shaper_shape_plan_data_destroy (hb_old_shaper_shape_plan_data_t *data HB_UNUSED) 1.266 +{ 1.267 +} 1.268 + 1.269 + 1.270 +/* 1.271 + * shaper 1.272 + */ 1.273 + 1.274 +hb_bool_t 1.275 +_hb_old_shape (hb_shape_plan_t *shape_plan HB_UNUSED, 1.276 + hb_font_t *font, 1.277 + hb_buffer_t *buffer, 1.278 + const hb_feature_t *features, 1.279 + unsigned int num_features) 1.280 +{ 1.281 + hb_face_t *face = font->face; 1.282 + HB_Face old_face = HB_SHAPER_DATA_GET (face); 1.283 + HB_Font old_font = HB_SHAPER_DATA_GET (font); 1.284 + 1.285 + bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction); 1.286 + 1.287 +retry: 1.288 + 1.289 + unsigned int scratch_size; 1.290 + char *scratch = (char *) buffer->get_scratch_buffer (&scratch_size); 1.291 + 1.292 +#define utf16_index() var1.u32 1.293 + HB_UChar16 *pchars = (HB_UChar16 *) scratch; 1.294 + unsigned int chars_len = 0; 1.295 + for (unsigned int i = 0; i < buffer->len; i++) { 1.296 + hb_codepoint_t c = buffer->info[i].codepoint; 1.297 + buffer->info[i].utf16_index() = chars_len; 1.298 + if (likely (c < 0x10000)) 1.299 + pchars[chars_len++] = c; 1.300 + else if (unlikely (c >= 0x110000)) 1.301 + pchars[chars_len++] = 0xFFFD; 1.302 + else { 1.303 + pchars[chars_len++] = 0xD800 + ((c - 0x10000) >> 10); 1.304 + pchars[chars_len++] = 0xDC00 + ((c - 0x10000) & ((1 << 10) - 1)); 1.305 + } 1.306 + } 1.307 + 1.308 + 1.309 +#define ALLOCATE_ARRAY(Type, name, len) \ 1.310 + name = (Type *) scratch; \ 1.311 + scratch += (len) * sizeof ((name)[0]); \ 1.312 + scratch_size -= (len) * sizeof ((name)[0]); 1.313 + 1.314 + 1.315 + HB_ShaperItem item = {0}; 1.316 + 1.317 + ALLOCATE_ARRAY (const HB_UChar16, item.string, chars_len); 1.318 + ALLOCATE_ARRAY (unsigned short, item.log_clusters, chars_len + 2); 1.319 + item.stringLength = chars_len; 1.320 + item.item.pos = 0; 1.321 + item.item.length = item.stringLength; 1.322 + item.item.script = hb_old_script_from_script (buffer->props.script); 1.323 + item.item.bidiLevel = backward ? 1 : 0; 1.324 + 1.325 + item.font = old_font; 1.326 + item.face = old_face; 1.327 + item.shaperFlags = 0; 1.328 + 1.329 + item.glyphIndicesPresent = false; 1.330 + 1.331 + /* TODO Alignment. */ 1.332 + unsigned int num_glyphs = scratch_size / (sizeof (HB_Glyph) + 1.333 + sizeof (HB_GlyphAttributes) + 1.334 + sizeof (HB_Fixed) + 1.335 + sizeof (HB_FixedPoint) + 1.336 + sizeof (uint32_t)); 1.337 + 1.338 + item.num_glyphs = num_glyphs; 1.339 + ALLOCATE_ARRAY (HB_Glyph, item.glyphs, num_glyphs); 1.340 + ALLOCATE_ARRAY (HB_GlyphAttributes, item.attributes, num_glyphs); 1.341 + ALLOCATE_ARRAY (HB_Fixed, item.advances, num_glyphs); 1.342 + ALLOCATE_ARRAY (HB_FixedPoint, item.offsets, num_glyphs); 1.343 + /* Apparently in some cases the offsets array will not be fully assigned to. 1.344 + * Clear it. */ 1.345 + memset (item.offsets, 0, num_glyphs * sizeof (item.offsets[0])); 1.346 + uint32_t *vis_clusters; 1.347 + ALLOCATE_ARRAY (uint32_t, vis_clusters, num_glyphs); 1.348 + 1.349 +#undef ALLOCATE_ARRAY 1.350 + 1.351 + if (!HB_ShapeItem (&item)) 1.352 + { 1.353 + if (unlikely (item.num_glyphs > num_glyphs)) 1.354 + { 1.355 + buffer->ensure (buffer->allocated * 2); 1.356 + if (buffer->in_error) 1.357 + return false; 1.358 + goto retry; 1.359 + } 1.360 + return false; 1.361 + } 1.362 + num_glyphs = item.num_glyphs; 1.363 + 1.364 + /* Ok, we've got everything we need, now compose output buffer, 1.365 + * very, *very*, carefully! */ 1.366 + 1.367 + /* Calculate visual-clusters. That's what we ship. */ 1.368 + for (unsigned int i = 0; i < num_glyphs; i++) 1.369 + vis_clusters[i] = -1; 1.370 + for (unsigned int i = 0; i < buffer->len; i++) { 1.371 + uint32_t *p = &vis_clusters[item.log_clusters[buffer->info[i].utf16_index()]]; 1.372 + *p = MIN (*p, buffer->info[i].cluster); 1.373 + } 1.374 + for (unsigned int i = 1; i < num_glyphs; i++) 1.375 + if (vis_clusters[i] == (uint32_t) -1) 1.376 + vis_clusters[i] = vis_clusters[i - 1]; 1.377 + 1.378 +#undef utf16_index 1.379 + 1.380 + buffer->ensure (num_glyphs); 1.381 + if (buffer->in_error) 1.382 + return false; 1.383 + 1.384 + 1.385 + buffer->len = num_glyphs; 1.386 + hb_glyph_info_t *info = buffer->info; 1.387 + for (unsigned int i = 0; i < num_glyphs; i++) 1.388 + { 1.389 + info[i].codepoint = item.glyphs[i]; 1.390 + info[i].cluster = vis_clusters[i]; 1.391 + 1.392 + info[i].mask = item.advances[i]; 1.393 + info[i].var1.u32 = item.offsets[i].x; 1.394 + info[i].var2.u32 = item.offsets[i].y; 1.395 + } 1.396 + 1.397 + buffer->clear_positions (); 1.398 + 1.399 + for (unsigned int i = 0; i < num_glyphs; ++i) { 1.400 + hb_glyph_info_t *info = &buffer->info[i]; 1.401 + hb_glyph_position_t *pos = &buffer->pos[i]; 1.402 + 1.403 + /* TODO vertical */ 1.404 + pos->x_advance = info->mask; 1.405 + pos->x_offset = info->var1.u32; 1.406 + pos->y_offset = info->var2.u32; 1.407 + } 1.408 + 1.409 + if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction)) 1.410 + buffer->reverse (); 1.411 + 1.412 + return true; 1.413 +}