Exemple #1
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);
    }
}
Exemple #2
0
static PangoGlyph
get_index (PangoFcFont *fc_font, gunichar wc)
{
	PangoGlyph index = pango_fc_font_get_glyph (fc_font, wc);
	if (!index)
		index = pango_fc_font_get_unknown_glyph (fc_font, wc);
	return index;
}
Exemple #3
0
static PangoGlyph
get_index (PangoFcFont *fc_font, gunichar wc)
{
  PangoGlyph index = pango_fc_font_get_glyph (fc_font, wc);
  if (!index)
    index = PANGO_GET_UNKNOWN_GLYPH ( wc);
  return index;
}
Exemple #4
0
PangoGlyph
thai_make_glyph_uni (ThaiFontInfo *font_info, gunichar uc)
{
  PangoGlyph result;
  PangoFcFont *fc_font = (PangoFcFont *)font_info->font;

  result = pango_fc_font_get_glyph (fc_font, uc);
  if (result)
    return result;
  else
    return PANGO_GET_UNKNOWN_GLYPH ( uc);
}
bool PangoFontInfo::GetSpacingProperties(const string& utf8_char,
                                         int* x_bearing, int* x_advance) const {
  // Convert to equivalent PangoFont structure
  PangoFont* font = ToPangoFont();
  // Find the glyph index in the font for the supplied utf8 character.
  int total_advance = 0;
  int min_bearing = 0;
  // Handle multi-unicode strings by reporting the left-most position of the
  // x-bearing, and right-most position of the x-advance if the string were to
  // be rendered.
  const UNICHAR::const_iterator it_begin = UNICHAR::begin(utf8_char.c_str(),
                                                          utf8_char.length());
  const UNICHAR::const_iterator it_end = UNICHAR::end(utf8_char.c_str(),
                                                      utf8_char.length());
  for (UNICHAR::const_iterator it = it_begin; it != it_end; ++it) {
    PangoGlyph glyph_index = pango_fc_font_get_glyph(
        reinterpret_cast<PangoFcFont*>(font), *it);
    if (!glyph_index) {
      // Glyph for given unicode character doesn't exist in font.
      return false;
    }
    // Find the ink glyph extents for the glyph
    PangoRectangle ink_rect, logical_rect;
    pango_font_get_glyph_extents(font, glyph_index, &ink_rect, &logical_rect);
    pango_extents_to_pixels(&ink_rect, NULL);
    pango_extents_to_pixels(&logical_rect, NULL);

    int bearing = total_advance + PANGO_LBEARING(ink_rect);
    if (it == it_begin || bearing < min_bearing) {
      min_bearing = bearing;
    }
    total_advance += PANGO_RBEARING(logical_rect);
  }
  *x_bearing = min_bearing;
  *x_advance = total_advance;
  return true;
}
JNIEXPORT void JNICALL 
Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getGlyphs
  (JNIEnv *env, jobject obj, jintArray codepoints, jintArray glyphs,
   jlongArray fonts)
{
  PangoFcFont *default_font, *current_font;
  PangoFontset *pfs;
  jint *cpvals;
  jint length;
  int i;

  /* Set up default font and fontset */
  default_font = getFont(env, obj);
  current_font = default_font;
  pfs = getFontSet(env, obj);

  /* Retrieve string information */
  length = (*env)->GetArrayLength (env, codepoints);
  cpvals = (*env)->GetIntArrayElements (env, codepoints, NULL);
  
  jint *glyphArray = (*env)->GetIntArrayElements (env, glyphs, NULL);
  jlong *fontArray = (*env)->GetLongArrayElements (env, fonts, NULL);

  /* A design goal of Pango is to be threadsafe, but it's admitted that it is
   * not actually threadsafe at the moment.  Using gdk locking here to be safe,
   * but I don't know if if actually helps at all... */ 
  gdk_threads_enter();

  for( i = 0; i < length; i++ )
  {
  	/* Ensure the current font has the requested character; if it doesn't,
  	 * try the default font before pulling a new font out of the fontset.
  	 * Once chosen, a font will be used until a character not in the font is
  	 * encountered. */ 
  	if (!pango_fc_font_has_char(current_font, cpvals[i]))
  	  {
  	    if (pango_fc_font_has_char(default_font, cpvals[i]))
  	      {
  	        current_font = default_font;
            g_object_ref(current_font);
  	      }
  	    else
  	      {
  	        current_font = (PangoFcFont*)pango_fontset_get_font(pfs, cpvals[i]);
  	      }
  	  }
  	else
      {
        g_object_ref(current_font);
      }
  	
  	/* Get glyph, and store both glyph and pointer to font */
    glyphArray[i] = (int)pango_fc_font_get_glyph(current_font,
                                                 (gunichar)cpvals[i]);
    fontArray[i] = PTR_TO_JLONG(current_font);
  }
  
  gdk_threads_leave();

  (*env)->ReleaseIntArrayElements (env, glyphs, glyphArray, 0);
  (*env)->ReleaseIntArrayElements (env, codepoints, cpvals, 0);
  (*env)->ReleaseLongArrayElements (env, fonts, fontArray, 0);
}
Exemple #7
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);
}
Exemple #8
0
TGlyphInfo *glyph_cache_get_info(TGlyphCache *cache, gunichar glyph) {
	TGlyphInfo *gfi;
	XftFont *xftfont;
	PangoFont *font;
	PangoGlyph pglyph;
	PangoRectangle ink, logical;
	gint ascent, descent;
	gint x_offset;
	gint nominal_width;
	double scale_y, scale_x;

	if (!cache->hash)
		return NULL;

	gfi = g_hash_table_lookup(cache->hash, GINT_TO_POINTER(glyph));
	if (gfi)
		return gfi;

	font = pango_fontset_get_font(cache->font_set, glyph);

	pglyph = pango_fc_font_get_glyph(PANGO_FC_FONT(font), glyph);
	if (!pglyph) {
		fprintf (stderr, "Error: Unable to find glyph %d.\n", glyph);
		if (!pglyph)
			pglyph = pango_fc_font_get_glyph(PANGO_FC_FONT(font), glyph);
		if (!pglyph)
			pglyph = PANGO_GET_UNKNOWN_GLYPH (glyph);
		if (!pglyph)
			return NULL;
	}
	pango_font_get_glyph_extents(font, pglyph, &ink, &logical);

	ascent = PANGO_ASCENT(logical);
	descent = PANGO_DESCENT(logical);

	xftfont = pango_xft_font_get_font(font);

	x_offset = 0;

	nominal_width = cache->width;
	if (g_unichar_iswide(glyph))
		nominal_width *= 2;

	scale_x = scale_y = 1.0;

	if (logical.width > nominal_width) {
		if (logical.width)
			scale_x = (double)nominal_width / (double)logical.width;
		else
			scale_x = 1.0;
	}

	if (logical.height != cache->height) {
		double scale;

		if (ascent) {
			scale_y = (double)cache->ascent / (double)ascent;
		} else {
			scale_y = 1.0;
		}
		if (descent) {
			scale = (double)cache->descent / (double)descent;
			if (scale < scale_y)
				scale_y = scale;
		}
	}

	if (scale_x >= 1.0) {
		scale_x = 1.0;
		x_offset += (nominal_width - logical.width) / 2;
	}

	if (scale_x < 1.0 || scale_y != 1.0) {
		FcBool scalable;

		FcPatternGetBool(xftfont->pattern, FC_SCALABLE, 0, &scalable);
		if (!scalable) {
			/* Bah. Need better handling of non-scalable fonts */
			if (scale_x < 1.0) scale_x = 1.0;
			scale_y = 1.0;
		} else if (scale_x < 1.0 || scale_y != 1.0) {
			FcPattern *pattern;
			FcMatrix mat;

			pattern = FcPatternDuplicate(xftfont->pattern);

			FcMatrixInit (&mat);

			FcMatrixScale(&mat, scale_x, scale_y);

			FcPatternDel (pattern, FC_MATRIX);
			FcPatternAddMatrix(pattern, FC_MATRIX, &mat);

			xftfont = XftFontOpenPattern(
				GDK_DISPLAY_XDISPLAY(cache->display),
				pattern
			);
		}

		ascent = ascent * scale_y;
	}

	g_object_unref(font);

//	gfi = calloc(sizeof(TGlyphInfo), 1);
	gfi = g_slice_new(TGlyphInfo);
	gfi->font = xftfont;

	gfi->x_offset = PANGO_PIXELS(x_offset);

	gfi->y_offset = cache->ascent + (cache->ascent - ascent);
	gfi->y_offset = PANGO_PIXELS(gfi->y_offset);

	g_hash_table_insert(cache->hash, GINT_TO_POINTER(glyph), gfi);

	return gfi;
}
Exemple #9
0
PangoGlyph
thai_get_glyph_uni (ThaiFontInfo *font_info, gunichar uc)
{
  return pango_fc_font_get_glyph ((PangoFcFont *)font_info->font, uc);
}
Exemple #10
0
bool PangoFontInfo::CanRenderString(const char* utf8_word, int len,
                                    vector<string>* graphemes) const {
  if (graphemes) graphemes->clear();
  // We check for font coverage of the text first, as otherwise Pango could
  // (undesirably) fall back to another font that does have the required
  // coverage.
  if (!CoversUTF8Text(utf8_word, len)) {
    return false;
  }
  // U+25CC dotted circle character that often (but not always) gets rendered
  // when there is an illegal grapheme sequence.
  const char32 kDottedCircleGlyph = 9676;
  bool bad_glyph = false;
  PangoFontMap* font_map = pango_cairo_font_map_get_default();
  PangoContext* context = pango_context_new();
  pango_context_set_font_map(context, font_map);
  PangoLayout* layout;
  {
    // Pango is not relasing the cached layout.
    DISABLE_HEAP_LEAK_CHECK;
    layout = pango_layout_new(context);
  }
  if (desc_) {
    pango_layout_set_font_description(layout, desc_);
  } else {
    PangoFontDescription *desc = pango_font_description_from_string(
        DescriptionName().c_str());
    pango_layout_set_font_description(layout, desc);
    pango_font_description_free(desc);
  }
  pango_layout_set_text(layout, utf8_word, len);
  PangoLayoutIter* run_iter = NULL;
  { // Fontconfig caches some information here that is not freed before exit.
    DISABLE_HEAP_LEAK_CHECK;
    run_iter = pango_layout_get_iter(layout);
  }
  do {
    PangoLayoutRun* run = pango_layout_iter_get_run_readonly(run_iter);
    if (!run) {
      tlog(2, "Found end of line NULL run marker\n");
      continue;
    }
    PangoGlyph dotted_circle_glyph;
    PangoFont* font = run->item->analysis.font;
    dotted_circle_glyph = pango_fc_font_get_glyph(
        reinterpret_cast<PangoFcFont*>(font), kDottedCircleGlyph);
    if (TLOG_IS_ON(2)) {
      PangoFontDescription* desc = pango_font_describe(font);
      char* desc_str = pango_font_description_to_string(desc);
      tlog(2, "Desc of font in run: %s\n", desc_str);
      g_free(desc_str);
      pango_font_description_free(desc);
    }

    PangoGlyphItemIter cluster_iter;
    gboolean have_cluster;
    for (have_cluster = pango_glyph_item_iter_init_start(&cluster_iter,
                                                         run, utf8_word);
         have_cluster && !bad_glyph;
         have_cluster = pango_glyph_item_iter_next_cluster(&cluster_iter)) {
      const int start_byte_index = cluster_iter.start_index;
      const int end_byte_index = cluster_iter.end_index;
      int start_glyph_index = cluster_iter.start_glyph;
      int end_glyph_index = cluster_iter.end_glyph;
      string cluster_text = string(utf8_word + start_byte_index,
                                   end_byte_index - start_byte_index);
      if (graphemes) graphemes->push_back(cluster_text);
      if (IsUTF8Whitespace(cluster_text.c_str())) {
        tlog(2, "Skipping whitespace\n");
        continue;
      }
      if (TLOG_IS_ON(2)) {
        printf("start_byte=%d end_byte=%d start_glyph=%d end_glyph=%d ",
               start_byte_index, end_byte_index,
               start_glyph_index, end_glyph_index);
      }
      for (int i = start_glyph_index,
               step = (end_glyph_index > start_glyph_index) ? 1 : -1;
           !bad_glyph && i != end_glyph_index; i+= step) {
        const bool unknown_glyph =
            (cluster_iter.glyph_item->glyphs->glyphs[i].glyph &
             PANGO_GLYPH_UNKNOWN_FLAG);
        const bool illegal_glyph =
            (cluster_iter.glyph_item->glyphs->glyphs[i].glyph ==
             dotted_circle_glyph);
        bad_glyph = unknown_glyph || illegal_glyph;
        if (TLOG_IS_ON(2)) {
          printf("(%d=%d)", cluster_iter.glyph_item->glyphs->glyphs[i].glyph,
                 bad_glyph ? 1 : 0);
        }
      }
      if (TLOG_IS_ON(2)) {
        printf("  '%s'\n", cluster_text.c_str());
      }
      if (bad_glyph)
        tlog(1, "Found illegal glyph!\n");
    }
  } while (!bad_glyph && pango_layout_iter_next_run(run_iter));

  pango_layout_iter_free(run_iter);
  g_object_unref(context);
  g_object_unref(layout);
  if (bad_glyph && graphemes) graphemes->clear();
  return !bad_glyph;
}