LCOV - code coverage report
Current view: top level - gfx/harfbuzz/src - hb-ot-shape-fallback.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 0 216 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 9 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright © 2011,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             :  */
      26             : 
      27             : #include "hb-ot-shape-fallback-private.hh"
      28             : #include "hb-ot-layout-gsubgpos-private.hh"
      29             : 
      30             : static unsigned int
      31           0 : recategorize_combining_class (hb_codepoint_t u,
      32             :                               unsigned int klass)
      33             : {
      34           0 :   if (klass >= 200)
      35           0 :     return klass;
      36             : 
      37             :   /* Thai / Lao need some per-character work. */
      38           0 :   if ((u & ~0xFF) == 0x0E00u)
      39             :   {
      40           0 :     if (unlikely (klass == 0))
      41             :     {
      42           0 :       switch (u)
      43             :       {
      44             :         case 0x0E31u:
      45             :         case 0x0E34u:
      46             :         case 0x0E35u:
      47             :         case 0x0E36u:
      48             :         case 0x0E37u:
      49             :         case 0x0E47u:
      50             :         case 0x0E4Cu:
      51             :         case 0x0E4Du:
      52             :         case 0x0E4Eu:
      53           0 :           klass = HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT;
      54           0 :           break;
      55             : 
      56             :         case 0x0EB1u:
      57             :         case 0x0EB4u:
      58             :         case 0x0EB5u:
      59             :         case 0x0EB6u:
      60             :         case 0x0EB7u:
      61             :         case 0x0EBBu:
      62             :         case 0x0ECCu:
      63             :         case 0x0ECDu:
      64           0 :           klass = HB_UNICODE_COMBINING_CLASS_ABOVE;
      65           0 :           break;
      66             : 
      67             :         case 0x0EBCu:
      68           0 :           klass = HB_UNICODE_COMBINING_CLASS_BELOW;
      69           0 :           break;
      70             :       }
      71             :     } else {
      72             :       /* Thai virama is below-right */
      73           0 :       if (u == 0x0E3Au)
      74           0 :         klass = HB_UNICODE_COMBINING_CLASS_BELOW_RIGHT;
      75             :     }
      76             :   }
      77             : 
      78           0 :   switch (klass)
      79             :   {
      80             : 
      81             :     /* Hebrew */
      82             : 
      83             :     case HB_MODIFIED_COMBINING_CLASS_CCC10: /* sheva */
      84             :     case HB_MODIFIED_COMBINING_CLASS_CCC11: /* hataf segol */
      85             :     case HB_MODIFIED_COMBINING_CLASS_CCC12: /* hataf patah */
      86             :     case HB_MODIFIED_COMBINING_CLASS_CCC13: /* hataf qamats */
      87             :     case HB_MODIFIED_COMBINING_CLASS_CCC14: /* hiriq */
      88             :     case HB_MODIFIED_COMBINING_CLASS_CCC15: /* tsere */
      89             :     case HB_MODIFIED_COMBINING_CLASS_CCC16: /* segol */
      90             :     case HB_MODIFIED_COMBINING_CLASS_CCC17: /* patah */
      91             :     case HB_MODIFIED_COMBINING_CLASS_CCC18: /* qamats */
      92             :     case HB_MODIFIED_COMBINING_CLASS_CCC20: /* qubuts */
      93             :     case HB_MODIFIED_COMBINING_CLASS_CCC22: /* meteg */
      94           0 :       return HB_UNICODE_COMBINING_CLASS_BELOW;
      95             : 
      96             :     case HB_MODIFIED_COMBINING_CLASS_CCC23: /* rafe */
      97           0 :       return HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE;
      98             : 
      99             :     case HB_MODIFIED_COMBINING_CLASS_CCC24: /* shin dot */
     100           0 :       return HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT;
     101             : 
     102             :     case HB_MODIFIED_COMBINING_CLASS_CCC25: /* sin dot */
     103             :     case HB_MODIFIED_COMBINING_CLASS_CCC19: /* holam */
     104           0 :       return HB_UNICODE_COMBINING_CLASS_ABOVE_LEFT;
     105             : 
     106             :     case HB_MODIFIED_COMBINING_CLASS_CCC26: /* point varika */
     107           0 :       return HB_UNICODE_COMBINING_CLASS_ABOVE;
     108             : 
     109             :     case HB_MODIFIED_COMBINING_CLASS_CCC21: /* dagesh */
     110           0 :       break;
     111             : 
     112             : 
     113             :     /* Arabic and Syriac */
     114             : 
     115             :     case HB_MODIFIED_COMBINING_CLASS_CCC27: /* fathatan */
     116             :     case HB_MODIFIED_COMBINING_CLASS_CCC28: /* dammatan */
     117             :     case HB_MODIFIED_COMBINING_CLASS_CCC30: /* fatha */
     118             :     case HB_MODIFIED_COMBINING_CLASS_CCC31: /* damma */
     119             :     case HB_MODIFIED_COMBINING_CLASS_CCC33: /* shadda */
     120             :     case HB_MODIFIED_COMBINING_CLASS_CCC34: /* sukun */
     121             :     case HB_MODIFIED_COMBINING_CLASS_CCC35: /* superscript alef */
     122             :     case HB_MODIFIED_COMBINING_CLASS_CCC36: /* superscript alaph */
     123           0 :       return HB_UNICODE_COMBINING_CLASS_ABOVE;
     124             : 
     125             :     case HB_MODIFIED_COMBINING_CLASS_CCC29: /* kasratan */
     126             :     case HB_MODIFIED_COMBINING_CLASS_CCC32: /* kasra */
     127           0 :       return HB_UNICODE_COMBINING_CLASS_BELOW;
     128             : 
     129             : 
     130             :     /* Thai */
     131             : 
     132             :     case HB_MODIFIED_COMBINING_CLASS_CCC103: /* sara u / sara uu */
     133           0 :       return HB_UNICODE_COMBINING_CLASS_BELOW_RIGHT;
     134             : 
     135             :     case HB_MODIFIED_COMBINING_CLASS_CCC107: /* mai */
     136           0 :       return HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT;
     137             : 
     138             : 
     139             :     /* Lao */
     140             : 
     141             :     case HB_MODIFIED_COMBINING_CLASS_CCC118: /* sign u / sign uu */
     142           0 :       return HB_UNICODE_COMBINING_CLASS_BELOW;
     143             : 
     144             :     case HB_MODIFIED_COMBINING_CLASS_CCC122: /* mai */
     145           0 :       return HB_UNICODE_COMBINING_CLASS_ABOVE;
     146             : 
     147             : 
     148             :     /* Tibetan */
     149             : 
     150             :     case HB_MODIFIED_COMBINING_CLASS_CCC129: /* sign aa */
     151           0 :       return HB_UNICODE_COMBINING_CLASS_BELOW;
     152             : 
     153             :     case HB_MODIFIED_COMBINING_CLASS_CCC130: /* sign i*/
     154           0 :       return HB_UNICODE_COMBINING_CLASS_ABOVE;
     155             : 
     156             :     case HB_MODIFIED_COMBINING_CLASS_CCC132: /* sign u */
     157           0 :       return HB_UNICODE_COMBINING_CLASS_BELOW;
     158             : 
     159             :   }
     160             : 
     161           0 :   return klass;
     162             : }
     163             : 
     164             : void
     165           0 : _hb_ot_shape_fallback_position_recategorize_marks (const hb_ot_shape_plan_t *plan HB_UNUSED,
     166             :                                                    hb_font_t *font HB_UNUSED,
     167             :                                                    hb_buffer_t  *buffer)
     168             : {
     169           0 :   unsigned int count = buffer->len;
     170           0 :   hb_glyph_info_t *info = buffer->info;
     171           0 :   for (unsigned int i = 0; i < count; i++)
     172           0 :     if (_hb_glyph_info_get_general_category (&info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) {
     173           0 :       unsigned int combining_class = _hb_glyph_info_get_modified_combining_class (&info[i]);
     174           0 :       combining_class = recategorize_combining_class (info[i].codepoint, combining_class);
     175           0 :       _hb_glyph_info_set_modified_combining_class (&info[i], combining_class);
     176             :     }
     177           0 : }
     178             : 
     179             : 
     180             : static void
     181           0 : zero_mark_advances (hb_buffer_t *buffer,
     182             :                     unsigned int start,
     183             :                     unsigned int end)
     184             : {
     185           0 :   hb_glyph_info_t *info = buffer->info;
     186           0 :   for (unsigned int i = start; i < end; i++)
     187           0 :     if (_hb_glyph_info_get_general_category (&info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
     188             :     {
     189           0 :       buffer->pos[i].x_advance = 0;
     190           0 :       buffer->pos[i].y_advance = 0;
     191             :     }
     192           0 : }
     193             : 
     194             : static inline void
     195           0 : position_mark (const hb_ot_shape_plan_t *plan,
     196             :                hb_font_t *font,
     197             :                hb_buffer_t  *buffer,
     198             :                hb_glyph_extents_t &base_extents,
     199             :                unsigned int i,
     200             :                unsigned int combining_class)
     201             : {
     202             :   hb_glyph_extents_t mark_extents;
     203           0 :   if (!font->get_glyph_extents (buffer->info[i].codepoint,
     204             :                                 &mark_extents))
     205           0 :     return;
     206             : 
     207           0 :   hb_position_t y_gap = font->y_scale / 16;
     208             : 
     209           0 :   hb_glyph_position_t &pos = buffer->pos[i];
     210           0 :   pos.x_offset = pos.y_offset = 0;
     211             : 
     212             : 
     213             :   /* We dont position LEFT and RIGHT marks. */
     214             : 
     215             :   /* X positioning */
     216           0 :   switch (combining_class)
     217             :   {
     218             :     case HB_UNICODE_COMBINING_CLASS_DOUBLE_BELOW:
     219             :     case HB_UNICODE_COMBINING_CLASS_DOUBLE_ABOVE:
     220           0 :       if (buffer->props.direction == HB_DIRECTION_LTR) {
     221           0 :         pos.x_offset += base_extents.x_bearing - mark_extents.width / 2 - mark_extents.x_bearing;
     222           0 :         break;
     223           0 :       } else if (buffer->props.direction == HB_DIRECTION_RTL) {
     224           0 :         pos.x_offset += base_extents.x_bearing + base_extents.width - mark_extents.width / 2 - mark_extents.x_bearing;
     225           0 :         break;
     226             :       }
     227             :       HB_FALLTHROUGH;
     228             : 
     229             :     default:
     230             :     case HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW:
     231             :     case HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE:
     232             :     case HB_UNICODE_COMBINING_CLASS_BELOW:
     233             :     case HB_UNICODE_COMBINING_CLASS_ABOVE:
     234             :       /* Center align. */
     235           0 :       pos.x_offset += base_extents.x_bearing + (base_extents.width - mark_extents.width) / 2 - mark_extents.x_bearing;
     236           0 :       break;
     237             : 
     238             :     case HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW_LEFT:
     239             :     case HB_UNICODE_COMBINING_CLASS_BELOW_LEFT:
     240             :     case HB_UNICODE_COMBINING_CLASS_ABOVE_LEFT:
     241             :       /* Left align. */
     242           0 :       pos.x_offset += base_extents.x_bearing - mark_extents.x_bearing;
     243           0 :       break;
     244             : 
     245             :     case HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE_RIGHT:
     246             :     case HB_UNICODE_COMBINING_CLASS_BELOW_RIGHT:
     247             :     case HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT:
     248             :       /* Right align. */
     249           0 :       pos.x_offset += base_extents.x_bearing + base_extents.width - mark_extents.width - mark_extents.x_bearing;
     250           0 :       break;
     251             :   }
     252             : 
     253             :   /* Y positioning */
     254           0 :   switch (combining_class)
     255             :   {
     256             :     case HB_UNICODE_COMBINING_CLASS_DOUBLE_BELOW:
     257             :     case HB_UNICODE_COMBINING_CLASS_BELOW_LEFT:
     258             :     case HB_UNICODE_COMBINING_CLASS_BELOW:
     259             :     case HB_UNICODE_COMBINING_CLASS_BELOW_RIGHT:
     260             :       /* Add gap, fall-through. */
     261           0 :       base_extents.height -= y_gap;
     262             :       HB_FALLTHROUGH;
     263             : 
     264             :     case HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW_LEFT:
     265             :     case HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW:
     266           0 :       pos.y_offset = base_extents.y_bearing + base_extents.height - mark_extents.y_bearing;
     267             :       /* Never shift up "below" marks. */
     268           0 :       if ((y_gap > 0) == (pos.y_offset > 0))
     269             :       {
     270           0 :         base_extents.height -= pos.y_offset;
     271           0 :         pos.y_offset = 0;
     272             :       }
     273           0 :       base_extents.height += mark_extents.height;
     274           0 :       break;
     275             : 
     276             :     case HB_UNICODE_COMBINING_CLASS_DOUBLE_ABOVE:
     277             :     case HB_UNICODE_COMBINING_CLASS_ABOVE_LEFT:
     278             :     case HB_UNICODE_COMBINING_CLASS_ABOVE:
     279             :     case HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT:
     280             :       /* Add gap, fall-through. */
     281           0 :       base_extents.y_bearing += y_gap;
     282           0 :       base_extents.height -= y_gap;
     283             :       HB_FALLTHROUGH;
     284             : 
     285             :     case HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE:
     286             :     case HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE_RIGHT:
     287           0 :       pos.y_offset = base_extents.y_bearing - (mark_extents.y_bearing + mark_extents.height);
     288             :       /* Don't shift down "above" marks too much. */
     289           0 :       if ((y_gap > 0) != (pos.y_offset > 0))
     290             :       {
     291           0 :         unsigned int correction = -pos.y_offset / 2;
     292           0 :         base_extents.y_bearing += correction;
     293           0 :         base_extents.height -= correction;
     294           0 :         pos.y_offset += correction;
     295             :       }
     296           0 :       base_extents.y_bearing -= mark_extents.height;
     297           0 :       base_extents.height += mark_extents.height;
     298           0 :       break;
     299             :   }
     300             : }
     301             : 
     302             : static inline void
     303           0 : position_around_base (const hb_ot_shape_plan_t *plan,
     304             :                       hb_font_t *font,
     305             :                       hb_buffer_t  *buffer,
     306             :                       unsigned int base,
     307             :                       unsigned int end)
     308             : {
     309           0 :   hb_direction_t horiz_dir = HB_DIRECTION_INVALID;
     310             :   hb_glyph_extents_t base_extents;
     311           0 :   if (!font->get_glyph_extents (buffer->info[base].codepoint,
     312             :                                 &base_extents))
     313             :   {
     314             :     /* If extents don't work, zero marks and go home. */
     315           0 :     zero_mark_advances (buffer, base + 1, end);
     316           0 :     return;
     317             :   }
     318           0 :   base_extents.x_bearing += buffer->pos[base].x_offset;
     319           0 :   base_extents.y_bearing += buffer->pos[base].y_offset;
     320             : 
     321           0 :   unsigned int lig_id = _hb_glyph_info_get_lig_id (&buffer->info[base]);
     322           0 :   unsigned int num_lig_components = _hb_glyph_info_get_lig_num_comps (&buffer->info[base]);
     323             : 
     324           0 :   hb_position_t x_offset = 0, y_offset = 0;
     325           0 :   if (HB_DIRECTION_IS_FORWARD (buffer->props.direction)) {
     326           0 :     x_offset -= buffer->pos[base].x_advance;
     327           0 :     y_offset -= buffer->pos[base].y_advance;
     328             :   }
     329             : 
     330           0 :   hb_glyph_extents_t component_extents = base_extents;
     331           0 :   unsigned int last_lig_component = (unsigned int) -1;
     332           0 :   unsigned int last_combining_class = 255;
     333           0 :   hb_glyph_extents_t cluster_extents = base_extents; /* Initialization is just to shut gcc up. */
     334           0 :   hb_glyph_info_t *info = buffer->info;
     335           0 :   for (unsigned int i = base + 1; i < end; i++)
     336           0 :     if (_hb_glyph_info_get_modified_combining_class (&info[i]))
     337             :     {
     338           0 :       if (num_lig_components > 1) {
     339           0 :         unsigned int this_lig_id = _hb_glyph_info_get_lig_id (&info[i]);
     340           0 :         unsigned int this_lig_component = _hb_glyph_info_get_lig_comp (&info[i]) - 1;
     341             :         /* Conditions for attaching to the last component. */
     342           0 :         if (!lig_id || lig_id != this_lig_id || this_lig_component >= num_lig_components)
     343           0 :           this_lig_component = num_lig_components - 1;
     344           0 :         if (last_lig_component != this_lig_component)
     345             :         {
     346           0 :           last_lig_component = this_lig_component;
     347           0 :           last_combining_class = 255;
     348           0 :           component_extents = base_extents;
     349           0 :           if (unlikely (horiz_dir == HB_DIRECTION_INVALID)) {
     350           0 :             if (HB_DIRECTION_IS_HORIZONTAL (plan->props.direction))
     351           0 :               horiz_dir = plan->props.direction;
     352             :             else
     353           0 :               horiz_dir = hb_script_get_horizontal_direction (plan->props.script);
     354             :           }
     355           0 :           if (horiz_dir == HB_DIRECTION_LTR)
     356           0 :             component_extents.x_bearing += (this_lig_component * component_extents.width) / num_lig_components;
     357             :           else
     358           0 :             component_extents.x_bearing += ((num_lig_components - 1 - this_lig_component) * component_extents.width) / num_lig_components;
     359           0 :           component_extents.width /= num_lig_components;
     360             :         }
     361             :       }
     362             : 
     363           0 :       unsigned int this_combining_class = _hb_glyph_info_get_modified_combining_class (&info[i]);
     364           0 :       if (last_combining_class != this_combining_class)
     365             :       {
     366           0 :         last_combining_class = this_combining_class;
     367           0 :         cluster_extents = component_extents;
     368             :       }
     369             : 
     370           0 :       position_mark (plan, font, buffer, cluster_extents, i, this_combining_class);
     371             : 
     372           0 :       buffer->pos[i].x_advance = 0;
     373           0 :       buffer->pos[i].y_advance = 0;
     374           0 :       buffer->pos[i].x_offset += x_offset;
     375           0 :       buffer->pos[i].y_offset += y_offset;
     376             : 
     377             :     } else {
     378           0 :       if (HB_DIRECTION_IS_FORWARD (buffer->props.direction)) {
     379           0 :         x_offset -= buffer->pos[i].x_advance;
     380           0 :         y_offset -= buffer->pos[i].y_advance;
     381             :       } else {
     382           0 :         x_offset += buffer->pos[i].x_advance;
     383           0 :         y_offset += buffer->pos[i].y_advance;
     384             :       }
     385             :     }
     386             : }
     387             : 
     388             : static inline void
     389           0 : position_cluster (const hb_ot_shape_plan_t *plan,
     390             :                   hb_font_t *font,
     391             :                   hb_buffer_t  *buffer,
     392             :                   unsigned int start,
     393             :                   unsigned int end)
     394             : {
     395           0 :   if (end - start < 2)
     396           0 :     return;
     397             : 
     398             :   /* Find the base glyph */
     399           0 :   hb_glyph_info_t *info = buffer->info;
     400           0 :   for (unsigned int i = start; i < end; i++)
     401           0 :     if (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i])))
     402             :     {
     403             :       /* Find mark glyphs */
     404             :       unsigned int j;
     405           0 :       for (j = i + 1; j < end; j++)
     406           0 :         if (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[j])))
     407           0 :           break;
     408             : 
     409           0 :       position_around_base (plan, font, buffer, i, j);
     410             : 
     411           0 :       i = j - 1;
     412             :     }
     413             : }
     414             : 
     415             : void
     416           0 : _hb_ot_shape_fallback_position (const hb_ot_shape_plan_t *plan,
     417             :                                 hb_font_t *font,
     418             :                                 hb_buffer_t  *buffer)
     419             : {
     420           0 :   _hb_buffer_assert_gsubgpos_vars (buffer);
     421             : 
     422           0 :   unsigned int start = 0;
     423           0 :   unsigned int count = buffer->len;
     424           0 :   hb_glyph_info_t *info = buffer->info;
     425           0 :   for (unsigned int i = 1; i < count; i++)
     426           0 :     if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i])))) {
     427           0 :       position_cluster (plan, font, buffer, start, i);
     428           0 :       start = i;
     429             :     }
     430           0 :   position_cluster (plan, font, buffer, start, count);
     431           0 : }
     432             : 
     433             : 
     434             : /* Performs old-style TrueType kerning. */
     435             : void
     436           0 : _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan,
     437             :                             hb_font_t *font,
     438             :                             hb_buffer_t  *buffer)
     439             : {
     440           0 :   if (!plan->has_kern) return;
     441             : 
     442           0 :   OT::hb_apply_context_t c (1, font, buffer);
     443           0 :   c.set_lookup_mask (plan->kern_mask);
     444           0 :   c.set_lookup_props (OT::LookupFlag::IgnoreMarks);
     445           0 :   OT::hb_apply_context_t::skipping_iterator_t &skippy_iter = c.iter_input;
     446           0 :   skippy_iter.init (&c);
     447             : 
     448           0 :   unsigned int count = buffer->len;
     449           0 :   hb_glyph_info_t *info = buffer->info;
     450           0 :   hb_glyph_position_t *pos = buffer->pos;
     451           0 :   for (unsigned int idx = 0; idx < count;)
     452             :   {
     453           0 :     skippy_iter.reset (idx, 1);
     454           0 :     if (!skippy_iter.next ())
     455             :     {
     456           0 :       idx++;
     457           0 :       continue;
     458             :     }
     459             : 
     460             :     hb_position_t x_kern, y_kern;
     461           0 :     font->get_glyph_kerning_for_direction (info[idx].codepoint,
     462           0 :                                            info[skippy_iter.idx].codepoint,
     463             :                                            buffer->props.direction,
     464           0 :                                            &x_kern, &y_kern);
     465             : 
     466           0 :     if (x_kern)
     467             :     {
     468           0 :       hb_position_t kern1 = x_kern >> 1;
     469           0 :       hb_position_t kern2 = x_kern - kern1;
     470           0 :       pos[idx].x_advance += kern1;
     471           0 :       pos[skippy_iter.idx].x_advance += kern2;
     472           0 :       pos[skippy_iter.idx].x_offset += kern2;
     473             :     }
     474             : 
     475           0 :     if (y_kern)
     476             :     {
     477           0 :       hb_position_t kern1 = y_kern >> 1;
     478           0 :       hb_position_t kern2 = y_kern - kern1;
     479           0 :       pos[idx].y_advance += kern1;
     480           0 :       pos[skippy_iter.idx].y_advance += kern2;
     481           0 :       pos[skippy_iter.idx].y_offset += kern2;
     482             :     }
     483             : 
     484           0 :     idx = skippy_iter.idx;
     485             :   }
     486             : }
     487             : 
     488             : 
     489             : /* Adjusts width of various spaces. */
     490             : void
     491           0 : _hb_ot_shape_fallback_spaces (const hb_ot_shape_plan_t *plan,
     492             :                               hb_font_t *font,
     493             :                               hb_buffer_t  *buffer)
     494             : {
     495           0 :   if (!HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction))
     496           0 :     return;
     497             : 
     498           0 :   hb_glyph_info_t *info = buffer->info;
     499           0 :   hb_glyph_position_t *pos = buffer->pos;
     500           0 :   unsigned int count = buffer->len;
     501           0 :   for (unsigned int i = 0; i < count; i++)
     502           0 :     if (_hb_glyph_info_is_unicode_space (&info[i]) && !_hb_glyph_info_ligated (&info[i]))
     503             :     {
     504           0 :       hb_unicode_funcs_t::space_t space_type = _hb_glyph_info_get_unicode_space_fallback_type (&info[i]);
     505             :       hb_codepoint_t glyph;
     506             :       typedef hb_unicode_funcs_t t;
     507           0 :       switch (space_type)
     508             :       {
     509             :         case t::NOT_SPACE: /* Shouldn't happen. */
     510             :         case t::SPACE:
     511           0 :           break;
     512             : 
     513             :         case t::SPACE_EM:
     514             :         case t::SPACE_EM_2:
     515             :         case t::SPACE_EM_3:
     516             :         case t::SPACE_EM_4:
     517             :         case t::SPACE_EM_5:
     518             :         case t::SPACE_EM_6:
     519             :         case t::SPACE_EM_16:
     520           0 :           pos[i].x_advance = (font->x_scale + ((int) space_type)/2) / (int) space_type;
     521           0 :           break;
     522             : 
     523             :         case t::SPACE_4_EM_18:
     524           0 :           pos[i].x_advance = font->x_scale * 4 / 18;
     525           0 :           break;
     526             : 
     527             :         case t::SPACE_FIGURE:
     528           0 :           for (char u = '0'; u <= '9'; u++)
     529           0 :             if (font->get_nominal_glyph (u, &glyph))
     530             :             {
     531           0 :               pos[i].x_advance = font->get_glyph_h_advance (glyph);
     532           0 :               break;
     533             :             }
     534           0 :           break;
     535             : 
     536             :         case t::SPACE_PUNCTUATION:
     537           0 :           if (font->get_nominal_glyph ('.', &glyph))
     538           0 :             pos[i].x_advance = font->get_glyph_h_advance (glyph);
     539           0 :           else if (font->get_nominal_glyph (',', &glyph))
     540           0 :             pos[i].x_advance = font->get_glyph_h_advance (glyph);
     541           0 :           break;
     542             : 
     543             :         case t::SPACE_NARROW:
     544             :           /* Half-space?
     545             :            * Unicode doc http://www.unicode.org/charts/PDF/U2000.pdf says ~1/4 or 1/5 of EM.
     546             :            * However, in my testing, many fonts have their regular space being about that
     547             :            * size.  To me, a percentage of the space width makes more sense.  Half is as
     548             :            * good as any. */
     549           0 :           pos[i].x_advance /= 2;
     550           0 :           break;
     551             :       }
     552             :     }
     553             : }

Generated by: LCOV version 1.13