1affaf8a0e5aa38e5820455f789eebf916e02eb7bBehdad Esfahbod/*
2affaf8a0e5aa38e5820455f789eebf916e02eb7bBehdad Esfahbod * Copyright © 2011,2012  Google, Inc.
3affaf8a0e5aa38e5820455f789eebf916e02eb7bBehdad Esfahbod *
4affaf8a0e5aa38e5820455f789eebf916e02eb7bBehdad Esfahbod *  This is part of HarfBuzz, a text shaping library.
5affaf8a0e5aa38e5820455f789eebf916e02eb7bBehdad Esfahbod *
6affaf8a0e5aa38e5820455f789eebf916e02eb7bBehdad Esfahbod * Permission is hereby granted, without written agreement and without
7affaf8a0e5aa38e5820455f789eebf916e02eb7bBehdad Esfahbod * license or royalty fees, to use, copy, modify, and distribute this
8affaf8a0e5aa38e5820455f789eebf916e02eb7bBehdad Esfahbod * software and its documentation for any purpose, provided that the
9affaf8a0e5aa38e5820455f789eebf916e02eb7bBehdad Esfahbod * above copyright notice and the following two paragraphs appear in
10affaf8a0e5aa38e5820455f789eebf916e02eb7bBehdad Esfahbod * all copies of this software.
11affaf8a0e5aa38e5820455f789eebf916e02eb7bBehdad Esfahbod *
12affaf8a0e5aa38e5820455f789eebf916e02eb7bBehdad Esfahbod * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13affaf8a0e5aa38e5820455f789eebf916e02eb7bBehdad Esfahbod * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14affaf8a0e5aa38e5820455f789eebf916e02eb7bBehdad Esfahbod * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15affaf8a0e5aa38e5820455f789eebf916e02eb7bBehdad Esfahbod * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
16affaf8a0e5aa38e5820455f789eebf916e02eb7bBehdad Esfahbod * DAMAGE.
17affaf8a0e5aa38e5820455f789eebf916e02eb7bBehdad Esfahbod *
18affaf8a0e5aa38e5820455f789eebf916e02eb7bBehdad Esfahbod * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19affaf8a0e5aa38e5820455f789eebf916e02eb7bBehdad Esfahbod * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20affaf8a0e5aa38e5820455f789eebf916e02eb7bBehdad Esfahbod * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
21affaf8a0e5aa38e5820455f789eebf916e02eb7bBehdad Esfahbod * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22affaf8a0e5aa38e5820455f789eebf916e02eb7bBehdad Esfahbod * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
23affaf8a0e5aa38e5820455f789eebf916e02eb7bBehdad Esfahbod *
24affaf8a0e5aa38e5820455f789eebf916e02eb7bBehdad Esfahbod * Google Author(s): Behdad Esfahbod
25affaf8a0e5aa38e5820455f789eebf916e02eb7bBehdad Esfahbod */
26affaf8a0e5aa38e5820455f789eebf916e02eb7bBehdad Esfahbod
279c929abdcfef44c0193a2917b20981df37ade21cBehdad Esfahbod#include "hb-ot-shape-fallback-private.hh"
28d46606e119b48dcca375d6313abd0f93ba5d09c3Behdad Esfahbod#include "hb-ot-layout-gsubgpos-private.hh"
29affaf8a0e5aa38e5820455f789eebf916e02eb7bBehdad Esfahbod
3021756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbodstatic unsigned int
313992b5ec4cb43d114d87ff7ee2b992bcf819c9cdBehdad Esfahbodrecategorize_combining_class (hb_codepoint_t u,
321d581ec384bc1780995e32e1c44103af57596edaBehdad Esfahbod			      unsigned int klass)
3321756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod{
341d581ec384bc1780995e32e1c44103af57596edaBehdad Esfahbod  if (klass >= 200)
351d581ec384bc1780995e32e1c44103af57596edaBehdad Esfahbod    return klass;
3621756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod
371d581ec384bc1780995e32e1c44103af57596edaBehdad Esfahbod  /* Thai / Lao need some per-character work. */
387627100f428ac0ec8509d961d368d2d25d8f0b6eBehdad Esfahbod  if ((u & ~0xFF) == 0x0E00u)
391d581ec384bc1780995e32e1c44103af57596edaBehdad Esfahbod  {
401d581ec384bc1780995e32e1c44103af57596edaBehdad Esfahbod    if (unlikely (klass == 0))
411d581ec384bc1780995e32e1c44103af57596edaBehdad Esfahbod    {
421d581ec384bc1780995e32e1c44103af57596edaBehdad Esfahbod      switch (u)
431d581ec384bc1780995e32e1c44103af57596edaBehdad Esfahbod      {
447627100f428ac0ec8509d961d368d2d25d8f0b6eBehdad Esfahbod        case 0x0E31u:
457627100f428ac0ec8509d961d368d2d25d8f0b6eBehdad Esfahbod        case 0x0E34u:
467627100f428ac0ec8509d961d368d2d25d8f0b6eBehdad Esfahbod        case 0x0E35u:
477627100f428ac0ec8509d961d368d2d25d8f0b6eBehdad Esfahbod        case 0x0E36u:
487627100f428ac0ec8509d961d368d2d25d8f0b6eBehdad Esfahbod        case 0x0E37u:
497627100f428ac0ec8509d961d368d2d25d8f0b6eBehdad Esfahbod        case 0x0E47u:
507627100f428ac0ec8509d961d368d2d25d8f0b6eBehdad Esfahbod        case 0x0E4Cu:
517627100f428ac0ec8509d961d368d2d25d8f0b6eBehdad Esfahbod        case 0x0E4Du:
527627100f428ac0ec8509d961d368d2d25d8f0b6eBehdad Esfahbod        case 0x0E4Eu:
531d581ec384bc1780995e32e1c44103af57596edaBehdad Esfahbod	  klass = HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT;
541d581ec384bc1780995e32e1c44103af57596edaBehdad Esfahbod	  break;
551d581ec384bc1780995e32e1c44103af57596edaBehdad Esfahbod
567627100f428ac0ec8509d961d368d2d25d8f0b6eBehdad Esfahbod        case 0x0EB1u:
577627100f428ac0ec8509d961d368d2d25d8f0b6eBehdad Esfahbod        case 0x0EB4u:
587627100f428ac0ec8509d961d368d2d25d8f0b6eBehdad Esfahbod        case 0x0EB5u:
597627100f428ac0ec8509d961d368d2d25d8f0b6eBehdad Esfahbod        case 0x0EB6u:
607627100f428ac0ec8509d961d368d2d25d8f0b6eBehdad Esfahbod        case 0x0EB7u:
617627100f428ac0ec8509d961d368d2d25d8f0b6eBehdad Esfahbod        case 0x0EBBu:
627627100f428ac0ec8509d961d368d2d25d8f0b6eBehdad Esfahbod        case 0x0ECCu:
637627100f428ac0ec8509d961d368d2d25d8f0b6eBehdad Esfahbod        case 0x0ECDu:
641d581ec384bc1780995e32e1c44103af57596edaBehdad Esfahbod	  klass = HB_UNICODE_COMBINING_CLASS_ABOVE;
651d581ec384bc1780995e32e1c44103af57596edaBehdad Esfahbod	  break;
661d581ec384bc1780995e32e1c44103af57596edaBehdad Esfahbod
677627100f428ac0ec8509d961d368d2d25d8f0b6eBehdad Esfahbod        case 0x0EBCu:
681d581ec384bc1780995e32e1c44103af57596edaBehdad Esfahbod	  klass = HB_UNICODE_COMBINING_CLASS_BELOW;
691d581ec384bc1780995e32e1c44103af57596edaBehdad Esfahbod	  break;
701d581ec384bc1780995e32e1c44103af57596edaBehdad Esfahbod      }
711d581ec384bc1780995e32e1c44103af57596edaBehdad Esfahbod    } else {
721d581ec384bc1780995e32e1c44103af57596edaBehdad Esfahbod      /* Thai virama is below-right */
737627100f428ac0ec8509d961d368d2d25d8f0b6eBehdad Esfahbod      if (u == 0x0E3Au)
741d581ec384bc1780995e32e1c44103af57596edaBehdad Esfahbod	klass = HB_UNICODE_COMBINING_CLASS_BELOW_RIGHT;
751d581ec384bc1780995e32e1c44103af57596edaBehdad Esfahbod    }
761d581ec384bc1780995e32e1c44103af57596edaBehdad Esfahbod  }
771d581ec384bc1780995e32e1c44103af57596edaBehdad Esfahbod
781d581ec384bc1780995e32e1c44103af57596edaBehdad Esfahbod  switch (klass)
7921756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod  {
8056c9e7c004e802ddcb8c704346026f1d7a812f9fBehdad Esfahbod
8121756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    /* Hebrew */
8256c9e7c004e802ddcb8c704346026f1d7a812f9fBehdad Esfahbod
8321756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_MODIFIED_COMBINING_CLASS_CCC10: /* sheva */
8421756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_MODIFIED_COMBINING_CLASS_CCC11: /* hataf segol */
8521756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_MODIFIED_COMBINING_CLASS_CCC12: /* hataf patah */
8621756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_MODIFIED_COMBINING_CLASS_CCC13: /* hataf qamats */
8721756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_MODIFIED_COMBINING_CLASS_CCC14: /* hiriq */
8821756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_MODIFIED_COMBINING_CLASS_CCC15: /* tsere */
8921756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_MODIFIED_COMBINING_CLASS_CCC16: /* segol */
9021756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_MODIFIED_COMBINING_CLASS_CCC17: /* patah */
9121756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_MODIFIED_COMBINING_CLASS_CCC18: /* qamats */
9221756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_MODIFIED_COMBINING_CLASS_CCC20: /* qubuts */
9321756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_MODIFIED_COMBINING_CLASS_CCC22: /* meteg */
9421756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod      return HB_UNICODE_COMBINING_CLASS_BELOW;
9521756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod
9621756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_MODIFIED_COMBINING_CLASS_CCC23: /* rafe */
9721756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod      return HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE;
9821756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod
9921756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_MODIFIED_COMBINING_CLASS_CCC24: /* shin dot */
10021756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod      return HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT;
10121756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod
10221756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_MODIFIED_COMBINING_CLASS_CCC25: /* sin dot */
10321756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_MODIFIED_COMBINING_CLASS_CCC19: /* holam */
10421756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod      return HB_UNICODE_COMBINING_CLASS_ABOVE_LEFT;
10521756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod
10621756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_MODIFIED_COMBINING_CLASS_CCC26: /* point varika */
10721756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod      return HB_UNICODE_COMBINING_CLASS_ABOVE;
10821756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod
10921756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_MODIFIED_COMBINING_CLASS_CCC21: /* dagesh */
11021756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod      break;
11121756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod
11256c9e7c004e802ddcb8c704346026f1d7a812f9fBehdad Esfahbod
11321756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    /* Arabic and Syriac */
11456c9e7c004e802ddcb8c704346026f1d7a812f9fBehdad Esfahbod
11521756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_MODIFIED_COMBINING_CLASS_CCC27: /* fathatan */
11621756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_MODIFIED_COMBINING_CLASS_CCC28: /* dammatan */
11721756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_MODIFIED_COMBINING_CLASS_CCC30: /* fatha */
11821756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_MODIFIED_COMBINING_CLASS_CCC31: /* damma */
11921756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_MODIFIED_COMBINING_CLASS_CCC33: /* shadda */
12021756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_MODIFIED_COMBINING_CLASS_CCC34: /* sukun */
12121756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_MODIFIED_COMBINING_CLASS_CCC35: /* superscript alef */
12221756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_MODIFIED_COMBINING_CLASS_CCC36: /* superscript alaph */
12321756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod      return HB_UNICODE_COMBINING_CLASS_ABOVE;
12421756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod
12521756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_MODIFIED_COMBINING_CLASS_CCC29: /* kasratan */
12621756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_MODIFIED_COMBINING_CLASS_CCC32: /* kasra */
12721756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod      return HB_UNICODE_COMBINING_CLASS_BELOW;
12821756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod
12956c9e7c004e802ddcb8c704346026f1d7a812f9fBehdad Esfahbod
13056c9e7c004e802ddcb8c704346026f1d7a812f9fBehdad Esfahbod    /* Thai */
13156c9e7c004e802ddcb8c704346026f1d7a812f9fBehdad Esfahbod
13256c9e7c004e802ddcb8c704346026f1d7a812f9fBehdad Esfahbod    case HB_MODIFIED_COMBINING_CLASS_CCC103: /* sara u / sara uu */
1335a7f18767a87a3f07269d0814f984a98f86ab852Behdad Esfahbod      return HB_UNICODE_COMBINING_CLASS_BELOW_RIGHT;
13456c9e7c004e802ddcb8c704346026f1d7a812f9fBehdad Esfahbod
13556c9e7c004e802ddcb8c704346026f1d7a812f9fBehdad Esfahbod    case HB_MODIFIED_COMBINING_CLASS_CCC107: /* mai */
1365a7f18767a87a3f07269d0814f984a98f86ab852Behdad Esfahbod      return HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT;
13756c9e7c004e802ddcb8c704346026f1d7a812f9fBehdad Esfahbod
13856c9e7c004e802ddcb8c704346026f1d7a812f9fBehdad Esfahbod
13956c9e7c004e802ddcb8c704346026f1d7a812f9fBehdad Esfahbod    /* Lao */
14056c9e7c004e802ddcb8c704346026f1d7a812f9fBehdad Esfahbod
14156c9e7c004e802ddcb8c704346026f1d7a812f9fBehdad Esfahbod    case HB_MODIFIED_COMBINING_CLASS_CCC118: /* sign u / sign uu */
1427e99e4f0740e47efda5882604954cb7d12700a4bBehdad Esfahbod      return HB_UNICODE_COMBINING_CLASS_BELOW;
14356c9e7c004e802ddcb8c704346026f1d7a812f9fBehdad Esfahbod
14456c9e7c004e802ddcb8c704346026f1d7a812f9fBehdad Esfahbod    case HB_MODIFIED_COMBINING_CLASS_CCC122: /* mai */
1457e99e4f0740e47efda5882604954cb7d12700a4bBehdad Esfahbod      return HB_UNICODE_COMBINING_CLASS_ABOVE;
14656c9e7c004e802ddcb8c704346026f1d7a812f9fBehdad Esfahbod
14756c9e7c004e802ddcb8c704346026f1d7a812f9fBehdad Esfahbod
14856c9e7c004e802ddcb8c704346026f1d7a812f9fBehdad Esfahbod    /* Tibetan */
14956c9e7c004e802ddcb8c704346026f1d7a812f9fBehdad Esfahbod
15056c9e7c004e802ddcb8c704346026f1d7a812f9fBehdad Esfahbod    case HB_MODIFIED_COMBINING_CLASS_CCC129: /* sign aa */
15156c9e7c004e802ddcb8c704346026f1d7a812f9fBehdad Esfahbod      return HB_UNICODE_COMBINING_CLASS_BELOW;
15256c9e7c004e802ddcb8c704346026f1d7a812f9fBehdad Esfahbod
15356c9e7c004e802ddcb8c704346026f1d7a812f9fBehdad Esfahbod    case HB_MODIFIED_COMBINING_CLASS_CCC130: /* sign i*/
15456c9e7c004e802ddcb8c704346026f1d7a812f9fBehdad Esfahbod      return HB_UNICODE_COMBINING_CLASS_ABOVE;
15556c9e7c004e802ddcb8c704346026f1d7a812f9fBehdad Esfahbod
15656c9e7c004e802ddcb8c704346026f1d7a812f9fBehdad Esfahbod    case HB_MODIFIED_COMBINING_CLASS_CCC132: /* sign u */
15756c9e7c004e802ddcb8c704346026f1d7a812f9fBehdad Esfahbod      return HB_UNICODE_COMBINING_CLASS_BELOW;
15856c9e7c004e802ddcb8c704346026f1d7a812f9fBehdad Esfahbod
15921756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod  }
16021756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod
1611d581ec384bc1780995e32e1c44103af57596edaBehdad Esfahbod  return klass;
16221756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod}
16321756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod
1643992b5ec4cb43d114d87ff7ee2b992bcf819c9cdBehdad Esfahbodvoid
1650beb66e3a61ae8bb1fa66e54b1ff1abb2f8711e9Behdad Esfahbod_hb_ot_shape_fallback_position_recategorize_marks (const hb_ot_shape_plan_t *plan HB_UNUSED,
1660beb66e3a61ae8bb1fa66e54b1ff1abb2f8711e9Behdad Esfahbod						   hb_font_t *font HB_UNUSED,
1673992b5ec4cb43d114d87ff7ee2b992bcf819c9cdBehdad Esfahbod						   hb_buffer_t  *buffer)
1683992b5ec4cb43d114d87ff7ee2b992bcf819c9cdBehdad Esfahbod{
1693992b5ec4cb43d114d87ff7ee2b992bcf819c9cdBehdad Esfahbod  unsigned int count = buffer->len;
1707cd33f230441093dbfb1fec48f8c580ee8d9ef71Behdad Esfahbod  hb_glyph_info_t *info = buffer->info;
1713992b5ec4cb43d114d87ff7ee2b992bcf819c9cdBehdad Esfahbod  for (unsigned int i = 0; i < count; i++)
1727cd33f230441093dbfb1fec48f8c580ee8d9ef71Behdad Esfahbod    if (_hb_glyph_info_get_general_category (&info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) {
1737cd33f230441093dbfb1fec48f8c580ee8d9ef71Behdad Esfahbod      unsigned int combining_class = _hb_glyph_info_get_modified_combining_class (&info[i]);
1747cd33f230441093dbfb1fec48f8c580ee8d9ef71Behdad Esfahbod      combining_class = recategorize_combining_class (info[i].codepoint, combining_class);
1757cd33f230441093dbfb1fec48f8c580ee8d9ef71Behdad Esfahbod      _hb_glyph_info_set_modified_combining_class (&info[i], combining_class);
1763992b5ec4cb43d114d87ff7ee2b992bcf819c9cdBehdad Esfahbod    }
1773992b5ec4cb43d114d87ff7ee2b992bcf819c9cdBehdad Esfahbod}
1783992b5ec4cb43d114d87ff7ee2b992bcf819c9cdBehdad Esfahbod
1793992b5ec4cb43d114d87ff7ee2b992bcf819c9cdBehdad Esfahbod
1803992b5ec4cb43d114d87ff7ee2b992bcf819c9cdBehdad Esfahbodstatic void
1813992b5ec4cb43d114d87ff7ee2b992bcf819c9cdBehdad Esfahbodzero_mark_advances (hb_buffer_t *buffer,
1823992b5ec4cb43d114d87ff7ee2b992bcf819c9cdBehdad Esfahbod		    unsigned int start,
1833992b5ec4cb43d114d87ff7ee2b992bcf819c9cdBehdad Esfahbod		    unsigned int end)
1843992b5ec4cb43d114d87ff7ee2b992bcf819c9cdBehdad Esfahbod{
1857cd33f230441093dbfb1fec48f8c580ee8d9ef71Behdad Esfahbod  hb_glyph_info_t *info = buffer->info;
1863992b5ec4cb43d114d87ff7ee2b992bcf819c9cdBehdad Esfahbod  for (unsigned int i = start; i < end; i++)
1877cd33f230441093dbfb1fec48f8c580ee8d9ef71Behdad Esfahbod    if (_hb_glyph_info_get_general_category (&info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
1883992b5ec4cb43d114d87ff7ee2b992bcf819c9cdBehdad Esfahbod    {
1893992b5ec4cb43d114d87ff7ee2b992bcf819c9cdBehdad Esfahbod      buffer->pos[i].x_advance = 0;
1903992b5ec4cb43d114d87ff7ee2b992bcf819c9cdBehdad Esfahbod      buffer->pos[i].y_advance = 0;
1913992b5ec4cb43d114d87ff7ee2b992bcf819c9cdBehdad Esfahbod    }
1923992b5ec4cb43d114d87ff7ee2b992bcf819c9cdBehdad Esfahbod}
1933992b5ec4cb43d114d87ff7ee2b992bcf819c9cdBehdad Esfahbod
19421756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbodstatic inline void
19521756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbodposition_mark (const hb_ot_shape_plan_t *plan,
19621756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod	       hb_font_t *font,
19721756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod	       hb_buffer_t  *buffer,
19821756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod	       hb_glyph_extents_t &base_extents,
19921756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod	       unsigned int i,
20021756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod	       unsigned int combining_class)
20121756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod{
20221756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod  hb_glyph_extents_t mark_extents;
2034c8ac4f47e95d2b266b2f64e75c55af8233b6b91Behdad Esfahbod  if (!font->get_glyph_extents (buffer->info[i].codepoint,
2044c8ac4f47e95d2b266b2f64e75c55af8233b6b91Behdad Esfahbod				&mark_extents))
20521756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    return;
20621756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod
20721756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod  hb_position_t y_gap = font->y_scale / 16;
20821756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod
20921756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod  hb_glyph_position_t &pos = buffer->pos[i];
21021756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod  pos.x_offset = pos.y_offset = 0;
21121756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod
21221756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod
21321756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod  /* We dont position LEFT and RIGHT marks. */
21421756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod
21521756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod  /* X positioning */
21621756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod  switch (combining_class)
21721756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod  {
21821756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_UNICODE_COMBINING_CLASS_DOUBLE_BELOW:
21921756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_UNICODE_COMBINING_CLASS_DOUBLE_ABOVE:
220daf13afb0801740dcc7900c4af190e24b80a05c0Behdad Esfahbod      if (buffer->props.direction == HB_DIRECTION_LTR) {
221daf13afb0801740dcc7900c4af190e24b80a05c0Behdad Esfahbod	pos.x_offset += base_extents.x_bearing - mark_extents.width / 2 - mark_extents.x_bearing;
222daf13afb0801740dcc7900c4af190e24b80a05c0Behdad Esfahbod        break;
223daf13afb0801740dcc7900c4af190e24b80a05c0Behdad Esfahbod      } else if (buffer->props.direction == HB_DIRECTION_RTL) {
224daf13afb0801740dcc7900c4af190e24b80a05c0Behdad Esfahbod	pos.x_offset += base_extents.x_bearing + base_extents.width - mark_extents.width / 2 - mark_extents.x_bearing;
225daf13afb0801740dcc7900c4af190e24b80a05c0Behdad Esfahbod        break;
226daf13afb0801740dcc7900c4af190e24b80a05c0Behdad Esfahbod      }
227daf13afb0801740dcc7900c4af190e24b80a05c0Behdad Esfahbod      /* Fall through */
22821756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod
229e1ba62811a61afb046d349e578cd141363c7fb34Behdad Esfahbod    default:
23021756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW:
23121756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE:
23221756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_UNICODE_COMBINING_CLASS_BELOW:
23321756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_UNICODE_COMBINING_CLASS_ABOVE:
23421756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod      /* Center align. */
23521756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod      pos.x_offset += base_extents.x_bearing + (base_extents.width - mark_extents.width) / 2 - mark_extents.x_bearing;
23621756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod      break;
23721756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod
23821756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW_LEFT:
23921756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_UNICODE_COMBINING_CLASS_BELOW_LEFT:
24021756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_UNICODE_COMBINING_CLASS_ABOVE_LEFT:
24121756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod      /* Left align. */
24221756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod      pos.x_offset += base_extents.x_bearing - mark_extents.x_bearing;
24321756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod      break;
24421756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod
24521756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE_RIGHT:
24621756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_UNICODE_COMBINING_CLASS_BELOW_RIGHT:
24721756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT:
24821756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod      /* Right align. */
24921756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod      pos.x_offset += base_extents.x_bearing + base_extents.width - mark_extents.width - mark_extents.x_bearing;
25021756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod      break;
25121756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod  }
25221756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod
25321756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod  /* Y positioning */
25421756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod  switch (combining_class)
25521756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod  {
25621756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_UNICODE_COMBINING_CLASS_DOUBLE_BELOW:
25721756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_UNICODE_COMBINING_CLASS_BELOW_LEFT:
25821756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_UNICODE_COMBINING_CLASS_BELOW:
25921756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_UNICODE_COMBINING_CLASS_BELOW_RIGHT:
26021756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod      /* Add gap, fall-through. */
26121756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod      base_extents.height -= y_gap;
26221756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod
26321756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW_LEFT:
26421756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW:
2658177da29ad07d8fa444ce07003fa65cd31a2776bBehdad Esfahbod      pos.y_offset = base_extents.y_bearing + base_extents.height - mark_extents.y_bearing;
2660193649ce4ca78b8e2835a50bd51ee594cffe34eBehdad Esfahbod      /* Never shift up "below" marks. */
267dba9580237da788275b1ab5fe6be75c8a3f359b9Behdad Esfahbod      if ((y_gap > 0) == (pos.y_offset > 0))
268dba9580237da788275b1ab5fe6be75c8a3f359b9Behdad Esfahbod      {
269dba9580237da788275b1ab5fe6be75c8a3f359b9Behdad Esfahbod	base_extents.height -= pos.y_offset;
270dba9580237da788275b1ab5fe6be75c8a3f359b9Behdad Esfahbod	pos.y_offset = 0;
271dba9580237da788275b1ab5fe6be75c8a3f359b9Behdad Esfahbod      }
27221756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod      base_extents.height += mark_extents.height;
27321756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod      break;
27421756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod
27521756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_UNICODE_COMBINING_CLASS_DOUBLE_ABOVE:
27621756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_UNICODE_COMBINING_CLASS_ABOVE_LEFT:
27721756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_UNICODE_COMBINING_CLASS_ABOVE:
27821756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT:
27921756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod      /* Add gap, fall-through. */
28021756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod      base_extents.y_bearing += y_gap;
28121756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod      base_extents.height -= y_gap;
28221756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod
28321756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE:
28421756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    case HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE_RIGHT:
2858177da29ad07d8fa444ce07003fa65cd31a2776bBehdad Esfahbod      pos.y_offset = base_extents.y_bearing - (mark_extents.y_bearing + mark_extents.height);
2860193649ce4ca78b8e2835a50bd51ee594cffe34eBehdad Esfahbod      /* Don't shift down "above" marks too much. */
2870193649ce4ca78b8e2835a50bd51ee594cffe34eBehdad Esfahbod      if ((y_gap > 0) != (pos.y_offset > 0))
2880193649ce4ca78b8e2835a50bd51ee594cffe34eBehdad Esfahbod      {
2890193649ce4ca78b8e2835a50bd51ee594cffe34eBehdad Esfahbod	unsigned int correction = -pos.y_offset / 2;
2900193649ce4ca78b8e2835a50bd51ee594cffe34eBehdad Esfahbod	base_extents.y_bearing += correction;
2910193649ce4ca78b8e2835a50bd51ee594cffe34eBehdad Esfahbod	base_extents.height -= correction;
2920193649ce4ca78b8e2835a50bd51ee594cffe34eBehdad Esfahbod	pos.y_offset += correction;
2930193649ce4ca78b8e2835a50bd51ee594cffe34eBehdad Esfahbod      }
29421756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod      base_extents.y_bearing -= mark_extents.height;
29521756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod      base_extents.height += mark_extents.height;
29621756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod      break;
29721756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod  }
29821756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod}
29921756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod
30021756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbodstatic inline void
30121756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbodposition_around_base (const hb_ot_shape_plan_t *plan,
30221756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod		      hb_font_t *font,
30321756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod		      hb_buffer_t  *buffer,
30421756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod		      unsigned int base,
30521756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod		      unsigned int end)
30621756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod{
307f67917161bbe317a33d6407fbc62ebffcafe7154Behdad Esfahbod  hb_direction_t horiz_dir = HB_DIRECTION_INVALID;
30821756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod  hb_glyph_extents_t base_extents;
3094c8ac4f47e95d2b266b2f64e75c55af8233b6b91Behdad Esfahbod  if (!font->get_glyph_extents (buffer->info[base].codepoint,
3104c8ac4f47e95d2b266b2f64e75c55af8233b6b91Behdad Esfahbod				&base_extents))
31121756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod  {
31221756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    /* If extents don't work, zero marks and go home. */
31321756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    zero_mark_advances (buffer, base + 1, end);
31421756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    return;
31521756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod  }
31621756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod  base_extents.x_bearing += buffer->pos[base].x_offset;
31721756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod  base_extents.y_bearing += buffer->pos[base].y_offset;
31821756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod
3193ddf892b5328b74afb6e7d9da727d8771ca5d288Behdad Esfahbod  unsigned int lig_id = _hb_glyph_info_get_lig_id (&buffer->info[base]);
3203ddf892b5328b74afb6e7d9da727d8771ca5d288Behdad Esfahbod  unsigned int num_lig_components = _hb_glyph_info_get_lig_num_comps (&buffer->info[base]);
32121756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod
32221756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod  hb_position_t x_offset = 0, y_offset = 0;
323d345313104d9e3c8a8533ccdebd74e0648d0bee3Behdad Esfahbod  if (HB_DIRECTION_IS_FORWARD (buffer->props.direction)) {
324d345313104d9e3c8a8533ccdebd74e0648d0bee3Behdad Esfahbod    x_offset -= buffer->pos[base].x_advance;
325d345313104d9e3c8a8533ccdebd74e0648d0bee3Behdad Esfahbod    y_offset -= buffer->pos[base].y_advance;
326d345313104d9e3c8a8533ccdebd74e0648d0bee3Behdad Esfahbod  }
327f67917161bbe317a33d6407fbc62ebffcafe7154Behdad Esfahbod
328f67917161bbe317a33d6407fbc62ebffcafe7154Behdad Esfahbod  hb_glyph_extents_t component_extents = base_extents;
329f67917161bbe317a33d6407fbc62ebffcafe7154Behdad Esfahbod  unsigned int last_lig_component = (unsigned int) -1;
33021756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod  unsigned int last_combining_class = 255;
331c26a52fbe62e5ba4d0e1e2ba13bfb6ceb3f773dcBehdad Esfahbod  hb_glyph_extents_t cluster_extents = base_extents; /* Initialization is just to shut gcc up. */
3327cd33f230441093dbfb1fec48f8c580ee8d9ef71Behdad Esfahbod  hb_glyph_info_t *info = buffer->info;
33321756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod  for (unsigned int i = base + 1; i < end; i++)
3347cd33f230441093dbfb1fec48f8c580ee8d9ef71Behdad Esfahbod    if (_hb_glyph_info_get_modified_combining_class (&info[i]))
33521756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    {
336f67917161bbe317a33d6407fbc62ebffcafe7154Behdad Esfahbod      if (num_lig_components > 1) {
3377cd33f230441093dbfb1fec48f8c580ee8d9ef71Behdad Esfahbod	unsigned int this_lig_id = _hb_glyph_info_get_lig_id (&info[i]);
3387cd33f230441093dbfb1fec48f8c580ee8d9ef71Behdad Esfahbod	unsigned int this_lig_component = _hb_glyph_info_get_lig_comp (&info[i]) - 1;
339f67917161bbe317a33d6407fbc62ebffcafe7154Behdad Esfahbod	/* Conditions for attaching to the last component. */
340f67917161bbe317a33d6407fbc62ebffcafe7154Behdad Esfahbod	if (!lig_id || lig_id != this_lig_id || this_lig_component >= num_lig_components)
341f67917161bbe317a33d6407fbc62ebffcafe7154Behdad Esfahbod	  this_lig_component = num_lig_components - 1;
342f67917161bbe317a33d6407fbc62ebffcafe7154Behdad Esfahbod	if (last_lig_component != this_lig_component)
343f67917161bbe317a33d6407fbc62ebffcafe7154Behdad Esfahbod	{
344f67917161bbe317a33d6407fbc62ebffcafe7154Behdad Esfahbod	  last_lig_component = this_lig_component;
345f67917161bbe317a33d6407fbc62ebffcafe7154Behdad Esfahbod	  last_combining_class = 255;
346f67917161bbe317a33d6407fbc62ebffcafe7154Behdad Esfahbod	  component_extents = base_extents;
347f67917161bbe317a33d6407fbc62ebffcafe7154Behdad Esfahbod	  if (unlikely (horiz_dir == HB_DIRECTION_INVALID)) {
348f67917161bbe317a33d6407fbc62ebffcafe7154Behdad Esfahbod	    if (HB_DIRECTION_IS_HORIZONTAL (plan->props.direction))
349f67917161bbe317a33d6407fbc62ebffcafe7154Behdad Esfahbod	      horiz_dir = plan->props.direction;
350f67917161bbe317a33d6407fbc62ebffcafe7154Behdad Esfahbod	    else
351f67917161bbe317a33d6407fbc62ebffcafe7154Behdad Esfahbod	      horiz_dir = hb_script_get_horizontal_direction (plan->props.script);
352f67917161bbe317a33d6407fbc62ebffcafe7154Behdad Esfahbod	  }
353f67917161bbe317a33d6407fbc62ebffcafe7154Behdad Esfahbod	  if (horiz_dir == HB_DIRECTION_LTR)
354f67917161bbe317a33d6407fbc62ebffcafe7154Behdad Esfahbod	    component_extents.x_bearing += (this_lig_component * component_extents.width) / num_lig_components;
355f67917161bbe317a33d6407fbc62ebffcafe7154Behdad Esfahbod	  else
356f67917161bbe317a33d6407fbc62ebffcafe7154Behdad Esfahbod	    component_extents.x_bearing += ((num_lig_components - 1 - this_lig_component) * component_extents.width) / num_lig_components;
357f67917161bbe317a33d6407fbc62ebffcafe7154Behdad Esfahbod	  component_extents.width /= num_lig_components;
358f67917161bbe317a33d6407fbc62ebffcafe7154Behdad Esfahbod	}
359f67917161bbe317a33d6407fbc62ebffcafe7154Behdad Esfahbod      }
360f67917161bbe317a33d6407fbc62ebffcafe7154Behdad Esfahbod
3617cd33f230441093dbfb1fec48f8c580ee8d9ef71Behdad Esfahbod      unsigned int this_combining_class = _hb_glyph_info_get_modified_combining_class (&info[i]);
362f67917161bbe317a33d6407fbc62ebffcafe7154Behdad Esfahbod      if (last_combining_class != this_combining_class)
363f67917161bbe317a33d6407fbc62ebffcafe7154Behdad Esfahbod      {
364f67917161bbe317a33d6407fbc62ebffcafe7154Behdad Esfahbod	last_combining_class = this_combining_class;
365f67917161bbe317a33d6407fbc62ebffcafe7154Behdad Esfahbod        cluster_extents = component_extents;
366f67917161bbe317a33d6407fbc62ebffcafe7154Behdad Esfahbod      }
36721756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod
368667218a5b134728863a318c73070f4e323590bbdBehdad Esfahbod      position_mark (plan, font, buffer, cluster_extents, i, this_combining_class);
36921756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod
37021756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod      buffer->pos[i].x_advance = 0;
37121756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod      buffer->pos[i].y_advance = 0;
37221756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod      buffer->pos[i].x_offset += x_offset;
37321756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod      buffer->pos[i].y_offset += y_offset;
37421756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod
37521756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    } else {
376d345313104d9e3c8a8533ccdebd74e0648d0bee3Behdad Esfahbod      if (HB_DIRECTION_IS_FORWARD (buffer->props.direction)) {
377d345313104d9e3c8a8533ccdebd74e0648d0bee3Behdad Esfahbod	x_offset -= buffer->pos[i].x_advance;
378d345313104d9e3c8a8533ccdebd74e0648d0bee3Behdad Esfahbod	y_offset -= buffer->pos[i].y_advance;
379d345313104d9e3c8a8533ccdebd74e0648d0bee3Behdad Esfahbod      } else {
380d345313104d9e3c8a8533ccdebd74e0648d0bee3Behdad Esfahbod	x_offset += buffer->pos[i].x_advance;
381d345313104d9e3c8a8533ccdebd74e0648d0bee3Behdad Esfahbod	y_offset += buffer->pos[i].y_advance;
382d345313104d9e3c8a8533ccdebd74e0648d0bee3Behdad Esfahbod      }
38321756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    }
38421756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod}
38521756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod
38621756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbodstatic inline void
38721756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbodposition_cluster (const hb_ot_shape_plan_t *plan,
38821756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod		  hb_font_t *font,
38921756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod		  hb_buffer_t  *buffer,
39021756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod		  unsigned int start,
39121756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod		  unsigned int end)
39221756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod{
39321756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod  if (end - start < 2)
39421756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    return;
39521756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod
39621756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod  /* Find the base glyph */
3977cd33f230441093dbfb1fec48f8c580ee8d9ef71Behdad Esfahbod  hb_glyph_info_t *info = buffer->info;
39821756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod  for (unsigned int i = start; i < end; i++)
3997cd33f230441093dbfb1fec48f8c580ee8d9ef71Behdad Esfahbod    if (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i])))
40021756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    {
401525c6855783a018d52867b9ece2ee90868ff1f91Behdad Esfahbod      /* Find mark glyphs */
402525c6855783a018d52867b9ece2ee90868ff1f91Behdad Esfahbod      unsigned int j;
403525c6855783a018d52867b9ece2ee90868ff1f91Behdad Esfahbod      for (j = i + 1; j < end; j++)
4047cd33f230441093dbfb1fec48f8c580ee8d9ef71Behdad Esfahbod	if (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[j])))
405525c6855783a018d52867b9ece2ee90868ff1f91Behdad Esfahbod	  break;
406525c6855783a018d52867b9ece2ee90868ff1f91Behdad Esfahbod
407525c6855783a018d52867b9ece2ee90868ff1f91Behdad Esfahbod      position_around_base (plan, font, buffer, i, j);
408525c6855783a018d52867b9ece2ee90868ff1f91Behdad Esfahbod
409525c6855783a018d52867b9ece2ee90868ff1f91Behdad Esfahbod      i = j - 1;
41021756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    }
41121756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod}
41221756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod
413affaf8a0e5aa38e5820455f789eebf916e02eb7bBehdad Esfahbodvoid
4149c929abdcfef44c0193a2917b20981df37ade21cBehdad Esfahbod_hb_ot_shape_fallback_position (const hb_ot_shape_plan_t *plan,
415affaf8a0e5aa38e5820455f789eebf916e02eb7bBehdad Esfahbod				hb_font_t *font,
416affaf8a0e5aa38e5820455f789eebf916e02eb7bBehdad Esfahbod				hb_buffer_t  *buffer)
417affaf8a0e5aa38e5820455f789eebf916e02eb7bBehdad Esfahbod{
4188f3eebf7ee4005f9a8efaafcb7f4058cc0a3756eBehdad Esfahbod  _hb_buffer_assert_gsubgpos_vars (buffer);
4198f3eebf7ee4005f9a8efaafcb7f4058cc0a3756eBehdad Esfahbod
42021756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod  unsigned int start = 0;
42121756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod  unsigned int last_cluster = buffer->info[0].cluster;
42221756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod  unsigned int count = buffer->len;
42321756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod  for (unsigned int i = 1; i < count; i++)
42421756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    if (buffer->info[i].cluster != last_cluster) {
42521756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod      position_cluster (plan, font, buffer, start, i);
42621756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod      start = i;
42721756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod      last_cluster = buffer->info[i].cluster;
42821756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod    }
42921756934a15e31dc243e2b6d80adec5752477652Behdad Esfahbod  position_cluster (plan, font, buffer, start, count);
430affaf8a0e5aa38e5820455f789eebf916e02eb7bBehdad Esfahbod}
431ba87b8fc89bf745068ccd19264a2631ea0904846Behdad Esfahbod
432ba87b8fc89bf745068ccd19264a2631ea0904846Behdad Esfahbod
433ba87b8fc89bf745068ccd19264a2631ea0904846Behdad Esfahbod/* Performs old-style TrueType kerning. */
434ba87b8fc89bf745068ccd19264a2631ea0904846Behdad Esfahbodvoid
435ba87b8fc89bf745068ccd19264a2631ea0904846Behdad Esfahbod_hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan,
436ba87b8fc89bf745068ccd19264a2631ea0904846Behdad Esfahbod			    hb_font_t *font,
437ba87b8fc89bf745068ccd19264a2631ea0904846Behdad Esfahbod			    hb_buffer_t  *buffer)
438ba87b8fc89bf745068ccd19264a2631ea0904846Behdad Esfahbod{
4395497a8a274a7066c0230c850baadef681785c8bbBehdad Esfahbod  if (!plan->has_kern) return;
4406b03e3c724ec6cd255f4a323bf4aa7d8c93a056eBehdad Esfahbod
441bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  OT::hb_apply_context_t c (1, font, buffer);
4425497a8a274a7066c0230c850baadef681785c8bbBehdad Esfahbod  c.set_lookup_mask (plan->kern_mask);
443d46606e119b48dcca375d6313abd0f93ba5d09c3Behdad Esfahbod  c.set_lookup_props (OT::LookupFlag::IgnoreMarks);
444ba87b8fc89bf745068ccd19264a2631ea0904846Behdad Esfahbod
4457cd33f230441093dbfb1fec48f8c580ee8d9ef71Behdad Esfahbod  unsigned int count = buffer->len;
4466b03e3c724ec6cd255f4a323bf4aa7d8c93a056eBehdad Esfahbod  hb_glyph_info_t *info = buffer->info;
4476b03e3c724ec6cd255f4a323bf4aa7d8c93a056eBehdad Esfahbod  hb_glyph_position_t *pos = buffer->pos;
4486b03e3c724ec6cd255f4a323bf4aa7d8c93a056eBehdad Esfahbod  for (unsigned int idx = 0; idx < count;)
449ba87b8fc89bf745068ccd19264a2631ea0904846Behdad Esfahbod  {
4506b03e3c724ec6cd255f4a323bf4aa7d8c93a056eBehdad Esfahbod    OT::hb_apply_context_t::skipping_forward_iterator_t skippy_iter (&c, idx, 1);
451d46606e119b48dcca375d6313abd0f93ba5d09c3Behdad Esfahbod    if (!skippy_iter.next ())
452ba87b8fc89bf745068ccd19264a2631ea0904846Behdad Esfahbod    {
4536b03e3c724ec6cd255f4a323bf4aa7d8c93a056eBehdad Esfahbod      idx++;
454d46606e119b48dcca375d6313abd0f93ba5d09c3Behdad Esfahbod      continue;
455ba87b8fc89bf745068ccd19264a2631ea0904846Behdad Esfahbod    }
456d46606e119b48dcca375d6313abd0f93ba5d09c3Behdad Esfahbod
4576b03e3c724ec6cd255f4a323bf4aa7d8c93a056eBehdad Esfahbod    hb_position_t x_kern, y_kern;
4586b03e3c724ec6cd255f4a323bf4aa7d8c93a056eBehdad Esfahbod    font->get_glyph_kerning_for_direction (info[idx].codepoint,
4596b03e3c724ec6cd255f4a323bf4aa7d8c93a056eBehdad Esfahbod					   info[skippy_iter.idx].codepoint,
460d46606e119b48dcca375d6313abd0f93ba5d09c3Behdad Esfahbod					   buffer->props.direction,
461d46606e119b48dcca375d6313abd0f93ba5d09c3Behdad Esfahbod					   &x_kern, &y_kern);
462d46606e119b48dcca375d6313abd0f93ba5d09c3Behdad Esfahbod
4636b03e3c724ec6cd255f4a323bf4aa7d8c93a056eBehdad Esfahbod    if (x_kern)
4646b03e3c724ec6cd255f4a323bf4aa7d8c93a056eBehdad Esfahbod    {
4656b03e3c724ec6cd255f4a323bf4aa7d8c93a056eBehdad Esfahbod      hb_position_t kern1 = x_kern >> 1;
4666b03e3c724ec6cd255f4a323bf4aa7d8c93a056eBehdad Esfahbod      hb_position_t kern2 = x_kern - kern1;
4676b03e3c724ec6cd255f4a323bf4aa7d8c93a056eBehdad Esfahbod      pos[idx].x_advance += kern1;
4686b03e3c724ec6cd255f4a323bf4aa7d8c93a056eBehdad Esfahbod      pos[skippy_iter.idx].x_advance += kern2;
4696b03e3c724ec6cd255f4a323bf4aa7d8c93a056eBehdad Esfahbod      pos[skippy_iter.idx].x_offset += kern2;
4706b03e3c724ec6cd255f4a323bf4aa7d8c93a056eBehdad Esfahbod    }
471d46606e119b48dcca375d6313abd0f93ba5d09c3Behdad Esfahbod
4726b03e3c724ec6cd255f4a323bf4aa7d8c93a056eBehdad Esfahbod    if (y_kern)
4736b03e3c724ec6cd255f4a323bf4aa7d8c93a056eBehdad Esfahbod    {
4746b03e3c724ec6cd255f4a323bf4aa7d8c93a056eBehdad Esfahbod      hb_position_t kern1 = y_kern >> 1;
4756b03e3c724ec6cd255f4a323bf4aa7d8c93a056eBehdad Esfahbod      hb_position_t kern2 = y_kern - kern1;
4766b03e3c724ec6cd255f4a323bf4aa7d8c93a056eBehdad Esfahbod      pos[idx].y_advance += kern1;
4776b03e3c724ec6cd255f4a323bf4aa7d8c93a056eBehdad Esfahbod      pos[skippy_iter.idx].y_advance += kern2;
4786b03e3c724ec6cd255f4a323bf4aa7d8c93a056eBehdad Esfahbod      pos[skippy_iter.idx].y_offset += kern2;
4796b03e3c724ec6cd255f4a323bf4aa7d8c93a056eBehdad Esfahbod    }
480d46606e119b48dcca375d6313abd0f93ba5d09c3Behdad Esfahbod
4816b03e3c724ec6cd255f4a323bf4aa7d8c93a056eBehdad Esfahbod    idx = skippy_iter.idx;
482ba87b8fc89bf745068ccd19264a2631ea0904846Behdad Esfahbod  }
483ba87b8fc89bf745068ccd19264a2631ea0904846Behdad Esfahbod}
484