gfx/harfbuzz/src/hb-graphite2.cc

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 /*
     2  * Copyright © 2011  Martin Hosken
     3  * Copyright © 2011  SIL International
     4  * Copyright © 2011,2012  Google, Inc.
     5  *
     6  *  This is part of HarfBuzz, a text shaping library.
     7  *
     8  * Permission is hereby granted, without written agreement and without
     9  * license or royalty fees, to use, copy, modify, and distribute this
    10  * software and its documentation for any purpose, provided that the
    11  * above copyright notice and the following two paragraphs appear in
    12  * all copies of this software.
    13  *
    14  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
    15  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
    16  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
    17  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
    18  * DAMAGE.
    19  *
    20  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
    21  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
    22  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
    23  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
    24  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
    25  *
    26  * Google Author(s): Behdad Esfahbod
    27  */
    29 #define HB_SHAPER graphite2
    30 #define hb_graphite2_shaper_font_data_t gr_font
    31 #include "hb-shaper-impl-private.hh"
    33 #include "hb-graphite2.h"
    35 #include <graphite2/Segment.h>
    38 HB_SHAPER_DATA_ENSURE_DECLARE(graphite2, face)
    39 HB_SHAPER_DATA_ENSURE_DECLARE(graphite2, font)
    42 /*
    43  * shaper face data
    44  */
    46 typedef struct hb_graphite2_tablelist_t {
    47   struct hb_graphite2_tablelist_t *next;
    48   hb_blob_t *blob;
    49   unsigned int tag;
    50 } hb_graphite2_tablelist_t;
    52 struct hb_graphite2_shaper_face_data_t {
    53   hb_face_t *face;
    54   gr_face   *grface;
    55   hb_graphite2_tablelist_t *tlist;
    56 };
    58 static const void *hb_graphite2_get_table (const void *data, unsigned int tag, size_t *len)
    59 {
    60   hb_graphite2_shaper_face_data_t *face_data = (hb_graphite2_shaper_face_data_t *) data;
    61   hb_graphite2_tablelist_t *tlist = face_data->tlist;
    63   hb_blob_t *blob = NULL;
    65   for (hb_graphite2_tablelist_t *p = tlist; p; p = p->next)
    66     if (p->tag == tag) {
    67       blob = p->blob;
    68       break;
    69     }
    71   if (unlikely (!blob))
    72   {
    73     blob = face_data->face->reference_table (tag);
    75     hb_graphite2_tablelist_t *p = (hb_graphite2_tablelist_t *) calloc (1, sizeof (hb_graphite2_tablelist_t));
    76     if (unlikely (!p)) {
    77       hb_blob_destroy (blob);
    78       return NULL;
    79     }
    80     p->blob = blob;
    81     p->tag = tag;
    83     /* TODO Not thread-safe, but fairly harmless.
    84      * We can do the double-chcked pointer cmpexch thing here. */
    85     p->next = face_data->tlist;
    86     face_data->tlist = p;
    87   }
    89   unsigned int tlen;
    90   const char *d = hb_blob_get_data (blob, &tlen);
    91   *len = tlen;
    92   return d;
    93 }
    95 hb_graphite2_shaper_face_data_t *
    96 _hb_graphite2_shaper_face_data_create (hb_face_t *face)
    97 {
    98   hb_blob_t *silf_blob = face->reference_table (HB_GRAPHITE2_TAG_SILF);
    99   /* Umm, we just reference the table to check whether it exists.
   100    * Maybe add better API for this? */
   101   if (!hb_blob_get_length (silf_blob))
   102   {
   103     hb_blob_destroy (silf_blob);
   104     return NULL;
   105   }
   106   hb_blob_destroy (silf_blob);
   108   hb_graphite2_shaper_face_data_t *data = (hb_graphite2_shaper_face_data_t *) calloc (1, sizeof (hb_graphite2_shaper_face_data_t));
   109   if (unlikely (!data))
   110     return NULL;
   112   data->face = face;
   113   data->grface = gr_make_face (data, &hb_graphite2_get_table, gr_face_preloadAll);
   115   if (unlikely (!data->grface)) {
   116     free (data);
   117     return NULL;
   118   }
   120   return data;
   121 }
   123 void
   124 _hb_graphite2_shaper_face_data_destroy (hb_graphite2_shaper_face_data_t *data)
   125 {
   126   hb_graphite2_tablelist_t *tlist = data->tlist;
   128   while (tlist)
   129   {
   130     hb_graphite2_tablelist_t *old = tlist;
   131     hb_blob_destroy (tlist->blob);
   132     tlist = tlist->next;
   133     free (old);
   134   }
   136   gr_face_destroy (data->grface);
   138   free (data);
   139 }
   141 gr_face *
   142 hb_graphite2_face_get_gr_face (hb_face_t *face)
   143 {
   144   if (unlikely (!hb_graphite2_shaper_face_data_ensure (face))) return NULL;
   145   return HB_SHAPER_DATA_GET (face)->grface;
   146 }
   149 /*
   150  * shaper font data
   151  */
   153 static float hb_graphite2_get_advance (const void *hb_font, unsigned short gid)
   154 {
   155   return ((hb_font_t *) hb_font)->get_glyph_h_advance (gid);
   156 }
   158 hb_graphite2_shaper_font_data_t *
   159 _hb_graphite2_shaper_font_data_create (hb_font_t *font)
   160 {
   161   if (unlikely (!hb_graphite2_shaper_face_data_ensure (font->face))) return NULL;
   163   hb_face_t *face = font->face;
   164   hb_graphite2_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
   166   return gr_make_font_with_advance_fn (font->x_scale, font, &hb_graphite2_get_advance, face_data->grface);
   167 }
   169 void
   170 _hb_graphite2_shaper_font_data_destroy (hb_graphite2_shaper_font_data_t *data)
   171 {
   172   gr_font_destroy (data);
   173 }
   175 gr_font *
   176 hb_graphite2_font_get_gr_font (hb_font_t *font)
   177 {
   178   if (unlikely (!hb_graphite2_shaper_font_data_ensure (font))) return NULL;
   179   return HB_SHAPER_DATA_GET (font);
   180 }
   183 /*
   184  * shaper shape_plan data
   185  */
   187 struct hb_graphite2_shaper_shape_plan_data_t {};
   189 hb_graphite2_shaper_shape_plan_data_t *
   190 _hb_graphite2_shaper_shape_plan_data_create (hb_shape_plan_t    *shape_plan HB_UNUSED,
   191 					     const hb_feature_t *user_features HB_UNUSED,
   192 					     unsigned int        num_user_features HB_UNUSED)
   193 {
   194   return (hb_graphite2_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
   195 }
   197 void
   198 _hb_graphite2_shaper_shape_plan_data_destroy (hb_graphite2_shaper_shape_plan_data_t *data HB_UNUSED)
   199 {
   200 }
   203 /*
   204  * shaper
   205  */
   207 struct hb_graphite2_cluster_t {
   208   unsigned int base_char;
   209   unsigned int num_chars;
   210   unsigned int base_glyph;
   211   unsigned int num_glyphs;
   212 };
   214 hb_bool_t
   215 _hb_graphite2_shape (hb_shape_plan_t    *shape_plan,
   216 		     hb_font_t          *font,
   217 		     hb_buffer_t        *buffer,
   218 		     const hb_feature_t *features,
   219 		     unsigned int        num_features)
   220 {
   221   hb_face_t *face = font->face;
   222   gr_face *grface = HB_SHAPER_DATA_GET (face)->grface;
   223   gr_font *grfont = HB_SHAPER_DATA_GET (font);
   225   const char *lang = hb_language_to_string (hb_buffer_get_language (buffer));
   226   const char *lang_end = lang ? strchr (lang, '-') : NULL;
   227   int lang_len = lang_end ? lang_end - lang : -1;
   228   gr_feature_val *feats = gr_face_featureval_for_lang (grface, lang ? hb_tag_from_string (lang, lang_len) : 0);
   230   while (num_features--)
   231   {
   232     const gr_feature_ref *fref = gr_face_find_fref (grface, features->tag);
   233     if (fref)
   234       gr_fref_set_feature_value (fref, features->value, feats);
   235     features++;
   236   }
   238   gr_segment *seg = NULL;
   239   const gr_slot *is;
   240   unsigned int ci = 0, ic = 0;
   241   float curradvx = 0., curradvy = 0.;
   243   unsigned int scratch_size;
   244   hb_buffer_t::scratch_buffer_t *scratch = buffer->get_scratch_buffer (&scratch_size);
   246   uint32_t *chars = (uint32_t *) scratch;
   248   for (unsigned int i = 0; i < buffer->len; ++i)
   249     chars[i] = buffer->info[i].codepoint;
   251   hb_tag_t script_tag[2];
   252   hb_ot_tags_from_script (hb_buffer_get_script (buffer), &script_tag[0], &script_tag[1]);
   254   seg = gr_make_seg (grfont, grface,
   255 		     script_tag[1] == HB_TAG_NONE ? script_tag[0] : script_tag[1],
   256 		     feats,
   257 		     gr_utf32, chars, buffer->len,
   258 		     2 | (hb_buffer_get_direction (buffer) == HB_DIRECTION_RTL ? 1 : 0));
   260   if (unlikely (!seg)) {
   261     if (feats) gr_featureval_destroy (feats);
   262     return false;
   263   }
   265   unsigned int glyph_count = gr_seg_n_slots (seg);
   266   if (unlikely (!glyph_count)) {
   267     if (feats) gr_featureval_destroy (feats);
   268     gr_seg_destroy (seg);
   269     return false;
   270   }
   272   scratch = buffer->get_scratch_buffer (&scratch_size);
   273   while ((DIV_CEIL (sizeof (hb_graphite2_cluster_t) * buffer->len, sizeof (*scratch)) +
   274 	  DIV_CEIL (sizeof (hb_codepoint_t) * glyph_count, sizeof (*scratch))) > scratch_size)
   275   {
   276     buffer->ensure (buffer->allocated * 2);
   277     if (unlikely (buffer->in_error)) {
   278       if (feats) gr_featureval_destroy (feats);
   279       gr_seg_destroy (seg);
   280       return false;
   281     }
   282     scratch = buffer->get_scratch_buffer (&scratch_size);
   283   }
   285 #define ALLOCATE_ARRAY(Type, name, len) \
   286   Type *name = (Type *) scratch; \
   287   { \
   288     unsigned int _consumed = DIV_CEIL ((len) * sizeof (Type), sizeof (*scratch)); \
   289     assert (_consumed <= scratch_size); \
   290     scratch += _consumed; \
   291     scratch_size -= _consumed; \
   292   }
   294   ALLOCATE_ARRAY (hb_graphite2_cluster_t, clusters, buffer->len);
   295   ALLOCATE_ARRAY (hb_codepoint_t, gids, glyph_count);
   297 #undef ALLOCATE_ARRAY
   299   memset (clusters, 0, sizeof (clusters[0]) * buffer->len);
   301   hb_codepoint_t *pg = gids;
   302   for (is = gr_seg_first_slot (seg), ic = 0; is; is = gr_slot_next_in_segment (is), ic++)
   303   {
   304     unsigned int before = gr_slot_before (is);
   305     unsigned int after = gr_slot_after (is);
   306     *pg = gr_slot_gid (is);
   307     pg++;
   308     while (clusters[ci].base_char > before && ci)
   309     {
   310       clusters[ci-1].num_chars += clusters[ci].num_chars;
   311       clusters[ci-1].num_glyphs += clusters[ci].num_glyphs;
   312       ci--;
   313     }
   315     if (gr_slot_can_insert_before (is) && clusters[ci].num_chars && before >= clusters[ci].base_char + clusters[ci].num_chars)
   316     {
   317       hb_graphite2_cluster_t *c = clusters + ci + 1;
   318       c->base_char = clusters[ci].base_char + clusters[ci].num_chars;
   319       c->num_chars = before - c->base_char;
   320       c->base_glyph = ic;
   321       c->num_glyphs = 0;
   322       ci++;
   323     }
   324     clusters[ci].num_glyphs++;
   326     if (clusters[ci].base_char + clusters[ci].num_chars < after + 1)
   327 	clusters[ci].num_chars = after + 1 - clusters[ci].base_char;
   328   }
   329   ci++;
   331   //buffer->clear_output ();
   332   for (unsigned int i = 0; i < ci; ++i)
   333   {
   334     for (unsigned int j = 0; j < clusters[i].num_glyphs; ++j)
   335     {
   336       hb_glyph_info_t *info = &buffer->info[clusters[i].base_glyph + j];
   337       info->codepoint = gids[clusters[i].base_glyph + j];
   338       info->cluster = gr_cinfo_base(gr_seg_cinfo(seg, clusters[i].base_char));
   339     }
   340   }
   341   buffer->len = glyph_count;
   342   //buffer->swap_buffers ();
   344   if (HB_DIRECTION_IS_BACKWARD(buffer->props.direction))
   345     curradvx = gr_seg_advance_X(seg);
   347   hb_glyph_position_t *pPos;
   348   for (pPos = hb_buffer_get_glyph_positions (buffer, NULL), is = gr_seg_first_slot (seg);
   349        is; pPos++, is = gr_slot_next_in_segment (is))
   350   {
   351     pPos->x_offset = gr_slot_origin_X (is) - curradvx;
   352     pPos->y_offset = gr_slot_origin_Y (is) - curradvy;
   353     pPos->x_advance = gr_slot_advance_X (is, grface, grfont);
   354     pPos->y_advance = gr_slot_advance_Y (is, grface, grfont);
   355     if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction))
   356       curradvx -= pPos->x_advance;
   357     pPos->x_offset = gr_slot_origin_X (is) - curradvx;
   358     if (!HB_DIRECTION_IS_BACKWARD (buffer->props.direction))
   359       curradvx += pPos->x_advance;
   360     pPos->y_offset = gr_slot_origin_Y (is) - curradvy;
   361     curradvy += pPos->y_advance;
   362   }
   363   if (!HB_DIRECTION_IS_BACKWARD (buffer->props.direction))
   364     pPos[-1].x_advance += gr_seg_advance_X(seg) - curradvx;
   366   if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction))
   367     hb_buffer_reverse_clusters (buffer);
   369   if (feats) gr_featureval_destroy (feats);
   370   gr_seg_destroy (seg);
   372   return true;
   373 }

mercurial