Example #1
0
void text_widget_set_text ( struct TEXT_WIDGET_HANDLE handle,
			    const char* text, int length )
{
  if ( handle.d == NULL || handle.d->layout == NULL )
    return;

  pango_layout_set_markup( handle.d->layout, text, length );

  // The idea here is to make sure that the VGFont contains
  // all the glyphs at the proper size so that when we want
  // to draw, we can can just call vgDrawGlyphs (well, maybe
  // not since PangoGlyphInfo is not an array of glyph
  // indexes; aww).
  PangoLayoutIter* li = pango_layout_get_iter( handle.d->layout );
  do {
    PangoLayoutRun* run = pango_layout_iter_get_run( li );
    if ( run == NULL )
      continue;
    PangoFont* font = run->item->analysis.font;
    // Well, you can see how C is not the most ideal language for
    // abstraction. Have to read the documentation to discover
    // that this font is a PangoFcFont.
    FT_Face face = pango_fc_font_lock_face( (PangoFcFont*)font );
    if ( face != NULL ) {
      struct VG_DATA* vg_data = face->size->generic.data;
      if ( vg_data == NULL ) {
	vg_data = vg_data_new();
	face->size->generic.data = vg_data;
	face->size->generic.finalizer = vg_data_free;
      }
      int g;
      for ( g = 0; g < run->glyphs->num_glyphs; g++ ) {
	int byte = run->glyphs->glyphs[g].glyph / 8;
	int bit  = 1 << ( run->glyphs->glyphs[g].glyph & 0x7 );
	if ( ! ( vg_data->cmap[byte] & bit  ) ) {
	  vg_data->cmap[byte] |= bit;
	  add_char( vg_data->font, face, run->glyphs->glyphs[g].glyph );
	}
      }
      pango_fc_font_unlock_face( (PangoFcFont*)font );
    }
  } while ( pango_layout_iter_next_run( li ) );

  pango_layout_iter_free( li );
}
Example #2
0
static gboolean
layout_is_ellipsized(PangoLayout *layout)
{
    /* pango_layout_is_ellipsized() is a new function in Pango-1.16; we
     * emulate it here by trying to look for the ellipsis run
     */
    PangoLogAttr *log_attrs;
    int n_attrs;
    PangoLayoutIter *iter;
    gboolean result = FALSE;

    /* Short circuit when we aren't ellipsizing at all */
    if (pango_layout_get_ellipsize(layout) == PANGO_ELLIPSIZE_NONE)
        return FALSE;
    
    pango_layout_get_log_attrs(layout, &log_attrs, &n_attrs);
    
    iter = pango_layout_get_iter(layout);
    do {
        PangoGlyphItem *run;
        int n_glyphs;
        int start_index;
        int n_graphemes;
        int i;

        run = pango_layout_iter_get_run(iter);
        if (!run)
            continue;

        n_glyphs = run->glyphs->num_glyphs;
        start_index = pango_layout_iter_get_index(iter);
        
        /* Check the number of clusters in the run ... if it is greater
         * than 1, then it isn't an ellipsis
         */
        if (run->glyphs->log_clusters[0] != run->glyphs->log_clusters[n_glyphs - 1])
            continue;

        /* Now check the number of graphemes in the run ... if it is less
         * than 3, it's probably an isolated 'fi' ligature or something
         * like that rather than an ellipsis.
         */
        n_graphemes = 0;
        for (i = 0; i < run->item->num_chars && i + start_index < n_attrs; i++)
            if (log_attrs[i + start_index].is_cursor_position)
                n_graphemes++;

        if (n_graphemes < 3)
            continue;

        /* OK, at this point it is probably an ellipsis; it's possible that
         * the text consists of just the letters 'ffi' and the font has a ligature
         * for that or something, but it's not too likely.
         */
        result = TRUE;
        break;
                
    } while (pango_layout_iter_next_run(iter));

    pango_layout_iter_free(iter);

    g_free(log_attrs);

    return result;
}
Example #3
0
void text_widget_draw_text ( struct TEXT_WIDGET_HANDLE handle )
{
  if ( handle.d == NULL || handle.d->layout == NULL )
    return;

  vgSetPaint( handle.d->foreground, VG_FILL_PATH );

  vgSeti( VG_MATRIX_MODE, VG_MATRIX_GLYPH_USER_TO_SURFACE );
  vgLoadIdentity();
#if 0
  // Overscan (in dots, evidently).
  vgTranslate( 14.f, 8.f );
#endif
  // Offset in mm.
  vgScale( handle.d->dpmm_x, handle.d->dpmm_y );
  // Move to the corner.
  vgTranslate( handle.d->x_mm, handle.d->y_mm );
  // Back to dots.
  vgScale( 1.f/handle.d->dpmm_x, 1.f/handle.d->dpmm_y );

  int height = PANGO_PIXELS( pango_layout_get_height( handle.d->layout ) );

  PangoLayoutIter* li = pango_layout_get_iter( handle.d->layout );
  do {
    PangoLayoutRun* run = pango_layout_iter_get_run( li );
    if ( run == NULL )
      continue;

    PangoRectangle logical_rect;
    int baseline_pango = pango_layout_iter_get_baseline( li );
    int baseline_pixel = PANGO_PIXELS( baseline_pango );
    pango_layout_iter_get_run_extents( li, NULL, &logical_rect );
    int x_pixel = PANGO_PIXELS( logical_rect.x );

    PangoFont* pg_font = run->item->analysis.font;

    FT_Face face = pango_fc_font_lock_face( (PangoFcFont*)pg_font );

    if ( face != NULL ) {

      struct VG_DATA* vg_data = face->size->generic.data;
      if ( vg_data != NULL ) {
	// About the only extra attribute we can manage is the foreground
	// color. But, it might be nice to render a background color
	// to see just how badly the text is fitted into the widget
	// box.
	GSList* attr_item = run->item->analysis.extra_attrs;
	while ( attr_item ) {
	  PangoAttribute* attr = attr_item->data;
	  switch ( attr->klass->type ) {
	  case PANGO_ATTR_FOREGROUND:
	    {
	      PangoColor color = ((PangoAttrColor*)attr)->color;
	      VGfloat new_color[] = { (float)color.red / 65535.f,
				      (float)color.green / 65535.f,
				      (float)color.blue / 65535.f, 1.f };
	      VGPaint new_paint = vgCreatePaint();
	      vgSetParameterfv( new_paint, VG_PAINT_COLOR, 4, new_color );
	      vgSetPaint( new_paint, VG_FILL_PATH );
	      vgDestroyPaint( new_paint );
	    }
	    break;
	  default:
	    printf( "\tHmm. Unknown attribute: %d\n", attr->klass->type );
	  }
	  attr_item = attr_item->next;
	}

	// Note: inverted Y coordinate
	VGfloat point[2] = { x_pixel, height - baseline_pixel };
	vgSetfv( VG_GLYPH_ORIGIN, 2, point );
	VGFont vg_font = vg_data->font;
	int g;
	for ( g = 0; g < run->glyphs->num_glyphs; g++ ) {
	  vgDrawGlyph( vg_font, run->glyphs->glyphs[g].glyph, VG_FILL_PATH,
		       VG_TRUE );
	}

	if ( vgGetPaint( VG_FILL_PATH ) != handle.d->foreground ) {
	  vgSetPaint( handle.d->foreground, VG_FILL_PATH );
	}
      }
      pango_fc_font_unlock_face( (PangoFcFont*)pg_font );
    }
  } while ( pango_layout_iter_next_run( li ) );
  // Iterators are not free.
  pango_layout_iter_free( li);
}
Example #4
0
static void
dump_runs (PangoLayout *layout, GString *string)
{
  PangoLayoutIter *iter;
  PangoLayoutRun *run;
  PangoItem *item;
  const gchar *text;
  gint index, index2;
  gboolean has_more;
  gchar *char_str;
  gint i;
  gchar *font;

  text = pango_layout_get_text (layout);
  iter = pango_layout_get_iter (layout);

  has_more = TRUE;
  index = pango_layout_iter_get_index (iter);
  i = 0;
  while (has_more)
    {
      run = pango_layout_iter_get_run (iter);
      has_more = pango_layout_iter_next_run (iter);
      i++;

      if (has_more)
        {
          index2 = pango_layout_iter_get_index (iter);
          char_str = g_strndup (text + index, index2 - index);          
        }
      else
        {
          char_str = g_strdup (text + index);
        }

      if (run)
        {
          item = ((PangoGlyphItem*)run)->item;
          font = font_name (item->analysis.font);
          g_string_append_printf (string, "i=%d, index=%d, chars=%d, level=%d, gravity=%s, flags=%d, font=%s, script=%s, language=%s, '%s'\n",
                                  i, index, item->num_chars, item->analysis.level,
                                  gravity_name (item->analysis.gravity),
                                  item->analysis.flags,
                                  "OMITTED", /* for some reason, this fails on build.gnome.org, so leave it out */
                                  script_name (item->analysis.script),
                                  pango_language_to_string (item->analysis.language),
                                  char_str);
          dump_extra_attrs (item->analysis.extra_attrs, string);
          g_free (font);
        }
      else
        {
          g_string_append_printf (string, "i=%d, index=%d, no run, line end\n",
                                  i, index);
        }

      g_free (char_str);
      index = index2;
    }
  pango_layout_iter_free (iter);
}
static VALUE
layout_iter_get_run(VALUE self)
{
    PangoLayoutRun* run = pango_layout_iter_get_run(_SELF(self));
    return BOXED2RVAL(run, PANGO_TYPE_GLYPH_ITEM);
}