Ejemplo n.º 1
0
int PangoFontInfo::DropUncoveredChars(string* utf8_text) const {
  PangoFont* font = ToPangoFont();
  PangoCoverage* coverage = pango_font_get_coverage(font, NULL);
  int num_dropped_chars = 0;
  // Maintain two iterators that point into the string. For space efficiency, we
  // will repeatedly copy one covered UTF8 character from one to the other, and
  // at the end resize the string to the right length.
  char* out = const_cast<char*>(utf8_text->c_str());
  const UNICHAR::const_iterator it_begin =
      UNICHAR::begin(utf8_text->c_str(), utf8_text->length());
  const UNICHAR::const_iterator it_end =
      UNICHAR::end(utf8_text->c_str(), utf8_text->length());
  for (UNICHAR::const_iterator it = it_begin; it != it_end; ++it) {
    // Skip bad utf-8.
    if (!it.is_legal())
      continue;  // One suitable error message will still be issued.
    if (!IsWhitespace(*it) && !pango_is_zero_width(*it) &&
        pango_coverage_get(coverage, *it) != PANGO_COVERAGE_EXACT) {
      if (TLOG_IS_ON(2)) {
        char tmp[5];
        int len = it.get_utf8(tmp);
        tmp[len] = '\0';
        tlog(2, "'%s' (U+%x) not covered by font\n", tmp, *it);
      }
      ++num_dropped_chars;
      continue;
    }
    strncpy(out, it.utf8_data(), it.utf8_len());
    out += it.utf8_len();
  }
  utf8_text->resize(out - utf8_text->c_str());
  return num_dropped_chars;
}
Ejemplo n.º 2
0
static void
set_glyphs (PangoFont      *font,
	    const gunichar *wcs,
	    gulong         *tags,
	    glong           n_glyphs,
	    PangoOTBuffer  *buffer,
	    gboolean        process_zwj)
{
  gint i;
  PangoFcFont *fc_font;

  g_assert (font);

  fc_font = PANGO_FC_FONT (font);

  for (i = 0; i < n_glyphs; i++)
    {
      guint glyph;

      if (pango_is_zero_width (wcs[i]) &&
	  (!process_zwj || wcs[i] != 0x200D))
	glyph = PANGO_GLYPH_EMPTY;
      else
        {
	  glyph = pango_fc_font_get_glyph (fc_font, wcs[i]);

	  if (!glyph)
	    glyph = PANGO_GET_UNKNOWN_GLYPH ( wcs[i]);
	}
      pango_ot_buffer_add_glyph (buffer, glyph, tags[i], i);
    }
}
Ejemplo n.º 3
0
bool PangoFontInfo::CoversUTF8Text(const char* utf8_text, int byte_length) const {
  PangoFont* font = ToPangoFont();
  PangoCoverage* coverage = pango_font_get_coverage(font, NULL);
  for (UNICHAR::const_iterator it = UNICHAR::begin(utf8_text, byte_length);
       it != UNICHAR::end(utf8_text, byte_length);
       ++it) {
    if (IsWhitespace(*it) || pango_is_zero_width(*it))
      continue;
    if (pango_coverage_get(coverage, *it) != PANGO_COVERAGE_EXACT) {
      char tmp[5];
      int len = it.get_utf8(tmp);
      tmp[len] = '\0';
      tlog(2, "'%s' (U+%x) not covered by font\n", tmp, *it);
      return false;
    }
  }
  return true;
}
Ejemplo n.º 4
0
static void
render_basic (PangoFont *font, gunichar wc,
	      PangoGlyphString *glyphs, int *n_glyphs, int cluster_offset)
{
  int index;

  if (wc == 0xa0)	/* non-break-space */
    wc = 0x20;

  pango_glyph_string_set_size (glyphs, *n_glyphs + 1);

  if (pango_is_zero_width (wc))
    set_glyph (font, glyphs, *n_glyphs, cluster_offset, PANGO_GLYPH_EMPTY);
  else
    {
      index = find_char (font, wc);
      if (index)
	set_glyph (font, glyphs, *n_glyphs, cluster_offset, index);
      else
	set_glyph (font, glyphs, *n_glyphs, cluster_offset, get_unknown_glyph (font, wc));
    }
  (*n_glyphs)++;
}
Ejemplo n.º 5
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);
}
Ejemplo n.º 6
0
static void
basic_engine_shape (PangoEngineShape *engine,
                    PangoFont        *font,
                    const char       *text,
                    gint              length,
                    PangoAnalysis    *analysis,
                    PangoGlyphString *glyphs)
{
    int n_chars;
    int i;
    const char *p;

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

#ifdef HAVE_USP10_H

    if (have_uniscribe &&
            !text_is_simple (text, length) &&
            uniscribe_shape (font, text, length, analysis, glyphs))
        return;

#endif

    n_chars = g_utf8_strlen (text, length);

    pango_glyph_string_set_size (glyphs, n_chars);

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

        wc = g_utf8_get_char (p);

        if (analysis->level % 2)
            if (pango_get_mirror_char (wc, &mirrored_ch))
                wc = mirrored_ch;

        if (wc == 0xa0)	/* non-break-space */
            wc = 0x20;

        if (pango_is_zero_width (wc))
        {
            set_glyph (font, glyphs, i, p - text, PANGO_GLYPH_EMPTY);
        }
        else
        {
            index = find_char (font, wc);
            if (index)
            {
                set_glyph (font, glyphs, i, p - text, index);

                if (g_unichar_type (wc) == G_UNICODE_NON_SPACING_MARK)
                {
                    if (i > 0)
                    {
                        PangoRectangle logical_rect, ink_rect;

                        glyphs->glyphs[i].geometry.width = MAX (glyphs->glyphs[i-1].geometry.width,
                                                                glyphs->glyphs[i].geometry.width);
                        glyphs->glyphs[i-1].geometry.width = 0;
                        glyphs->log_clusters[i] = glyphs->log_clusters[i-1];

                        /* Some heuristics to try to guess how overstrike glyphs are
                         * done and compensate
                         */
                        /* FIXME: (alex) Is this double call to get_glyph_extents really necessary? */
                        pango_font_get_glyph_extents (font, glyphs->glyphs[i].glyph, &ink_rect, &logical_rect);
                        if (logical_rect.width == 0 && ink_rect.x == 0)
                            glyphs->glyphs[i].geometry.x_offset = (glyphs->glyphs[i].geometry.width - ink_rect.width) / 2;
                    }
                }
            }
            else
                set_glyph (font, glyphs, i, p - text, PANGO_GET_UNKNOWN_GLYPH (wc));
        }

        p = g_utf8_next_char (p);
    }

    /* Simple bidi support... may have separate modules later */

    if (analysis->level % 2)
    {
        int start, end;

        /* Swap all glyphs */
        swap_range (glyphs, 0, n_chars);

        /* Now reorder glyphs within each cluster back to LTR */
        for (start = 0; start < n_chars;)
        {
            end = start;
            while (end < n_chars &&
                    glyphs->log_clusters[end] == glyphs->log_clusters[start])
                end++;

            swap_range (glyphs, start, end);
            start = end;
        }
    }
}
Ejemplo n.º 7
0
static void
basic_engine_shape (PangoEngineShape    *engine,
		    PangoFont           *font,
		    const char          *text,
		    gint                 length,
		    const PangoAnalysis *analysis,
		    PangoGlyphString    *glyphs)
{
  const char *p;
  char *copy;
  CTLineRef line;
  CFStringRef cstr;
  CFDictionaryRef attributes;
  CFAttributedStringRef attstr;
  PangoCoreTextFont *cfont = PANGO_CORE_TEXT_FONT (font);
  PangoCoverage *coverage;
  CFArrayRef runs;
  CTRunRef run;
  CTRunStatus run_status;
  CFIndex i, glyph_count;
  const CGGlyph *cgglyphs;

  CFTypeRef keys[] = {
      (CFTypeRef) kCTFontAttributeName
  };

  CFTypeRef values[] = {
      pango_core_text_font_get_ctfont (cfont)
  };

  attributes = CFDictionaryCreate (kCFAllocatorDefault,
                                   (const void **)keys,
                                   (const void **)values,
                                   1,
                                   &kCFCopyStringDictionaryKeyCallBacks,
                                   &kCFTypeDictionaryValueCallBacks);

  copy = g_strndup (text, length + 1);
  copy[length] = 0;

  cstr = CFStringCreateWithCString (kCFAllocatorDefault, copy,
                                    kCFStringEncodingUTF8);
  g_free (copy);

  attstr = CFAttributedStringCreate (kCFAllocatorDefault,
                                     cstr,
                                     attributes);

  line = CTLineCreateWithAttributedString (attstr);

  runs = CTLineGetGlyphRuns (line);

  /* Since Pango divides things into runs already, we assume there is
   * only a single run in this line.
   */
  run = CFArrayGetValueAtIndex (runs, 0);
  run_status = CTRunGetStatus (run);
  glyph_count = CTRunGetGlyphCount (run);
  cgglyphs = CTRunGetGlyphsPtr (run);

  p = text;
  pango_glyph_string_set_size (glyphs, glyph_count);
  coverage = pango_font_get_coverage (PANGO_FONT (cfont),
                                      analysis->language);

  for (i = 0; i < glyph_count; i++)
    {
      CFIndex real_i, prev_i;
      gunichar wc;
      gunichar mirrored_ch;

      wc = g_utf8_get_char (p);

      if (analysis->level % 2)
	if (pango_get_mirror_char (wc, &mirrored_ch))
	  wc = mirrored_ch;

      if (run_status & kCTRunStatusRightToLeft)
        {
          real_i = glyph_count - i - 1;
          prev_i = real_i + 1;
        }
      else
        {
          real_i = i;
          prev_i = real_i - 1;
        }

      if (wc == 0xa0)	/* non-break-space */
	wc = 0x20;

      if (pango_is_zero_width (wc))
	{
	  set_glyph (font, glyphs, real_i, p - text, PANGO_GLYPH_EMPTY);
	}
      else
	{
          PangoCoverageLevel result;

          result = pango_coverage_get (coverage, wc);

          if (result != PANGO_COVERAGE_NONE)
            {
              set_glyph (font, glyphs, real_i, p - text, cgglyphs[real_i]);

              if (g_unichar_type (wc) == G_UNICODE_NON_SPACING_MARK)
                {
                  if (i > 0)
                    {
                      PangoRectangle logical_rect, ink_rect;

                      glyphs->glyphs[real_i].geometry.width = MAX (glyphs->glyphs[prev_i].geometry.width,
                                                                   glyphs->glyphs[prev_i].geometry.width);
                      glyphs->glyphs[prev_i].geometry.width = 0;
                      glyphs->log_clusters[real_i] = glyphs->log_clusters[prev_i];

                      /* Some heuristics to try to guess how overstrike glyphs are
                       * done and compensate
                       */
                      pango_font_get_glyph_extents (font, glyphs->glyphs[real_i].glyph, &ink_rect, &logical_rect);
                      if (logical_rect.width == 0 && ink_rect.x == 0)
                        glyphs->glyphs[real_i].geometry.x_offset = (glyphs->glyphs[real_i].geometry.width - ink_rect.width) / 2;
                    }
                }
            }
          else
            {
              set_glyph (font, glyphs, real_i, p - text,
                         PANGO_GET_UNKNOWN_GLYPH (wc));
            }
        }

      p = g_utf8_next_char (p);
    }

  CFRelease (line);
  CFRelease (attstr);
  CFRelease (cstr);
  CFRelease (attributes);
  pango_coverage_unref (coverage);
}