Example #1
0
static struct text_layout *
text_layout_create(void)
{
	struct text_layout *layout;
	cairo_surface_t *surface;
	cairo_t *cr;

	layout = malloc(sizeof *layout);
	if (!layout)
		return NULL;

	layout->glyphs = NULL;
	layout->num_glyphs = 0;

	layout->clusters = NULL;
	layout->num_clusters = 0;

	surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 0, 0);
	cr = cairo_create(surface);
	cairo_set_font_size(cr, font_size);
	cairo_select_font_face(cr, font_name, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
	layout->font = cairo_get_scaled_font(cr);
	cairo_scaled_font_reference(layout->font);

	cairo_destroy(cr);
	cairo_surface_destroy(surface);

	return layout;
}
Example #2
0
static cairo_test_status_t
get_glyph (cairo_t *cr, const char *utf8, cairo_glyph_t *glyph)
{
    cairo_glyph_t *text_to_glyphs;
    cairo_status_t status;
    int i;

    text_to_glyphs = glyph;
    i = 1;
    status = cairo_scaled_font_text_to_glyphs (cairo_get_scaled_font (cr),
					       0, 0,
					       utf8, -1,
					       &text_to_glyphs, &i,
					       NULL, NULL,
					       0);
    if (status != CAIRO_STATUS_SUCCESS)
	return cairo_test_status_from_status (cairo_test_get_context (cr),
					      status);

    if (text_to_glyphs != glyph) {
	*glyph = text_to_glyphs[0];
	cairo_glyph_free (text_to_glyphs);
    }

    return CAIRO_TEST_SUCCESS;
}
Example #3
0
static cairo_test_status_t
draw (cairo_t *cr, int width, int height)
{
    const cairo_test_context_t *ctx = cairo_test_get_context (cr);
    cairo_glyph_t *glyphs = xmalloc (NUM_GLYPHS * sizeof (cairo_glyph_t));
    cairo_scaled_font_t *scaled_font;
    const char *characters[] = { /* try to exercise different widths of index */
	"m", /* Latin letter m, index=0x50 */
	"μ", /* Greek letter mu, index=0x349 */
	NULL,
    }, **utf8;
    int i, j;
    cairo_status_t status;

    /* Paint white background. */
    cairo_set_source_rgb (cr, 1, 1, 1);
    cairo_paint (cr);

    cairo_select_font_face (cr, CAIRO_TEST_FONT_FAMILY " Sans",
			    CAIRO_FONT_SLANT_NORMAL,
			    CAIRO_FONT_WEIGHT_NORMAL);
    cairo_set_font_size (cr, TEXT_SIZE);
    scaled_font = cairo_get_scaled_font (cr);

    for (utf8 = characters; *utf8 != NULL; utf8++) {
	status = get_glyph (ctx, scaled_font, *utf8, &glyphs[0]);
	if (status)
	    goto BAIL;

	if (glyphs[0].index) {
	    glyphs[0].x = 1.0;
	    glyphs[0].y = height - 1;
	    for (i=1; i < NUM_GLYPHS; i++)
		glyphs[i] = glyphs[0];

	    cairo_show_glyphs (cr, glyphs, NUM_GLYPHS);
	}
    }

    /* we can pack ~21k 1-byte glyphs into a single XRenderCompositeGlyphs8 */
    status = get_glyph (ctx, scaled_font, "m", &glyphs[0]);
    if (status)
	goto BAIL;
    for (i=1; i < 21500; i++)
	glyphs[i] = glyphs[0];
    /* so check expanding the current 1-byte request for 2-byte glyphs */
    status = get_glyph (ctx, scaled_font, "μ", &glyphs[i]);
    if (status)
	goto BAIL;
    for (j=i+1; j < NUM_GLYPHS; j++)
	glyphs[j] = glyphs[i];

    cairo_show_glyphs (cr, glyphs, NUM_GLYPHS);

  BAIL:
    free(glyphs);

    return status;
}
Example #4
0
static int
cr_get_scaled_font (lua_State *L) {
    cairo_t **obj = luaL_checkudata(L, 1, OOCAIRO_MT_NAME_CONTEXT);
    cairo_scaled_font_t **font = create_scaledfont_userdata(L);
    *font = cairo_get_scaled_font(*obj);
    cairo_scaled_font_reference(*font);
    return 1;
}
static cairo_status_t
glyph_array_add_text(glyph_array_t *glyphs, cairo_t *cr, const char *s, double spacing)
{
    cairo_scaled_font_t *scaled_font;
    cairo_status_t status;
    FT_Face face;
    unsigned long charcode;
    unsigned int index;
    cairo_text_extents_t extents;
    const char *p;
    FT_Vector kerning;
    double kern_x;
    int first = TRUE;

    scaled_font = cairo_get_scaled_font (cr);
    status = cairo_scaled_font_status (scaled_font);
    if (status)
	return status;

    face = cairo_ft_scaled_font_lock_face (scaled_font);
    if (face == NULL)
	return CAIRO_STATUS_FONT_TYPE_MISMATCH;

    p = s;
    while (*p)
    {
        charcode = *p;
        index = FT_Get_Char_Index (face, charcode);
        glyphs->glyph_list[glyphs->num_glyphs].index = index;
        if (first) {
            first = FALSE;
            glyphs->glyph_list[glyphs->num_glyphs].x = glyphs->x;
            glyphs->glyph_list[glyphs->num_glyphs].y = glyphs->y;
        } else {
            cairo_glyph_extents (cr, &glyphs->glyph_list[glyphs->num_glyphs - 1], 1, &extents);
            FT_Get_Kerning (face,
                            glyphs->glyph_list[glyphs->num_glyphs - 1].index,
                            glyphs->glyph_list[glyphs->num_glyphs].index,
                            FT_KERNING_UNSCALED,
                            &kerning);
            kern_x = DOUBLE_FROM_26_6(kerning.x);
            glyphs->glyph_list[glyphs->num_glyphs].x =
		glyphs->glyph_list[glyphs->num_glyphs - 1].x + extents.x_advance + kern_x + spacing;
            glyphs->glyph_list[glyphs->num_glyphs].y =
		glyphs->glyph_list[glyphs->num_glyphs - 1].y + extents.y_advance;
	}

	cairo_glyph_extents (cr, &glyphs->glyph_list[glyphs->num_glyphs], 1, &extents);
	glyphs->x = glyphs->glyph_list[glyphs->num_glyphs].x + extents.x_advance + spacing;
	glyphs->y = glyphs->glyph_list[glyphs->num_glyphs].y + extents.y_advance;
	p++;
        glyphs->num_glyphs++;
    }

    cairo_ft_scaled_font_unlock_face (scaled_font);
    return CAIRO_STATUS_SUCCESS;
}
Example #6
0
bool GlyphLayerBevel::render(
    cairo_t*       c,
    cairo_glyph_t* glyph,
    unsigned int   width,
    unsigned int   height
) {
    if(cairo_status(c) || !glyph) return false;

    cairo_surface_t* bumpmap = cairo_image_surface_create(CAIRO_FORMAT_A8, width, height);
    cairo_t*         cr      = cairo_create(bumpmap);

    cairo_set_scaled_font(cr, cairo_get_scaled_font(c));
    cairo_glyph_path(cr, glyph, 1);
    cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);

    for(double l = _bevelWidth; l > 0.0f; l -= _bevelStep) {
        cairo_set_source_rgba(cr, 1.0f, 1.0f, 1.0f, 1.0f - (l / _bevelWidth));
        cairo_set_line_width(cr, l);
        cairo_stroke_preserve(cr);
    }

    cairo_destroy(cr);

    cairo_surface_t* lightmap = osgPairo::createEmbossedSurface(
                                    bumpmap,
                                    _azimuth,
                                    _elevation,
                                    _height,
                                    _ambient,
                                    _diffuse
                                );

    cairo_glyph_path(c, glyph, 1);
    cairo_save(c);
    cairo_clip_preserve(c);
    cairo_set_operator(c, CAIRO_OPERATOR_SOURCE);
    cairo_set_source_surface(c, lightmap, 0, 0);
    cairo_paint(c);
    cairo_set_operator(c, CAIRO_OPERATOR_SATURATE);
    cairo_set_source_rgba(c, 1.0f, 1.0f, 1.0f, 1.0f);
    cairo_paint(c);
    cairo_restore(c);

    // TODO: This is a hack! Figure out why the border is poor quality...
    cairo_set_line_width(c, 4.0);
    cairo_set_operator(c, CAIRO_OPERATOR_CLEAR);
    cairo_stroke(c);

    // cairo_surface_write_to_png(bumpmap, "bumpmap.png");
    // cairo_surface_write_to_png(lightmap, "lightmap.png");

    cairo_surface_destroy(bumpmap);
    cairo_surface_destroy(lightmap);

    return true;
}
Example #7
0
static cairo_test_status_t
draw (cairo_t *cr, int width, int height)
{
    cairo_font_options_t *font_options;
    cairo_scaled_font_t *scaled_font;
    FT_Face face;
    FT_ULong charcode;
    FT_UInt idx;
    int i = 0;
    cairo_glyph_t glyphs[NUM_GLYPHS];

    /* paint white so we don't need separate ref images for
     * RGB24 and ARGB32 */
    cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
    cairo_paint (cr);

    cairo_select_font_face (cr, "Bitstream Vera Sans",
			    CAIRO_FONT_SLANT_NORMAL,
			    CAIRO_FONT_WEIGHT_NORMAL);
    cairo_set_font_size (cr, TEXT_SIZE);

    font_options = cairo_font_options_create ();
    cairo_get_font_options (cr, font_options);
    cairo_font_options_set_hint_metrics (font_options, CAIRO_HINT_METRICS_OFF);
    cairo_set_font_options (cr, font_options);
    cairo_font_options_destroy (font_options);

    cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);

    scaled_font = cairo_get_scaled_font (cr);
    face = cairo_ft_scaled_font_lock_face (scaled_font);
    {
	charcode = FT_Get_First_Char(face, &idx);
	while (idx && (i < NUM_GLYPHS)) {
	    glyphs[i] = (cairo_glyph_t) {idx, PAD + GRID_SIZE * (i/GRID_ROWS), PAD + TEXT_SIZE + GRID_SIZE * (i%GRID_ROWS)};
	    i++;
	    charcode = FT_Get_Next_Char(face, charcode, &idx);
	}
    }
    cairo_ft_scaled_font_unlock_face (scaled_font);

    cairo_show_glyphs(cr, glyphs, i);

    return CAIRO_TEST_SUCCESS;
}
Example #8
0
static cairo_status_t
test_scaled_font_init (cairo_scaled_font_t  *scaled_font,
		       cairo_t              *cr,
		       cairo_font_extents_t *extents)
{
    cairo_set_font_face (cr,
			 cairo_font_face_get_user_data (cairo_scaled_font_get_font_face (scaled_font),
							&fallback_font_key));

    cairo_scaled_font_set_user_data (scaled_font,
				     &fallback_font_key,
				     cairo_scaled_font_reference (cairo_get_scaled_font (cr)),
				     (cairo_destroy_func_t) cairo_scaled_font_destroy);

    cairo_font_extents (cr, extents);

    return CAIRO_STATUS_SUCCESS;
}
static cairo_test_status_t
draw (cairo_t *cr, int width, int height)
{
    const cairo_test_context_t *ctx = cairo_test_get_context (cr);
    cairo_status_t status;
    const double colors[8][3] = {
	{ 1.0, 0.0, 0.0 }, /* red */
	{ 0.0, 1.0, 0.0 }, /* green */
	{ 1.0, 1.0, 0.0 }, /* yellow */
	{ 0.0, 0.0, 1.0 }, /* blue */
	{ 1.0, 0.0, 1.0 }, /* magenta */
	{ 0.0, 1.0, 1.0 }, /* cyan */
	{ 1.0, 1.0, 1.0 }, /* white */
	{ 0.0, 0.0, 0.0 }, /* black */
    };
    int i, j, loop;

    /* cache a resolved scaled-font */
    scaled_font = cairo_get_scaled_font (cr);

    for (loop = 0; loop < LOOPS; loop++) {
	for (i = 0; i < LOOPS; i++) {
	    for (j = 0; j < 8; j++) {
		use_solid (cr, colors[j][0], colors[j][1], colors[j][2]);
		status = cairo_status (cr);
		if (status)
		    return cairo_test_status_from_status (ctx, status);
	    }
	}

	for (i = 0; i < NRAND; i++) {
	    use_solid (cr, drand48 (), drand48 (), drand48 ());
	    status = cairo_status (cr);
	    if (status)
		return cairo_test_status_from_status (ctx, status);
	}
    }

    /* stress test only, so clear the surface before comparing */
    cairo_set_source_rgb (cr, 0, 0, 1);
    cairo_paint (cr);

    return CAIRO_TEST_SUCCESS;
}
Example #10
0
File: glyphs.c Project: AZed/cairo
static double
count_glyphs (double font_size,
	      cairo_antialias_t antialias,
	      cairo_t *cr, int width, int height)
{
    const char text[] = "the jay, pig, fox, zebra and my wolves quack";
    cairo_scaled_font_t *scaled_font;
    cairo_glyph_t *glyphs = NULL;
    cairo_text_extents_t extents;
    cairo_font_options_t *options;
    cairo_status_t status;
    int num_glyphs;
    int glyphs_per_line, lines_per_loop;

    options = cairo_font_options_create ();
    cairo_font_options_set_antialias (options, antialias);
    cairo_set_font_options (cr, options);
    cairo_font_options_destroy (options);

    cairo_select_font_face (cr,
			    "@cairo:",
			    CAIRO_FONT_SLANT_NORMAL,
			    CAIRO_FONT_WEIGHT_NORMAL);
    cairo_set_font_size (cr, font_size);
    scaled_font = cairo_get_scaled_font (cr);
    status = cairo_scaled_font_text_to_glyphs (scaled_font, 0., 0.,
					       text, -1,
					       &glyphs, &num_glyphs,
					       NULL, NULL,
					       NULL);
    if (status)
	return 0;

    cairo_scaled_font_glyph_extents (scaled_font,
				     glyphs, num_glyphs,
				     &extents);
    cairo_glyph_free (glyphs);

    glyphs_per_line = num_glyphs * width / extents.width + 1;
    lines_per_loop = height / extents.height + 1;
    return glyphs_per_line * lines_per_loop / 1000.; /* kiloglyphs */
}
Example #11
0
static cairo_test_status_t
draw (cairo_t *cr, int width, int height)
{
    /* We draw in the default black, so paint white first. */
    cairo_save (cr);
    cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* white */
    cairo_paint (cr);
    cairo_restore (cr);

    cairo_select_font_face (cr, "Bitstream Vera Sans",
			    CAIRO_FONT_SLANT_NORMAL,
			    CAIRO_FONT_WEIGHT_NORMAL);
    cairo_set_font_size (cr, TEXT_SIZE);

    cairo_set_source_rgb (cr, 0, 0, 0); /* black */

    cairo_boilerplate_scaled_font_set_max_glyphs_cached (cairo_get_scaled_font (cr), 1);

    cairo_move_to (cr, 1, TEXT_SIZE);
    cairo_show_text (cr, "the five boxing wizards jump quickly");

    return CAIRO_TEST_SUCCESS;
}
Example #12
0
static void
text_to_glyphs (cairo_t *cr,
                const gchar *text,
                cairo_glyph_t **glyphs,
                int *num_glyphs)
{
  PangoAttribute *fallback_attr;
  PangoAttrList *attr_list;
  PangoContext *context;
  PangoDirection base_dir;
  GList *items;
  GList *visual_items;
  FT_Face ft_face;
  hb_font_t *hb_font;
  gdouble x = 0, y = 0;
  gint i;
  gdouble x_scale, y_scale;

  *num_glyphs = 0;
  *glyphs = NULL;

  base_dir = pango_find_base_dir (text, -1);

  cairo_scaled_font_t *cr_font = cairo_get_scaled_font (cr);
  ft_face = cairo_ft_scaled_font_lock_face (cr_font);
  hb_font = hb_ft_font_create (ft_face, NULL);

  cairo_surface_t *target = cairo_get_target (cr);
  cairo_surface_get_device_scale (target, &x_scale, &y_scale);

  /* We abuse pango itemazation to split text into script and direction
   * runs, since we use our fonts directly no through pango, we don't
   * bother changing the default font, but we disable font fallback as
   * pango will split runs at font change */
  context = pango_cairo_create_context (cr);
  attr_list = pango_attr_list_new ();
  fallback_attr = pango_attr_fallback_new (FALSE);
  pango_attr_list_insert (attr_list, fallback_attr);
  items = pango_itemize_with_base_dir (context, base_dir,
                                       text, 0, strlen (text),
                                       attr_list, NULL);
  g_object_unref (context);
  pango_attr_list_unref (attr_list);

  /* reorder the items in the visual order */
  visual_items = pango_reorder_items (items);

  while (visual_items) {
    PangoItem *item;
    PangoAnalysis analysis;
    hb_buffer_t *hb_buffer;
    hb_glyph_info_t *hb_glyphs;
    hb_glyph_position_t *hb_positions;
    gint n;

    item = visual_items->data;
    analysis = item->analysis;

    hb_buffer = hb_buffer_create ();
    hb_buffer_add_utf8 (hb_buffer, text, -1, item->offset, item->length);
    hb_buffer_set_script (hb_buffer, hb_glib_script_to_script (analysis.script));
    hb_buffer_set_language (hb_buffer, hb_language_from_string (pango_language_to_string (analysis.language), -1));
    hb_buffer_set_direction (hb_buffer, analysis.level % 2 ? HB_DIRECTION_RTL : HB_DIRECTION_LTR);

    hb_shape (hb_font, hb_buffer, NULL, 0);

    n = hb_buffer_get_length (hb_buffer);
    hb_glyphs = hb_buffer_get_glyph_infos (hb_buffer, NULL);
    hb_positions = hb_buffer_get_glyph_positions (hb_buffer, NULL);

    *glyphs = g_renew (cairo_glyph_t, *glyphs, *num_glyphs + n);

    for (i = 0; i < n; i++) {
      (*glyphs)[*num_glyphs + i].index = hb_glyphs[i].codepoint;
      (*glyphs)[*num_glyphs + i].x = x + (hb_positions[i].x_offset / (64. * x_scale));
      (*glyphs)[*num_glyphs + i].y = y - (hb_positions[i].y_offset / (64. * y_scale));
      x += (hb_positions[i].x_advance / (64. * x_scale));
      y -= (hb_positions[i].y_advance / (64. * y_scale));
    }

    *num_glyphs += n;

    hb_buffer_destroy (hb_buffer);

    visual_items = visual_items->next;
  }

  g_list_free_full (visual_items, (GDestroyNotify) pango_item_free);
  g_list_free_full (items, (GDestroyNotify) pango_item_free);

  hb_font_destroy (hb_font);
  cairo_ft_scaled_font_unlock_face (cr_font);
}
Example #13
0
static cairo_test_status_t
draw (cairo_t *cr, int width, int height)
{
    const cairo_test_context_t *ctx = cairo_test_get_context (cr);
    cairo_text_extents_t extents, nil_extents;
    cairo_font_extents_t font_extents, nil_font_extents;
    cairo_scaled_font_t *scaled_font;

    cairo_select_font_face (cr, "Bitstream Vera Sans",
			    CAIRO_FONT_SLANT_NORMAL,
			    CAIRO_FONT_WEIGHT_NORMAL);
    cairo_set_font_size (cr, 16);

    cairo_move_to (cr, 10, 25);
    cairo_show_text (cr, NULL);
    cairo_show_text (cr, "");
    cairo_show_glyphs (cr, NULL, 0);
    cairo_show_glyphs (cr, (void*)8, 0);

    cairo_move_to (cr, 10, 55);
    cairo_text_path (cr, NULL);
    cairo_text_path (cr, "");
    cairo_glyph_path (cr, (void*)8, 0);
    cairo_fill (cr);

    memset (&nil_extents, 0, sizeof (cairo_text_extents_t));

    memset (&extents, 0xff, sizeof (cairo_text_extents_t));
    cairo_text_extents (cr, "", &extents);
    if (! text_extents_equal (&extents, &nil_extents)) {
	cairo_test_log (ctx, "Error: cairo_text_extents(\"\"); extents (%g, %g, %g, %g, %g, %g)\n",
		        extents.x_bearing, extents.y_bearing,
			extents.width, extents.height,
			extents.x_advance, extents.y_advance);
	return CAIRO_TEST_FAILURE;
    }

    memset (&extents, 0xff, sizeof (cairo_text_extents_t));
    cairo_text_extents (cr, NULL, &extents);
    if (! text_extents_equal (&extents, &nil_extents)) {
	cairo_test_log (ctx, "Error: cairo_text_extents(NULL); extents (%g, %g, %g, %g, %g, %g)\n",
		        extents.x_bearing, extents.y_bearing,
			extents.width, extents.height,
			extents.x_advance, extents.y_advance);
	return CAIRO_TEST_FAILURE;
    }

    memset (&extents, 0xff, sizeof (cairo_text_extents_t));
    cairo_glyph_extents (cr, (void*)8, 0, &extents);
    if (! text_extents_equal (&extents, &nil_extents)) {
	cairo_test_log (ctx, "Error: cairo_glyph_extents(); extents (%g, %g, %g, %g, %g, %g)\n",
		        extents.x_bearing, extents.y_bearing,
			extents.width, extents.height,
			extents.x_advance, extents.y_advance);
	return CAIRO_TEST_FAILURE;
    }

    scaled_font = cairo_get_scaled_font (cr);

    memset (&extents, 0xff, sizeof (cairo_text_extents_t));
    cairo_scaled_font_text_extents (scaled_font, "", &extents);
    if (! text_extents_equal (&extents, &nil_extents)) {
	cairo_test_log (ctx, "Error: cairo_scaled_font_text_extents(\"\"); extents (%g, %g, %g, %g, %g, %g)\n",
		        extents.x_bearing, extents.y_bearing,
			extents.width, extents.height,
			extents.x_advance, extents.y_advance);
	return CAIRO_TEST_FAILURE;
    }

    memset (&extents, 0xff, sizeof (cairo_text_extents_t));
    cairo_scaled_font_text_extents (scaled_font, NULL, &extents);
    if (! text_extents_equal (&extents, &nil_extents)) {
	cairo_test_log (ctx, "Error: cairo_scaled_font_text_extents(NULL); extents (%g, %g, %g, %g, %g, %g)\n",
		        extents.x_bearing, extents.y_bearing,
			extents.width, extents.height,
			extents.x_advance, extents.y_advance);
	return CAIRO_TEST_FAILURE;
    }

    memset (&extents, 0xff, sizeof (cairo_text_extents_t));
    cairo_scaled_font_glyph_extents (scaled_font, (void*)8, 0, &extents);
    if (! text_extents_equal (&extents, &nil_extents)) {
	cairo_test_log (ctx, "Error: cairo_scaled_font_glyph_extents(NULL); extents (%g, %g, %g, %g, %g, %g)\n",
		        extents.x_bearing, extents.y_bearing,
			extents.width, extents.height,
			extents.x_advance, extents.y_advance);
	return CAIRO_TEST_FAILURE;
    }

    /* Lets also try font size 0 while here */
    cairo_set_font_size (cr, 0);

    memset (&extents, 0xff, sizeof (cairo_text_extents_t));
    cairo_text_extents (cr, "test", &extents);
    if (! text_extents_equal (&extents, &nil_extents)) {
	cairo_test_log (ctx, "Error: cairo_set_font_size(0); cairo_text_extents(\"test\"); extents (%g, %g, %g, %g, %g, %g)\n",
		        extents.x_bearing, extents.y_bearing,
			extents.width, extents.height,
			extents.x_advance, extents.y_advance);
	return CAIRO_TEST_FAILURE;
    }

    memset (&nil_font_extents, 0, sizeof (cairo_font_extents_t));

    memset (&font_extents, 0xff, sizeof (cairo_font_extents_t));
    cairo_font_extents (cr,  &font_extents);
    if (! font_extents_equal (&font_extents, &nil_font_extents)) {
	cairo_test_log (ctx, "Error: cairo_set_font_size(0); cairo_font_extents(); extents (%g, %g, %g, %g, %g)\n",
		        font_extents.ascent, font_extents.descent,
			font_extents.height,
			font_extents.max_x_advance, font_extents.max_y_advance);
	return CAIRO_TEST_FAILURE;
    }

    scaled_font = cairo_get_scaled_font (cr);

    memset (&font_extents, 0xff, sizeof (cairo_font_extents_t));
    cairo_scaled_font_extents (scaled_font,  &font_extents);
    if (! font_extents_equal (&font_extents, &nil_font_extents)) {
	cairo_test_log (ctx, "Error: cairo_set_font_size(0); cairo_scaled_font_extents(); extents (%g, %g, %g, %g, %g)\n",
		        font_extents.ascent, font_extents.descent,
			font_extents.height,
			font_extents.max_x_advance, font_extents.max_y_advance);
	return CAIRO_TEST_FAILURE;
    }

    return CAIRO_TEST_SUCCESS;
}
Example #14
0
File: glyphs.c Project: AZed/cairo
static cairo_time_t
do_glyphs (double font_size,
	   cairo_antialias_t antialias,
	   cairo_t *cr, int width, int height, int loops)
{
    const char text[] = "the jay, pig, fox, zebra and my wolves quack";
    cairo_scaled_font_t *scaled_font;
    cairo_glyph_t *glyphs = NULL, *glyphs_copy;
    cairo_text_extents_t extents;
    cairo_font_options_t *options;
    cairo_status_t status;
    double x, y;
    int num_glyphs, n;

    options = cairo_font_options_create ();
    cairo_font_options_set_antialias (options, antialias);
    cairo_set_font_options (cr, options);
    cairo_font_options_destroy (options);

    cairo_select_font_face (cr,
			    "@cairo:",
			    CAIRO_FONT_SLANT_NORMAL,
			    CAIRO_FONT_WEIGHT_NORMAL);
    cairo_set_font_size (cr, font_size);
    scaled_font = cairo_get_scaled_font (cr);
    status = cairo_scaled_font_text_to_glyphs (scaled_font, 0., 0.,
					       text, -1,
					       &glyphs, &num_glyphs,
					       NULL, NULL,
					       NULL);
    if (status)
	return 0;

    glyphs_copy = cairo_glyph_allocate (num_glyphs);
    if (glyphs_copy == NULL) {
	cairo_glyph_free (glyphs);
	return 0;
    }

    cairo_scaled_font_glyph_extents (scaled_font,
				     glyphs, num_glyphs,
				     &extents);

    cairo_perf_timer_start ();

    while (loops--) {
	y = 0;
	do {
	    x = 0;
	    do {
		for (n = 0; n < num_glyphs; n++) {
		    glyphs_copy[n] = glyphs[n];
		    glyphs_copy[n].x += x;
		    glyphs_copy[n].y += y;
		}
		cairo_show_glyphs (cr, glyphs_copy, num_glyphs);

		x += extents.width;
	    } while (x < width);
	    y += extents.height;
	} while (y < height);
    }

    cairo_perf_timer_stop ();

    cairo_glyph_free (glyphs);
    cairo_glyph_free (glyphs_copy);

    return cairo_perf_timer_elapsed ();
}
Example #15
0
static cairo_perf_ticks_t
do_glyphs (cairo_t *cr, int width, int height, int loops)
{
    const char text[] = "the jay, pig, fox, zebra and my wolves quack";
    cairo_scaled_font_t *scaled_font;
    cairo_glyph_t *glyphs = NULL, *glyphs_copy;
    cairo_text_extents_t extents;
    cairo_status_t status;
    double x, y;
    int num_glyphs, n;

    cairo_set_font_size (cr, 9);
    scaled_font = cairo_get_scaled_font (cr);
    status = cairo_scaled_font_text_to_glyphs (scaled_font, 0., 0.,
					       text, -1,
					       &glyphs, &num_glyphs,
					       NULL, NULL,
					       NULL);
    if (status)
	return 0;

    glyphs_copy = cairo_glyph_allocate (num_glyphs);
    if (glyphs_copy == NULL) {
	cairo_glyph_free (glyphs);
	return 0;
    }

    cairo_scaled_font_glyph_extents (scaled_font,
				     glyphs, num_glyphs,
				     &extents);
    y = 0;

    cairo_perf_timer_start ();

    while (loops--) {
	do {
	    x = 0;
	    do {
		for (n = 0; n < num_glyphs; n++) {
		    glyphs_copy[n] = glyphs[n];
		    glyphs_copy[n].x += x;
		    glyphs_copy[n].y += y;
		}
		cairo_show_glyphs (cr, glyphs_copy, num_glyphs);
		if (cairo_status (cr) != CAIRO_STATUS_SUCCESS)
		    goto out;

		x += extents.width;
	    } while (x < width);
	    y += extents.height;
	} while (y < height);
    }
out:

    cairo_perf_timer_stop ();

    cairo_glyph_free (glyphs);
    cairo_glyph_free (glyphs_copy);

    return cairo_perf_timer_elapsed ();
}
static VALUE
cr_get_scaled_font (VALUE self)
{
  return CRSCALEDFONT2RVAL (cairo_get_scaled_font (_SELF));
}
Example #17
0
bool GlyphLayerDistanceField::render(
	cairo_t*       c,
	cairo_glyph_t* glyph,
	unsigned int   width,
	unsigned int   height
) {
	if(cairo_status(c) || !glyph) return false;

	unsigned int w = (width * _blockSize) + (_padding * _blockSize * 2);
	unsigned int h = (height * _blockSize) + (_padding * _blockSize * 2);

	// It distanceField needs to be square.
	if(w > h) h = w;

	else if(h > w) w = h;

	cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_A8, w, h);
	cairo_t*         cr      = cairo_create(surface);

	cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE);
	cairo_set_scaled_font(cr, cairo_get_scaled_font(c));
	cairo_scale(cr, _blockSize, _blockSize);
	cairo_translate(cr, _padding, _padding);
	cairo_glyph_path(cr, glyph, 1);
	cairo_fill(cr);

	cairo_surface_t* distanceField = osgPairo::createDistanceField(
		surface,
		_scanSize,
		_blockSize
	);

	// osgPairo::util::writeToPNG(distanceField, "distanceField.png");
	// osgPairo::util::writeToPNG(surface, "surface.png");

	cairo_surface_destroy(surface);
	cairo_destroy(cr);

	if(!distanceField) {
		OSG_WARN << "Unable to call osgPairo::util::createDistanceField." << std::endl;

		return false;
	}

	cairo_status_t err = cairo_surface_status(distanceField);

	if(cairo_surface_status(distanceField)) {
		OSG_WARN
			<< "Unable to call osgPairo::util::createDistanceField; error was: "
			<< cairo_status_to_string(err) << "."
			<< std::endl
		;

		return false;
	}

	cairo_set_source_surface(c, distanceField, -_padding, -_padding);
	cairo_paint(c);

	/*
	cairo_set_line_width(c, 1.0f);
	cairo_set_source_rgba(c, 1.0f, 1.0f, 1.0f, 1.0f);
	cairo_rectangle(c, -_padding + 0.5f, -_padding + 0.5f, (width + _padding * 2) - 0.5f, (height + _padding * 2) - 0.5f);
	cairo_stroke(c);
	*/

	cairo_surface_destroy(distanceField);

	return true;
}
/**
 * layout a text with provided parameters
 *
 * @param cr:			the cairo instance
 * @param text:			the text to layout
 * @param font:			the font to use to layout to
 * @param size:			the font size size of each char to layout
 * @param bounds:		the bounds of layouting
 * @param alignment:	the text alignment on cairo's buffer
 * @param layout:		the returned layouted text instance
 * @param-opt breakOnOverflow:	break the layouting if size overflow the provided bounds
 */
void TextLayouter::layout(cairo_t *cr, const char *text, Font_t *font, int32_t size, Rectangle bounds, const TextAlignment &alignment, LayoutedText *layout, bool breakOnOverflow)
{
	// check font validity
	if (!font) return;

	// get text length
	size_t textLen = strlen(text);

	// starting coordinates
	int x = bounds.x;
	int y = bounds.y;
	int lineStartX = x;

	// created the scaled font face
	cairo_set_font_face(cr, font->getFace());
	cairo_set_font_size(cr, size);
	cairo_scaled_font_t *scaledFace = cairo_get_scaled_font(cr);

	int line = 0;
	int lineHeight = size;

	// create glyphs for the text
	cairo_glyph_t *previousGlyphBuffer = layout->glyphBuffer;
	cairo_text_cluster_t *previousClusterBuffer = layout->clusterBuffer;

	cairo_text_cluster_flags_t clusterFlags;
	cairo_status_t stat = cairo_scaled_font_text_to_glyphs(scaledFace, 0, 0, text, textLen, &layout->glyphBuffer, &layout->glyphCount, &layout->clusterBuffer, &layout->clusterCount, &clusterFlags);

	// free old buffer
	if (previousGlyphBuffer != nullptr && layout->glyphBuffer != previousGlyphBuffer) free(previousGlyphBuffer);
	if (previousClusterBuffer != nullptr && layout->clusterBuffer != previousClusterBuffer) free(previousClusterBuffer);

	// clear layout entries
	layout->positions.clear();

	// perform layouting
	if (stat == CAIRO_STATUS_SUCCESS)
	{
		// positions in bytes and glyphs
		size_t bytePos = 0;
		size_t glyphPos = 0;

		// text extents
		cairo_text_extents_t extents;
		for (int i = 0; i < layout->clusterCount; i++)
		{
			cairo_text_cluster_t *cluster = &layout->clusterBuffer[i];
			cairo_glyph_t *glyphs = &layout->glyphBuffer[glyphPos];

			// create new position
			PositionedGlyph positioned;
			positioned.glyph = glyphs;
			positioned.glyphCount = cluster->num_glyphs;
			cairo_scaled_font_glyph_extents(scaledFace, positioned.glyph, positioned.glyphCount, &extents);

			positioned.advance.x = extents.x_advance;
			positioned.advance.y = extents.y_advance;
			positioned.size.width = extents.width;
			positioned.size.height = extents.height;

			// check if newline
			bool isNewline = false;
			if (cluster->num_bytes == 1 && text[bytePos] == '\n') isNewline = true;
			bool invisible = false;

			// Wouldn't match in line or is break character? Start next line
			if (isNewline || (breakOnOverflow && (x + positioned.size.width > bounds.width)))
			{
				if (isNewline) invisible = true;
				if (alignment == TextAlignment::RIGHT) rightAlign(layout, line, x - lineStartX, bounds);
				else if (alignment == TextAlignment::CENTER) centerAlign(layout, line, x - lineStartX, bounds);

				++line;
				x = bounds.x;
				lineStartX = x;
				y += lineHeight;
			}

			if (!invisible)
			{
				// Position
				positioned.line = line;
				positioned.position.x = x;
				positioned.position.y = y + lineHeight;

				// Add position
				layout->positions.push_back(positioned);

				// Jump to next
				x += positioned.advance.x;
			}

			// increase positions
			glyphPos += cluster->num_glyphs;
			bytePos += cluster->num_bytes;
		}
	}

	if (alignment == TextAlignment::RIGHT) rightAlign(layout, line, x - lineStartX, bounds);
	else if (alignment == TextAlignment::CENTER) centerAlign(layout, line, x - lineStartX, bounds);

	// Set text bounds
	#define BOUNDS_EMPTY 0xFFFFFF
	int tbTop = BOUNDS_EMPTY;
	int tbLeft = BOUNDS_EMPTY;
	int tbRight = 0;
	int tbBottom = 0;

	for (PositionedGlyph &p : layout->positions)
	{
		if (p.position.x < tbLeft) tbLeft = p.position.x;
		if (p.position.y < tbTop) tbTop = p.position.y;

		// get extents again
		int r = p.position.x + p.size.width;
		if (r > tbRight) tbRight = r;

		int b = p.position.y + p.size.height;
		if (b > tbBottom) tbBottom = b;
	}

	if (tbTop != BOUNDS_EMPTY && tbLeft != BOUNDS_EMPTY)
	{
		layout->textBounds.x = tbLeft;
		layout->textBounds.y = tbTop;
		layout->textBounds.width = tbRight - tbLeft;
		layout->textBounds.height = tbBottom - tbTop;
	}
}
Example #19
0
static cairo_time_t
do_hash_table (cairo_t *cr, int width, int height, int loops)
{
    /*
     * Microsoft C Compiler complains that:
     * error C2466: cannot allocate an array of constant size 0
     * so we add an unused element to make it happy
     */
    cairo_scaled_font_t *active_fonts[ACTIVE_FONTS + 1];
    cairo_matrix_t m;
    int i;

    cairo_matrix_init_identity (&m);

    /* Touch HOLDOVERS scaled fonts to fill up the holdover list. */
    for (i = 0; i < HOLDOVERS; i++) {
	m.yy = m.xx * (i + 1);
	cairo_set_font_matrix (cr, &m);
	cairo_get_scaled_font (cr);
    }

    /*
     * Reference some scaled fonts so that they will be kept in the
     * scaled fonts map. We want LIVE_ENTRIES elements in the font
     * map, but cairo keeps HOLDOVERS recently used fonts in it and we
     * will be activating a new font in the cr context, so we just
     * keep references to ACTIVE_FONTS fonts.
     *
     * Note: setting LIVE_ENTRIES == HOLDOVERS+1 means that we keep no
     * font in active_fonts and the slowness is caused by the holdover
     * fonts only.
     */
    for (i = 0; i < ACTIVE_FONTS; i++) {
	cairo_scaled_font_t *scaled_font;

	m.yy = m.xx * (i + 1);
	cairo_set_font_matrix (cr, &m);

	scaled_font = cairo_get_scaled_font (cr);
	active_fonts[i] = cairo_scaled_font_reference (scaled_font);
    }

    cairo_perf_timer_start ();
    cairo_perf_set_thread_aware (cr, FALSE);

    while (loops--) {
	if (loops == 0)
    	    cairo_perf_set_thread_aware (cr, TRUE); 
	m.xx += 1.0;

	/* Generate ITER new scaled fonts per loop */
	for (i = 0; i < ITER; i++) {
	    m.yy = m.xx * (i + 1);
	    cairo_set_font_matrix (cr, &m);
	    cairo_get_scaled_font (cr);
	}
    }

    cairo_perf_timer_stop ();

    for (i = 0; i < ACTIVE_FONTS; i++)
	cairo_scaled_font_destroy (active_fonts[i]);

    return cairo_perf_timer_elapsed ();
}
Example #20
0
ScaledFont*	Context::getScaledFont()
{
	return new ScaledFont( cairo_get_scaled_font( mCairo ) );
}
static cairo_test_status_t
draw (cairo_t *cr, int width, int height)
{
    const cairo_test_context_t *ctx = cairo_test_get_context (cr);
    cairo_surface_t *surface;
    cairo_t         *cr2;
    const char      *phase;
    const char	     string[] = "The quick brown fox jumps over the lazy dog.";
    cairo_text_extents_t extents, scaled_font_extents;
    cairo_status_t   status;
    int              errors = 0;

    surface = cairo_surface_create_similar (cairo_get_group_target (cr),
                                            CAIRO_CONTENT_COLOR, 100, 100);
    /* don't use cr accidentally */
    cr = NULL;
    cr2 = cairo_create (surface);
    cairo_surface_destroy (surface);

    cairo_set_line_width (cr2, 10);
    cairo_set_line_join (cr2, CAIRO_LINE_JOIN_MITER);
    cairo_set_miter_limit (cr2, 100);

    phase = "No path";
    errors += !check_extents (ctx, phase, cr2, FILL, EQUALS, 0, 0, 0, 0);
    errors += !check_extents (ctx, phase, cr2, STROKE, EQUALS, 0, 0, 0, 0);
    errors += !check_extents (ctx, phase, cr2, PATH, EQUALS, 0, 0, 0, 0);

    cairo_save (cr2);

    cairo_new_path (cr2);
    cairo_move_to (cr2, 200, 400);
    cairo_rel_line_to (cr2, 0., 0.);
    phase = "Degenerate line";
    errors += !check_extents (ctx, phase, cr2, FILL, EQUALS, 0, 0, 0, 0);
    errors += !check_extents (ctx, phase, cr2, STROKE, EQUALS, 0, 0, 0, 0);
    errors += !check_extents (ctx, phase, cr2, PATH, EQUALS, 200, 400, 0, 0);

    cairo_new_path (cr2);
    cairo_move_to (cr2, 200, 400);
    cairo_rel_curve_to (cr2, 0., 0., 0., 0., 0., 0.);
    phase = "Degenerate curve";
    errors += !check_extents (ctx, phase, cr2, FILL, EQUALS, 0, 0, 0, 0);
    errors += !check_extents (ctx, phase, cr2, STROKE, EQUALS, 0, 0, 0, 0);
    errors += !check_extents (ctx, phase, cr2, PATH, EQUALS, 200, 400, 0, 0);

    cairo_new_path (cr2);
    cairo_arc (cr2, 200, 400, 0., 0, 2 * M_PI);
    phase = "Degenerate arc (R=0)";
    errors += !check_extents (ctx, phase, cr2, FILL, EQUALS, 0, 0, 0, 0);
    errors += !check_extents (ctx, phase, cr2, STROKE, EQUALS, 0, 0, 0, 0);
    errors += !check_extents (ctx, phase, cr2, PATH, EQUALS, 200, 400, 0, 0);

    cairo_new_path (cr2);
    cairo_arc (cr2, 200, 400, 10., 0, 0);
    phase = "Degenerate arc (Θ=0)";
    errors += !check_extents (ctx, phase, cr2, FILL, EQUALS, 0, 0, 0, 0);
    errors += !check_extents (ctx, phase, cr2, STROKE, EQUALS, 0, 0, 0, 0);
    errors += !check_extents (ctx, phase, cr2, PATH, EQUALS, 200, 400, 0, 0);

    cairo_new_path (cr2);
    cairo_restore (cr2);

    /* Test that with CAIRO_LINE_CAP_ROUND, we get "dots" from
     * cairo_move_to; cairo_rel_line_to(0,0) */
    cairo_save (cr2);

    cairo_set_line_cap (cr2, CAIRO_LINE_CAP_ROUND);
    cairo_set_line_width (cr2, 20);

    cairo_move_to (cr2, 200, 400);
    cairo_rel_line_to (cr2, 0, 0);
    phase = "Single 'dot'";
    errors += !check_extents (ctx, phase, cr2, FILL, EQUALS, 0, 0, 0, 0);
    errors += !check_extents (ctx, phase, cr2, STROKE, EQUALS, 190, 390, 20, 20);
    errors += !check_extents (ctx, phase, cr2, PATH, EQUALS, 200, 400, 0, 0);

    /* Add another dot without starting a new path */
    cairo_move_to (cr2, 100, 500);
    cairo_rel_line_to (cr2, 0, 0);
    phase = "Multiple 'dots'";
    errors += !check_extents (ctx, phase, cr2, FILL, EQUALS, 0, 0, 0, 0);
    errors += !check_extents (ctx, phase, cr2, STROKE, EQUALS, 90, 390, 120, 120);
    errors += !check_extents (ctx, phase, cr2, PATH, EQUALS, 100, 400, 100, 100);

    cairo_new_path (cr2);

    cairo_restore (cr2);

    /* http://bugs.freedesktop.org/show_bug.cgi?id=7965 */
    phase = "A vertical, open path";
    cairo_save (cr2);
    cairo_set_line_cap (cr2, CAIRO_LINE_CAP_ROUND);
    cairo_set_line_join (cr2, CAIRO_LINE_JOIN_ROUND);
    cairo_move_to (cr2, 0, 180);
    cairo_line_to (cr2, 750, 180);
    errors += !check_extents (ctx, phase, cr2, FILL, EQUALS, 0, 0, 0, 0);
    errors += !check_extents (ctx, phase, cr2, STROKE, EQUALS, -5, 175, 760, 10);
    errors += !check_extents (ctx, phase, cr2, PATH, EQUALS, 0, 180, 755, 0);
    cairo_new_path (cr2);
    cairo_restore (cr2);

    phase = "Simple rect";
    cairo_save (cr2);
    cairo_rectangle (cr2, 10, 10, 80, 80);
    errors += !check_extents (ctx, phase, cr2, FILL, EQUALS, 10, 10, 80, 80);
    errors += !check_extents (ctx, phase, cr2, STROKE, EQUALS, 5, 5, 90, 90);
    errors += !check_extents (ctx, phase, cr2, PATH, EQUALS, 10, 10, 80, 80);
    cairo_new_path (cr2);
    cairo_restore (cr2);

    phase = "Two rects";
    cairo_save (cr2);
    cairo_rectangle (cr2, 10, 10, 10, 10);
    cairo_rectangle (cr2, 20, 20, 10, 10);
    errors += !check_extents (ctx, phase, cr2, FILL, EQUALS, 10, 10, 20, 20);
    errors += !check_extents (ctx, phase, cr2, STROKE, EQUALS, 5, 5, 30, 30);
    errors += !check_extents (ctx, phase, cr2, PATH, EQUALS, 10, 10, 20, 20);
    cairo_new_path (cr2);
    cairo_restore (cr2);

    phase = "Triangle";
    cairo_save (cr2);
    cairo_move_to (cr2, 10, 10);
    cairo_line_to (cr2, 90, 90);
    cairo_line_to (cr2, 90, 10);
    cairo_close_path (cr2);
    /* miter joins protrude 5*(1+sqrt(2)) above the top-left corner and to
       the right of the bottom-right corner */
    errors += !check_extents (ctx, phase, cr2, FILL, EQUALS, 10, 10, 80, 80);
    errors += !check_extents (ctx, phase, cr2, STROKE, CONTAINS, 0, 5, 95, 95);
    errors += !check_extents (ctx, phase, cr2, PATH, CONTAINS, 10, 10, 80, 80);
    cairo_new_path (cr2);
    cairo_restore (cr2);

    cairo_save (cr2);

    cairo_set_line_width (cr2, 4);

    cairo_rectangle (cr2, 10, 10, 30, 30);
    cairo_rectangle (cr2, 25, 10, 15, 30);

    cairo_set_fill_rule (cr2, CAIRO_FILL_RULE_EVEN_ODD);
    phase = "EVEN_ODD overlapping rectangles";
    errors += !check_extents (ctx, phase, cr2, FILL, EQUALS, 10, 10, 15, 30);
    errors += !check_extents (ctx, phase, cr2, STROKE, EQUALS, 8, 8, 34, 34);
    errors += !check_extents (ctx, phase, cr2, PATH, EQUALS, 10, 10, 30, 30);

    /* Test other fill rule with the same path. */

    cairo_set_fill_rule (cr2, CAIRO_FILL_RULE_WINDING);
    phase = "WINDING overlapping rectangles";
    errors += !check_extents (ctx, phase, cr2, FILL, EQUALS, 10, 10, 30, 30);
    errors += !check_extents (ctx, phase, cr2, STROKE, EQUALS, 8, 8, 34, 34);
    errors += !check_extents (ctx, phase, cr2, PATH, EQUALS, 10, 10, 30, 30);

    /* Now, change the direction of the second rectangle and test both
     * fill rules again. */
    cairo_new_path (cr2);
    cairo_rectangle (cr2, 10, 10, 30, 30);
    cairo_rectangle (cr2, 25, 40, 15, -30);

    cairo_set_fill_rule (cr2, CAIRO_FILL_RULE_EVEN_ODD);
    phase = "EVEN_ODD overlapping rectangles";
    errors += !check_extents (ctx, phase, cr2, FILL, EQUALS, 10, 10, 15, 30);
    errors += !check_extents (ctx, phase, cr2, STROKE, EQUALS, 8, 8, 34, 34);
    errors += !check_extents (ctx, phase, cr2, PATH, EQUALS, 10, 10, 30, 30);

    /* Test other fill rule with the same path. */

    cairo_set_fill_rule (cr2, CAIRO_FILL_RULE_WINDING);
    phase = "WINDING overlapping rectangles";
    errors += !check_extents (ctx, phase, cr2, FILL, EQUALS, 10, 10, 15, 30);
    errors += !check_extents (ctx, phase, cr2, STROKE, EQUALS, 8, 8, 34, 34);
    errors += !check_extents (ctx, phase, cr2, PATH, EQUALS, 10, 10, 30, 30);

    cairo_new_path (cr2);

    cairo_restore (cr2);

    /* http://bugs.freedesktop.org/show_bug.cgi?id=7245 */
    phase = "Arc";
    cairo_save (cr2);
    cairo_arc (cr2, 250.0, 250.0, 157.0, 5.147, 3.432);
    cairo_set_line_width (cr2, 154.0);
    errors += !check_extents (ctx, phase, cr2, STROKE, APPROX_EQUALS, 16, 38, 468, 446);
    cairo_new_path (cr2);
    cairo_restore (cr2);

    phase = "Text";
    cairo_save (cr2);
    cairo_select_font_face (cr2, "Bitstream Vera Sans",
			    CAIRO_FONT_SLANT_NORMAL,
			    CAIRO_FONT_WEIGHT_NORMAL);
    cairo_set_font_size (cr2, 12);
    cairo_text_extents (cr2, string, &extents);
    /* double check that the two methods of measuring the text agree... */
    cairo_scaled_font_text_extents (cairo_get_scaled_font (cr2),
				    string,
				    &scaled_font_extents);
    if (memcmp (&extents, &scaled_font_extents, sizeof (extents))) {
	cairo_test_log (ctx, "Error: cairo_text_extents() does not match cairo_scaled_font_text_extents() - font extents (%f, %f) x (%f, %f) should be (%f, %f) x (%f, %f)\n",
		        scaled_font_extents.x_bearing,
			scaled_font_extents.y_bearing,
			scaled_font_extents.width,
			scaled_font_extents.height,
			extents.x_bearing,
			extents.y_bearing,
			extents.width,
			extents.height);
	errors++;
    }

    cairo_move_to (cr2, -extents.x_bearing, -extents.y_bearing);
    cairo_text_path (cr2, string);
    cairo_set_line_width (cr2, 2.0);
    /* XXX: We'd like to be able to use EQUALS here, but currently
     * when hinting is enabled freetype returns integer extents. See
     * http://cairographics.org/todo */
    errors += !check_extents (ctx, phase, cr2, FILL, APPROX_EQUALS,
			      0, 0, extents.width, extents.height);
    errors += !check_extents (ctx, phase, cr2, STROKE, APPROX_EQUALS,
			      -1, -1, extents.width+2, extents.height+2);
    errors += !check_extents (ctx, phase, cr2, PATH, APPROX_EQUALS,
			      0, 0, extents.width, extents.height);
    cairo_new_path (cr2);
    cairo_restore (cr2);

    phase = "User space, simple scale, getting extents with same transform";
    cairo_save (cr2);
    cairo_scale (cr2, 2, 2);
    cairo_rectangle (cr2, 5, 5, 40, 40);
    errors += !check_extents (ctx, phase, cr2, FILL, EQUALS, 5, 5, 40, 40);
    errors += !check_extents (ctx, phase, cr2, STROKE, EQUALS, 0, 0, 50, 50);
    errors += !check_extents (ctx, phase, cr2, PATH, EQUALS, 5, 5, 40, 40);
    cairo_new_path (cr2);
    cairo_restore (cr2);

    phase = "User space, simple scale, getting extents with no transform";
    cairo_save (cr2);
    cairo_save (cr2);
    cairo_scale (cr2, 2, 2);
    cairo_rectangle (cr2, 5, 5, 40, 40);
    cairo_restore (cr2);
    errors += !check_extents (ctx, phase, cr2, FILL, EQUALS, 10, 10, 80, 80);
    errors += !check_extents (ctx, phase, cr2, STROKE, EQUALS, 5, 5, 90, 90);
    errors += !check_extents (ctx, phase, cr2, PATH, EQUALS, 10, 10, 80, 80);
    cairo_new_path (cr2);
    cairo_restore (cr2);

    phase = "User space, rotation, getting extents with transform";
    cairo_save (cr2);
    cairo_rectangle (cr2, -50, -50, 50, 50);
    cairo_rotate (cr2, -M_PI/4);
    /* the path in user space is now (nearly) the square rotated by
       45 degrees about the origin. Thus its x1 and x2 are both nearly 0.
       This should show any bugs where we just transform device-space
       x1,y1 and x2,y2 to get the extents. */
    /* The largest axis-aligned square inside the rotated path has
       side lengths 50*sqrt(2), so a bit over 35 on either side of
       the axes. With the stroke width added to the rotated path,
       the largest axis-aligned square is a bit over 38 on either side of
       the axes. */
    errors += !check_extents (ctx, phase, cr2, FILL, CONTAINS, -35, -35, 35, 35);
    errors += !check_extents (ctx, phase, cr2, STROKE, CONTAINS, -38, -38, 38, 38);
    errors += !check_extents (ctx, phase, cr2, PATH, CONTAINS, -35, -35, 35, 35);
    cairo_new_path (cr2);
    cairo_restore (cr2);

    status = cairo_status (cr2);
    cairo_destroy (cr2);

    if (status)
	return cairo_test_status_from_status (ctx, status);

    return errors == 0 ? CAIRO_TEST_SUCCESS : CAIRO_TEST_FAILURE;
}
Example #22
0
static PyObject *
pycairo_get_scaled_font (PycairoContext *o) {
  return PycairoScaledFont_FromScaledFont (
	   cairo_scaled_font_reference (cairo_get_scaled_font (o->ctx)));
}