Esempio n. 1
0
// Helper function used in the implementation of ScriptItemize
HRESULT PangoItemize(const char * chars, int cInChars, int cMaxItems, SCRIPT_ITEM *pItems, int * pcItems)
{
	SCRIPT_CACHE context = NULL;

	PangoAttrList * attributes_list = pango_attr_list_new();
	GList * items = pango_itemize(GetPangoContext(&context), chars, 0, cInChars, attributes_list, NULL);

	*pcItems = g_list_length(items);

	if (*pcItems >= cMaxItems)
	{
		pango_attr_list_unref(attributes_list);
		g_list_free(items);
		return E_OUTOFMEMORY;
	}

	for(int i = 0; i < *pcItems; ++i)
	{
		PangoItem* item = static_cast<PangoItem*>(g_list_nth_data(items, i));
		pItems[i].iCharPos = item->offset;
		pItems[i].a.fRTL = item->analysis.level == 1;
		pItems[i].a.fLayoutRTL = pItems[i].a.fRTL;
		// TODO: set other fields in SCRIPT_ANALYSIS as needed.

		pango_item_free(item);
	}

	pango_attr_list_unref(attributes_list);
	g_list_free(items);

	return S_OK;
}
Esempio n. 2
0
// Helper function used in the implementation of ScriptShape
HRESULT PangoCharsToGlyph(SCRIPT_CACHE *psc, const char * chars, int cInChars, int cMaxItems, PangoGlyphString **pGlpyhs, int * pcItems)
{
	ScriptCacheImplementation * cache = reinterpret_cast<ScriptCacheImplementation*>(*psc);
	PangoContext * pangoContext;
	cache->m_vwGraphics->GetTextStyleContext(reinterpret_cast<HDC*>(&pangoContext));

	PangoAttrList * attributes_list = pango_attr_list_new();
	GList * items = pango_itemize(pangoContext, chars, 0, cInChars, attributes_list, NULL);

	int length = g_list_length(items);

	int glyphsCount = 0;
	pGlpyhs[0] = NULL;
	for(int i = 0; i < length; ++i)
	{
		PangoItem* item = static_cast<PangoItem*>(g_list_nth_data(items, i));

		PangoGlyphString * ptrPangoGlyphString = pango_glyph_string_new();
		pango_shape(chars + item->offset, item->length, &item->analysis, ptrPangoGlyphString);
		glyphsCount += ptrPangoGlyphString->num_glyphs;

		if (glyphsCount > cMaxItems)
		{
			pango_glyph_string_free(ptrPangoGlyphString);
			FreeGlyphs(reinterpret_cast<WORD*>(pGlpyhs), cMaxItems);
			pango_item_free(item);
			pango_attr_list_unref(attributes_list);
			g_list_free(items);
			return E_OUTOFMEMORY;
		}

		pGlpyhs[i] = ptrPangoGlyphString;
		if (i < (cMaxItems - 1))
			pGlpyhs[i + 1] = NULL; // null term the list (used for deleting etc.)
		pango_item_free(item);
	}

	pango_attr_list_unref(attributes_list);
	g_list_free(items);

	*pcItems = glyphsCount;
	return S_OK;
}
Esempio n. 3
0
void FontSupport::drawText(const WFont& font, const WRectF& rect,
			   const WTransform& transform, Bitmap& bitmap,
			   WFlags<AlignmentFlag> flags,
			   const WString& text)
{
  PANGO_LOCK;

  enabledFontFormats = enabledFontFormats_;

  PangoMatrix matrix;
  matrix.xx = transform.m11();
  matrix.xy = transform.m21();
  matrix.yx = transform.m12();
  matrix.yy = transform.m22();
  matrix.x0 = transform.dx();
  matrix.y0 = transform.dy();

  std::string utf8 = text.toUTF8();

  std::vector<PangoGlyphString *> glyphs;
  int width;

  pango_context_set_matrix(context_, &matrix);

  /*
   * Oh my god, somebody explain me why we need to do this...
   */
  WFont f = font;
  f.setSize(font.sizeLength().toPixels()
	    / pango_matrix_get_font_scale_factor(&matrix));

  GList *items = layoutText(f, utf8, glyphs, width);
  pango_context_set_matrix(context_, nullptr);

  AlignmentFlag hAlign = flags & AlignHorizontalMask;

  /* FIXME handle bidi ! */

  double x;
  switch (hAlign) {
  case AlignmentFlag::Left:
    x = rect.left();
    break;
  case AlignmentFlag::Right:
    x = rect.right() - pangoUnitsToDouble(width);
    break;
  case AlignmentFlag::Center:
    x = rect.center().x() - pangoUnitsToDouble(width/2);
    break;
  default:
    x = 0;
  }

  AlignmentFlag vAlign = flags & AlignVerticalMask;

  PangoFont *pangoFont = matchFont(font).pangoFont();
  PangoFontMetrics *metrics = pango_font_get_metrics(pangoFont, nullptr);

  double ascent
    = pangoUnitsToDouble(pango_font_metrics_get_ascent(metrics));
  double descent 
    = pangoUnitsToDouble(pango_font_metrics_get_descent(metrics));

  pango_font_metrics_unref(metrics);

  double baseline = ascent;
  double height = ascent + descent;

  double y;
  switch (vAlign) {
  case AlignmentFlag::Top:
    y = rect.top() + baseline;
    break;
  case AlignmentFlag::Middle:
    y = rect.center().y() - height / 2 + baseline;
    break;
  case AlignmentFlag::Bottom:
    y = rect.bottom() - height + baseline;
    break;
  default:
    y = 0;
  }

  FT_Bitmap bmp;
  bmp.buffer = bitmap.buffer();
  bmp.width = bitmap.width();
  bmp.rows = bitmap.height();
  bmp.pitch = bitmap.pitch();
  bmp.pixel_mode = FT_PIXEL_MODE_GRAY;
  bmp.num_grays = 16; // ???

  GList *elem;
  unsigned i = 0;

  for (elem = items; elem; elem = elem->next) {
    PangoItem *item = (PangoItem *)elem->data;
    PangoAnalysis *analysis = &item->analysis;

    PangoGlyphString *gl = glyphs[i++];

    pango_ft2_render_transformed(&bmp, &matrix,
				 analysis->font, gl,
				 pangoUnitsFromDouble(x),
				 pangoUnitsFromDouble(y));

    x += pangoUnitsToDouble(pango_glyph_string_get_width(gl));

    pango_glyph_string_free(gl);
    pango_item_free(item);
  }

  g_list_free(items);
}
Esempio n. 4
0
void FontSupport::drawText(const WFont& font, const WRectF& rect,
			   WFlags<AlignmentFlag> flags, const WString& text)
{
  PANGO_LOCK;

  enabledFontFormats = enabledFontFormats_;

  std::string utf8 = text.toUTF8();

  std::vector<PangoGlyphString *> glyphs;
  int width;

  GList *items = layoutText(font, utf8, glyphs, width);

  AlignmentFlag hAlign = flags & AlignHorizontalMask;
  AlignmentFlag vAlign = flags & AlignVerticalMask;

  /* FIXME handle bidi ! */

  double x;
  switch (hAlign) {
  case AlignmentFlag::Left:
    x = rect.left();
    break;
  case AlignmentFlag::Right:
    x = rect.right() - pangoUnitsToDouble(width);
    break;
  case AlignmentFlag::Center:
    x = rect.center().x() - pangoUnitsToDouble(width/2);
    break;
  default:
    x = 0;
  }

  unsigned i = 0;
  for (GList *elem = items; elem; elem = elem->next) {
    PangoItem *item = (PangoItem *)elem->data;
    PangoAnalysis *analysis = &item->analysis;

    PangoGlyphString *gl = glyphs[i++];

    currentFont_ = analysis->font;

    /*
     * Note, we are actually ignoring the selected glyphs here, which
     * is a pitty and possibly wrong if the device does not make the
     * same selection !
     */
    WString s = WString::fromUTF8(utf8.substr(item->offset,
                                              item->length));

    device_->drawText(WRectF(x, rect.y(),
			     1000, rect.height()),
		      AlignmentFlag::Left | vAlign, TextFlag::SingleLine,
		      s, nullptr);

    WTextItem textItem = device_->measureText(s, -1, false);

    x += textItem.width();

    pango_item_free(item);
    pango_glyph_string_free(gl);
  }

  g_list_free(items);

  currentFont_ = nullptr;
}
Esempio n. 5
0
/* Shapes the ellipsis using the font and is_cjk information computed by
 * update_ellipsis_shape() from the first character in the gap.
 */
static void
shape_ellipsis (EllipsizeState *state)
{
  PangoAttrList *attrs = pango_attr_list_new ();
  GSList *run_attrs;
  PangoItem *item;
  PangoGlyphString *glyphs;
  GSList *l;
  PangoAttribute *fallback;
  const char *ellipsis_text;
  int i;

  /* Create/reset state->ellipsis_run
   */
  if (!state->ellipsis_run)
    {
      state->ellipsis_run = g_slice_new (PangoGlyphItem);
      state->ellipsis_run->glyphs = pango_glyph_string_new ();
      state->ellipsis_run->item = NULL;
    }

  if (state->ellipsis_run->item)
    {
      pango_item_free (state->ellipsis_run->item);
      state->ellipsis_run->item = NULL;
    }
  
  /* Create an attribute list
   */
  run_attrs = pango_attr_iterator_get_attrs (state->gap_start_attr);
  for (l = run_attrs; l; l = l->next)
    {
      PangoAttribute *attr = l->data;
      attr->start_index = 0;
      attr->end_index = G_MAXINT;

      pango_attr_list_insert (attrs, attr);
    }

  g_slist_free (run_attrs);

  fallback = pango_attr_fallback_new (FALSE);
  fallback->start_index = 0;
  fallback->end_index = G_MAXINT;
  pango_attr_list_insert (attrs, fallback);

  /* First try using a specific ellipsis character in the best matching font
   */
  if (state->ellipsis_is_cjk)
    ellipsis_text = "\342\213\257";	/* U+22EF: MIDLINE HORIZONTAL ELLIPSIS, used for CJK */
  else
    ellipsis_text = "\342\200\246";	/* U+2026: HORIZONTAL ELLIPSIS */

  item = itemize_text (state, ellipsis_text, attrs);

  /* If that fails we use "..." in the first matching font
   */
  if (!item->analysis.font ||
      !_pango_engine_shape_covers (item->analysis.shape_engine, item->analysis.font,
				   item->analysis.language, g_utf8_get_char (ellipsis_text)))
    {
      pango_item_free (item);
      
      /* Modify the fallback iter while it is inside the PangoAttrList; Don't try this at home
       */
      ((PangoAttrInt *)fallback)->value = TRUE; 

      ellipsis_text = "...";
      item = itemize_text (state, ellipsis_text, attrs);
    }
  
  pango_attr_list_unref (attrs);
  
  state->ellipsis_run->item = item;

  /* Now shape
   */
  glyphs = state->ellipsis_run->glyphs;

  pango_shape (ellipsis_text, strlen (ellipsis_text),
	       &item->analysis, glyphs);

  state->ellipsis_width = 0;
  for (i = 0; i < glyphs->num_glyphs; i++)
    state->ellipsis_width += glyphs->glyphs[i].geometry.width;
}