gfx/harfbuzz/src/hb-icu-le.cc

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /*
     2  * Copyright © 2012  Google, Inc.
     3  *
     4  *  This is part of HarfBuzz, a text shaping library.
     5  *
     6  * Permission is hereby granted, without written agreement and without
     7  * license or royalty fees, to use, copy, modify, and distribute this
     8  * software and its documentation for any purpose, provided that the
     9  * above copyright notice and the following two paragraphs appear in
    10  * all copies of this software.
    11  *
    12  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
    13  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
    14  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
    15  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
    16  * DAMAGE.
    17  *
    18  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
    19  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
    20  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
    21  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
    22  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
    23  *
    24  * Google Author(s): Behdad Esfahbod
    25  */
    27 #define HB_SHAPER icu_le
    28 #define hb_icu_le_shaper_font_data_t PortableFontInstance
    29 #include "hb-shaper-impl-private.hh"
    31 #include "hb-icu-le/PortableFontInstance.h"
    33 #include "layout/loengine.h"
    34 #include "unicode/unistr.h"
    36 #include "hb-icu.h"
    39 /*
    40  * shaper face data
    41  */
    43 struct hb_icu_le_shaper_face_data_t {};
    45 hb_icu_le_shaper_face_data_t *
    46 _hb_icu_le_shaper_face_data_create (hb_face_t *face HB_UNUSED)
    47 {
    48   return (hb_icu_le_shaper_face_data_t *) HB_SHAPER_DATA_SUCCEEDED;
    49 }
    51 void
    52 _hb_icu_le_shaper_face_data_destroy (hb_icu_le_shaper_face_data_t *data HB_UNUSED)
    53 {
    54 }
    57 /*
    58  * shaper font data
    59  */
    61 hb_icu_le_shaper_font_data_t *
    62 _hb_icu_le_shaper_font_data_create (hb_font_t *font)
    63 {
    64   LEErrorCode status = LE_NO_ERROR;
    65   hb_icu_le_shaper_font_data_t *data = new PortableFontInstance (font->face,
    66 								 font->x_scale,
    67 								 font->y_scale,
    68 								 status);
    69   if (status != LE_NO_ERROR) {
    70     delete (data);
    71     return NULL;
    72   }
    74   return data;
    75 }
    77 void
    78 _hb_icu_le_shaper_font_data_destroy (hb_icu_le_shaper_font_data_t *data)
    79 {
    80   delete (data);
    81 }
    84 /*
    85  * shaper shape_plan data
    86  */
    88 struct hb_icu_le_shaper_shape_plan_data_t {};
    90 hb_icu_le_shaper_shape_plan_data_t *
    91 _hb_icu_le_shaper_shape_plan_data_create (hb_shape_plan_t    *shape_plan HB_UNUSED,
    92 					  const hb_feature_t *user_features,
    93 					  unsigned int        num_user_features)
    94 {
    95   return (hb_icu_le_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
    96 }
    98 void
    99 _hb_icu_le_shaper_shape_plan_data_destroy (hb_icu_le_shaper_shape_plan_data_t *data)
   100 {
   101 }
   104 /*
   105  * shaper
   106  */
   108 hb_bool_t
   109 _hb_icu_le_shape (hb_shape_plan_t    *shape_plan,
   110 		  hb_font_t          *font,
   111 		  hb_buffer_t        *buffer,
   112 		  const hb_feature_t *features,
   113 		  unsigned int        num_features)
   114 {
   115   LEFontInstance *font_instance = HB_SHAPER_DATA_GET (font);
   116   le_int32 script_code = hb_icu_script_from_script (shape_plan->props.script);
   117   le_int32 language_code = -1 /* TODO */;
   118   le_int32 typography_flags = 3; /* Needed for ligatures and kerning */
   119   LEErrorCode status = LE_NO_ERROR;
   120   le_engine *le = le_create ((const le_font *) font_instance,
   121 			     script_code,
   122 			     language_code,
   123 			     typography_flags,
   124 			     &status);
   125   if (status != LE_NO_ERROR)
   126   { le_close (le); return false; }
   128 retry:
   130   unsigned int scratch_size;
   131   char *scratch = (char *) buffer->get_scratch_buffer (&scratch_size);
   133 #define ALLOCATE_ARRAY(Type, name, len) \
   134   Type *name = (Type *) scratch; \
   135   scratch += (len) * sizeof ((name)[0]); \
   136   scratch_size -= (len) * sizeof ((name)[0]);
   138   ALLOCATE_ARRAY (LEUnicode, chars, buffer->len);
   139   ALLOCATE_ARRAY (unsigned int, clusters, buffer->len);
   141   /* XXX Use UTF-16 decoder! */
   142   for (unsigned int i = 0; i < buffer->len; i++) {
   143     chars[i] = buffer->info[i].codepoint;
   144     clusters[i] = buffer->info[i].cluster;
   145   }
   147   unsigned int glyph_count = le_layoutChars (le,
   148 					     chars,
   149 					     0,
   150 					     buffer->len,
   151 					     buffer->len,
   152 					     HB_DIRECTION_IS_BACKWARD (buffer->props.direction),
   153 					     0., 0.,
   154 					     &status);
   155   if (status != LE_NO_ERROR)
   156   { le_close (le); return false; }
   158   unsigned int num_glyphs = scratch_size / (sizeof (LEGlyphID) +
   159 					    sizeof (le_int32) +
   160 					    sizeof (float) * 2);
   162   if (unlikely (glyph_count >= num_glyphs || glyph_count > buffer->allocated)) {
   163     buffer->ensure (buffer->allocated * 2);
   164     if (buffer->in_error)
   165     { le_close (le); return false; }
   166     goto retry;
   167   }
   169   ALLOCATE_ARRAY (LEGlyphID, glyphs, glyph_count);
   170   ALLOCATE_ARRAY (le_int32, indices, glyph_count);
   171   ALLOCATE_ARRAY (float, positions, glyph_count * 2 + 2);
   173   le_getGlyphs (le, glyphs, &status);
   174   le_getCharIndices (le, indices, &status);
   175   le_getGlyphPositions (le, positions, &status);
   177 #undef ALLOCATE_ARRAY
   179   /* Ok, we've got everything we need, now compose output buffer,
   180    * very, *very*, carefully! */
   182   unsigned int j = 0;
   183   hb_glyph_info_t *info = buffer->info;
   184   for (unsigned int i = 0; i < glyph_count; i++)
   185   {
   186     if (glyphs[i] >= 0xFFFE)
   187 	continue;
   189     info[j].codepoint = glyphs[i];
   190     info[j].cluster = clusters[indices[i]];
   192     /* icu-le doesn't seem to have separate advance values. */
   193     info[j].mask = positions[2 * i + 2] - positions[2 * i];
   194     info[j].var1.u32 = 0;
   195     info[j].var2.u32 = -positions[2 * i + 1];
   197     j++;
   198   }
   199   buffer->len = j;
   201   buffer->clear_positions ();
   203   for (unsigned int i = 0; i < buffer->len; i++) {
   204     hb_glyph_info_t *info = &buffer->info[i];
   205     hb_glyph_position_t *pos = &buffer->pos[i];
   207     /* TODO vertical */
   208     pos->x_advance = info->mask;
   209     pos->x_offset = info->var1.u32;
   210     pos->y_offset = info->var2.u32;
   211   }
   213   le_close (le);
   214   return true;
   215 }

mercurial