Ejemplo n.º 1
0
/* analysis->shape_engine has the PangoEngine... */
static void 
indic_engine_shape (PangoEngineShape *engine,
		    PangoFont        *font,
		    const char       *text,
		    gint              length,
		    const PangoAnalysis *analysis,
		    PangoGlyphString *glyphs)
{
  PangoFcFont *fc_font;
  FT_Face face;
  PangoOTRuleset *gsub_ruleset, *gpos_ruleset;
  PangoOTBuffer *buffer;
  glong i, n_chars, n_glyphs;
  gulong *tags = NULL;
  gunichar *wc_in = NULL, *wc_out = NULL;
  glong *utf8_offsets = NULL;
  glong *indices = NULL;
  IndicEngineFc *indic_shape_engine = NULL;
  const PangoIndicInfo *indic_info = NULL;
  MPreFixups *mprefixups;

  g_return_if_fail (font != NULL);
  g_return_if_fail (text != NULL);
  g_return_if_fail (length >= 0);
  g_return_if_fail (analysis != NULL);

  fc_font = PANGO_FC_FONT (font);
  face = pango_fc_font_lock_face (fc_font);
  if (!face)
    return;

  indic_shape_engine = (IndicEngineFc *) engine;

  indic_info = indic_shape_engine->indicInfo;

  wc_in    = expand_text (text, length, &utf8_offsets, &n_chars);
 
  n_glyphs = indic_ot_reorder (wc_in, utf8_offsets, n_chars, indic_info->classTable, NULL, NULL, NULL, NULL);
  
  wc_out  = g_new (gunichar, n_glyphs);
  indices = g_new (glong,    n_glyphs);
  tags    = g_new (gulong,   n_glyphs);

  n_glyphs  = indic_ot_reorder (wc_in, utf8_offsets, n_chars, indic_info->classTable, wc_out, indices, tags, &mprefixups);
  
  pango_glyph_string_set_size (glyphs, n_glyphs);
  buffer = pango_ot_buffer_new (fc_font);

  set_glyphs(font, wc_out, tags, n_glyphs, buffer,
	     (indic_info->classTable->scriptFlags & SF_PROCESS_ZWJ) != 0);

  /* do gsub processing */
  gsub_ruleset = get_gsub_ruleset (face, indic_info);
  if (gsub_ruleset != NULL)
    pango_ot_ruleset_substitute (gsub_ruleset, buffer);

  /* Fix pre-modifiers for some scripts before base consonant */
  if (mprefixups)
    {
      indic_mprefixups_apply (mprefixups, buffer);
      indic_mprefixups_free (mprefixups);
    }

  /* do gpos processing */
  gpos_ruleset = get_gpos_ruleset (face, indic_info);
  if (gpos_ruleset != NULL)
    pango_ot_ruleset_position (gpos_ruleset, buffer);

  pango_ot_buffer_output (buffer, glyphs);

  /* Get the right log_clusters values */
  for (i = 0; i < glyphs->num_glyphs; i += 1)
    glyphs->log_clusters[i] = indices[glyphs->log_clusters[i]];

  pango_fc_font_unlock_face (fc_font);

  pango_ot_buffer_destroy (buffer);
  g_free (tags);
  g_free (indices);
  g_free (wc_out);
  g_free (wc_in);
  g_free (utf8_offsets);
}
Ejemplo n.º 2
0
static void
tibetan_engine_shape (PangoEngineShape *engine,
                    PangoFont        *font,
                    const char       *text,
                    int               length,
                    const PangoAnalysis *analysis,
                    PangoGlyphString *glyphs)
{
  PangoFcFont *fc_font;
  FT_Face face;
  PangoOTRuleset *ruleset;
  PangoOTBuffer *buffer;
  glong n_chars;
  gunichar *wcs;
  const char *p;
  int i;
  glong syllable;
  TibetanCharClass charClass;
  glong cursor = 0;

  g_return_if_fail (font != NULL);
  g_return_if_fail (text != NULL);
  g_return_if_fail (length >= 0);
  g_return_if_fail (analysis != NULL);

  fc_font = PANGO_FC_FONT (font);
  face = pango_fc_font_lock_face (fc_font);
  if (!face)
    return;

  buffer = pango_ot_buffer_new (fc_font);

  wcs = g_utf8_to_ucs4_fast (text, length, &n_chars);

  p = text;
  /* This loop only exits when we reach the end of a run, which may contain
   * several syllables.
   */
  while (cursor < n_chars)
    {
      syllable = find_syllable (wcs, cursor, n_chars);

      /* shall we add a dotted circle?
      * If in the position in which the base should be (first char in the string) there is
      * a character that has the Dotted circle flag (a character that cannot be a base)
      * then write a dotted circle
      */
      if (get_char_class (wcs[cursor]) & CF_DOTTED_CIRCLE)
        {
          pango_ot_buffer_add_glyph (buffer, get_index (fc_font, C_DOTTED_CIRCLE), default_p, p - text);
        }

      /* If it encounters a digit followed by number pre combining mark, then reorder the two characters
      * coeng Ro if they are present 
      */
      for (i = cursor; i < syllable; i += 1)
        {
          charClass = get_char_class (wcs[i]);

          if ((charClass & CF_DIGIT ) 
              && ( get_char_class (wcs[i+1]) & CF_PREDIGIT))
           {
         		 pango_ot_buffer_add_glyph (buffer, get_index (fc_font, C_PRE_NUMBER_MARK), pref_p, p - text);
         		 p = g_utf8_next_char (p);
         		 pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), pref_p, p - text);
 			       i += 1;          
         } else {
          switch (charClass & CF_POS_MASK)
            {
              case CF_POS_ABOVE :
		             pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), abvf_p, p - text);
		             break;

              case CF_POS_AFTER :
		             pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), pstf_p, p - text);
		             break;
		
              case CF_POS_BELOW :
		             pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), blwf_p, p - text);
		             break;

              default:
                   /* default - any other characters  */
                  pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), default_p, p - text);
                  break;
            } /* switch */
           } 
            
          p = g_utf8_next_char (p);
        } /* for */

      cursor = syllable; /* move the pointer to the start of next syllable */
    } /* while */

  /* do gsub processing */
  ruleset = get_ruleset (face);
  if (ruleset != NULL)
    {
      pango_ot_ruleset_substitute (ruleset, buffer);
      pango_ot_ruleset_position (ruleset, buffer);
    }

  pango_ot_buffer_output (buffer, glyphs);

  g_free (wcs);
  pango_ot_buffer_destroy (buffer);

  pango_fc_font_unlock_face (fc_font);
}
Ejemplo n.º 3
0
static void
khmer_engine_shape (PangoEngineShape *engine,
                    PangoFont        *font,
                    const char       *text,
                    int               length,
                    const PangoAnalysis *analysis,
                    PangoGlyphString *glyphs)
{
  PangoFcFont *fc_font;
  FT_Face face;
  PangoOTRuleset *ruleset;
  PangoOTBuffer *buffer;
  glong n_chars;
  gunichar *wcs;
  const char *p;
  int i;
  glong syllable;
  KhmerCharClass charClass;
  glong cursor = 0;

  g_return_if_fail (font != NULL);
  g_return_if_fail (text != NULL);
  g_return_if_fail (length >= 0);
  g_return_if_fail (analysis != NULL);

  fc_font = PANGO_FC_FONT (font);
  face = pango_fc_font_lock_face (fc_font);
  if (!face)
    return;

  buffer = pango_ot_buffer_new (fc_font);

  wcs = g_utf8_to_ucs4_fast (text, length, &n_chars);

  p = text;
  /* This loop only exits when we reach the end of a run, which may contain
   * several syllables.
   */
  while (cursor < n_chars)
    {
      /* write a pre vowel or the pre part of a split vowel first
       * and look out for coeng + ro. RO is the only vowel of type 2, and
       * therefore the only one that requires saving space before the base.
       */
      glong coengRo = -1;  /* There is no Coeng Ro, if found this value will change */

      syllable = find_syllable (wcs, cursor, n_chars);

      for (i = cursor; i < syllable; i += 1)
        {
          charClass = get_char_class (wcs[i]);

          /* if a split vowel, write the pre part. In Khmer the pre part
           * is the same for all split vowels, same glyph as pre vowel C_VOWEL_E
           */
          if (charClass & CF_SPLIT_VOWEL)
            {
              pango_ot_buffer_add_glyph (buffer, get_index (fc_font, C_VOWEL_E), pref_p, p - text);
              break; /* there can be only one vowel */
            }

          /* if a vowel with pos before write it out */
          if (charClass & CF_POS_BEFORE)
            {
              pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), pref_p, p - text);
              break; /* there can be only one vowel */
            }

          /* look for coeng + ro and remember position
           * works because coeng + ro is always in front of a vowel (if there is a vowel)
           * and because CC_CONSONANT2 is enough to identify it, as it is the only consonant
           * with this flag
           */
          if ((charClass & CF_COENG) && (i + 1 < syllable) &&
             ((get_char_class (wcs[i + 1]) & CF_CLASS_MASK) == CC_CONSONANT2))
            {
              coengRo = i;
            }
        }

      /* write coeng + ro if found  */
      if (coengRo > -1)
        {
          pango_ot_buffer_add_glyph (buffer, get_index (fc_font, C_COENG), pref_p, p - text);
          pango_ot_buffer_add_glyph (buffer, get_index (fc_font, C_RO), pref_p, p - text);
        }

      /* shall we add a dotted circle?
      * If in the position in which the base should be (first char in the string) there is
      * a character that has the Dotted circle flag (a character that cannot be a base)
      * then write a dotted circle
      */
      if (get_char_class (wcs[cursor]) & CF_DOTTED_CIRCLE)
        {
          pango_ot_buffer_add_glyph (buffer, get_index (fc_font, C_DOTTED_CIRCLE), default_p, p - text);
        }

      /* copy what is left to the output, skipping before vowels and
      * coeng Ro if they are present
      */
      for (i = cursor; i < syllable; i += 1)
        {
          charClass = get_char_class (wcs[i]);

          /* skip a before vowel, it was already processed */
          if (charClass & CF_POS_BEFORE)
            {
              p = g_utf8_next_char (p);
              continue;
            }

          /* skip coeng + ro, it was already processed */
          if (i == coengRo)
            {
              p = g_utf8_next_char (p);
              i += 1;
              p = g_utf8_next_char (p);
              continue;
            }

          switch (charClass & CF_POS_MASK)
            {
              case CF_POS_ABOVE :
		pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), abvf_p, p - text);
		break;

              case CF_POS_AFTER :
		pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), pstf_p, p - text);
		break;
		
              case CF_POS_BELOW :
		pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), blwf_p, p - text);
		break;

              default:
                  /* assign the correct flags to a coeng consonant
                  * Consonants of type 3 are taged as Post forms and those type 1 as below forms
                  */
		if ((charClass & CF_COENG) && i + 1 < syllable)
		  {
		    if ((get_char_class (wcs[i + 1]) & CF_CLASS_MASK) == CC_CONSONANT3)
		      {
			pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), pstf_p, p - text);
			p = g_utf8_next_char (p);
			i += 1;
			pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), pstf_p, p - text);
			break;
		      }
		    else
		      {
			pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), blwf_p, p - text);
			p = g_utf8_next_char (p);
			i += 1;
			pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), blwf_p, p - text);
			break;
		      }
		  }

                  /* if a shifter is followed by an above vowel change the shifter to below form,
                  * an above vowel can have two possible positions i + 1 or i + 3
                  * (position i+1 corresponds to unicode 3, position i+3 to Unicode 4)
                  * and there is an extra rule for C_VOWEL_AA + C_SIGN_NIKAHIT also for two
                  * different positions, right after the shifter or after a vowel (Unicode 4)
                  */
                  if ((charClass & CF_SHIFTER) && (i + 1 < syllable))
                    {
                      if (get_char_class (wcs[i + 1]) & CF_ABOVE_VOWEL)
                        {
                          pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), blwf_p, p - text);
                          break;
                        }
                      if (i + 2 < syllable &&
                          (wcs[i + 1] == C_VOWEL_AA) &&
                          (wcs[i + 2] == C_SIGN_NIKAHIT) )
                        {
                          pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), blwf_p, p - text);
                          break;
                        }
                      if (i + 3 < syllable && (get_char_class (wcs[i + 3]) & CF_ABOVE_VOWEL) )
                        {
                          pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), blwf_p, p - text);
                          break;
                        }
                      if (i + 4 < syllable &&
                          (wcs[i + 3] == C_VOWEL_AA) &&
                          (wcs[i + 4] == C_SIGN_NIKAHIT) )
                        {
                          pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), blwf_p, p - text);
                          break;
                        }

                    }

                  /* default - any other characters  */
                  pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), default_p, p - text);
                  break;
            } /* switch */
          p = g_utf8_next_char (p);
        } /* for */

      cursor = syllable; /* move the pointer to the start of next syllable */
    } /* while */

  /* do gsub processing */
  ruleset = get_ruleset (face);
  if (ruleset != NULL)
    {
      pango_ot_ruleset_substitute (ruleset, buffer);
      pango_ot_ruleset_position (ruleset, buffer);
    }

  pango_ot_buffer_output (buffer, glyphs);

  g_free (wcs);
  pango_ot_buffer_destroy (buffer);

  pango_fc_font_unlock_face (fc_font);
}
Ejemplo n.º 4
0
static void
syriac_engine_shape (PangoEngineShape *engine,
		     PangoFont        *font,
		     const char       *text,
		     gint              length,
		     const PangoAnalysis *analysis,
		     PangoGlyphString *glyphs)
{
  PangoFcFont *fc_font;
  FT_Face face;
  PangoOTRulesetDescription desc;
  const PangoOTRuleset *ruleset;
  PangoOTBuffer *buffer;
  gulong *properties = NULL;
  glong n_chars;
  gunichar *wcs;
  const char *p;
  int cluster = 0;
  int i;

  g_return_if_fail (font != NULL);
  g_return_if_fail (text != NULL);
  g_return_if_fail (length >= 0);
  g_return_if_fail (analysis != NULL);

  fc_font = PANGO_FC_FONT (font);
  face = pango_fc_font_lock_face (fc_font);
  if (!face)
    return;

  buffer = pango_ot_buffer_new (fc_font);
  pango_ot_buffer_set_rtl (buffer, analysis->level % 2 != 0);
  pango_ot_buffer_set_zero_width_marks (buffer, TRUE);

  wcs = g_utf8_to_ucs4_fast (text, length, &n_chars);
  properties = g_new0 (gulong, n_chars);

  syriac_assign_properties (wcs, properties, n_chars);

  g_free (wcs);

  p = text;
  for (i=0; i < n_chars; i++)
    {
      gunichar wc;
      PangoGlyph glyph;

      wc = g_utf8_get_char (p);

      if (g_unichar_type (wc) != G_UNICODE_NON_SPACING_MARK)
	cluster = p - text;

      if (pango_is_zero_width (wc))
        glyph = PANGO_GLYPH_EMPTY;
      else
        {
	  gunichar c = wc;

	  if (analysis->level % 2)
	    g_unichar_get_mirror_char (c, &c);

	  glyph = pango_fc_font_get_glyph (fc_font, c);
	}

      if (!glyph)
	glyph = PANGO_GET_UNKNOWN_GLYPH (wc);

      pango_ot_buffer_add_glyph (buffer, glyph, properties[i], cluster);

      p = g_utf8_next_char (p);
    }

  g_free (properties);

  desc.script = analysis->script;
  desc.language = analysis->language;

  desc.n_static_gsub_features = G_N_ELEMENTS (gsub_features);
  desc.static_gsub_features = gsub_features;
  desc.n_static_gpos_features = G_N_ELEMENTS (gpos_features);
  desc.static_gpos_features = gpos_features;

  /* TODO populate other_features from analysis->extra_attrs */
  desc.n_other_features = 0;
  desc.other_features = NULL;

  ruleset = pango_ot_ruleset_get_for_description (pango_ot_info_get (face), &desc);

  pango_ot_ruleset_substitute (ruleset, buffer);
  pango_ot_ruleset_position (ruleset, buffer);
  pango_ot_buffer_output (buffer, glyphs);

  pango_ot_buffer_destroy (buffer);

  pango_fc_font_unlock_face (fc_font);
}