Пример #1
0
    size_t render(const string& text, double x = 0.0, double y = 0.0) override {
      cairo_glyph_t* glyphs{nullptr};
      cairo_text_cluster_t* clusters{nullptr};
      cairo_text_cluster_flags_t cf{};
      int nglyphs = 0, nclusters = 0;

      string utf8 = string(text);
      auto status = cairo_scaled_font_text_to_glyphs(
          m_scaled, x, y, utf8.c_str(), utf8.size(), &glyphs, &nglyphs, &clusters, &nclusters, &cf);

      if (status != CAIRO_STATUS_SUCCESS) {
        throw application_error(sstream() << "cairo_scaled_font_text_to_glyphs()" << cairo_status_to_string(status));
      }

      size_t bytes = 0;
      for (int g = 0; g < nglyphs; g++) {
        if (glyphs[g].index) {
          bytes += clusters[g].num_bytes;
        } else {
          break;
        }
      }

      if (bytes && bytes < text.size()) {
        cairo_glyph_free(glyphs);
        cairo_text_cluster_free(clusters);

        utf8 = text.substr(0, bytes);
        auto status = cairo_scaled_font_text_to_glyphs(
            m_scaled, x, y, utf8.c_str(), utf8.size(), &glyphs, &nglyphs, &clusters, &nclusters, &cf);

        if (status != CAIRO_STATUS_SUCCESS) {
          throw application_error(sstream() << "cairo_scaled_font_text_to_glyphs()" << cairo_status_to_string(status));
        }
      }

      if (bytes) {
        // auto lock = make_unique<utils::device_lock>(cairo_surface_get_device(cairo_get_target(m_cairo)));
        // if (lock.get()) {
        //   cairo_glyph_path(m_cairo, glyphs, nglyphs);
        // }

        cairo_text_extents_t extents{};
        cairo_scaled_font_glyph_extents(m_scaled, glyphs, nglyphs, &extents);
        cairo_show_text_glyphs(m_cairo, utf8.c_str(), utf8.size(), glyphs, nglyphs, clusters, nclusters, cf);
        cairo_fill(m_cairo);
        cairo_move_to(m_cairo, x + extents.x_advance, 0.0);
      }

      cairo_glyph_free(glyphs);
      cairo_text_cluster_free(clusters);

      return bytes;
    }
Пример #2
0
static VALUE
cr_show_text_glyphs (VALUE self, VALUE rb_utf8, VALUE rb_glyphs,
                     VALUE rb_clusters, VALUE rb_cluster_flags)
{
  cairo_t *cr;
  const char *utf8;
  int utf8_len;
  cairo_glyph_t *glyphs = NULL;
  int num_glyphs = 0;
  cairo_text_cluster_t *clusters = NULL;
  int num_clusters = 0;
  cairo_text_cluster_flags_t cluster_flags;

  cr = _SELF;
  utf8 = RSTRING_PTR (rb_utf8);
  utf8_len = RSTRING_LEN (rb_utf8);
  rb_cairo__glyphs_from_ruby_object (rb_glyphs, &glyphs, &num_glyphs);
  rb_cairo__text_clusters_from_ruby_object (rb_clusters,
                                            &clusters, &num_clusters);
  cluster_flags = RVAL2CRTEXTCLUSTERFLAGS (rb_cluster_flags);
  cairo_show_text_glyphs (cr, utf8, utf8_len,
                          glyphs, num_glyphs,
                          clusters, num_clusters,
                          cluster_flags);
  if (glyphs)
    cairo_glyph_free (glyphs);
  if (clusters)
    cairo_text_cluster_free (clusters);

  return self;
}
Пример #3
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;
}
static cairo_int_status_t
_cairo_user_text_to_glyphs (void		      *abstract_font,
			    double		       x,
			    double		       y,
			    const char		      *utf8,
			    int			       utf8_len,
			    cairo_glyph_t	     **glyphs,
			    int			       *num_glyphs,
			    cairo_text_cluster_t      **clusters,
			    int			       *num_clusters,
			    cairo_text_cluster_flags_t *cluster_flags)
{
    cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;

    cairo_user_scaled_font_t *scaled_font = abstract_font;
    cairo_user_font_face_t *face =
	(cairo_user_font_face_t *) scaled_font->base.font_face;

    if (face->scaled_font_methods.text_to_glyphs) {
	int i;
	cairo_glyph_t *orig_glyphs = *glyphs;
	int orig_num_glyphs = *num_glyphs;

	status = face->scaled_font_methods.text_to_glyphs (&scaled_font->base,
							   utf8, utf8_len,
							   glyphs, num_glyphs,
							   clusters, num_clusters, cluster_flags);

	if (status != CAIRO_STATUS_SUCCESS &&
	    status != CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED)
	    return status;

	if (status == CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED || *num_glyphs < 0) {
	    if (orig_glyphs != *glyphs) {
		cairo_glyph_free (*glyphs);
		*glyphs = orig_glyphs;
	    }
	    *num_glyphs = orig_num_glyphs;
	    return CAIRO_INT_STATUS_UNSUPPORTED;
	}

	/* Convert from font space to user space and add x,y */
	for (i = 0; i < *num_glyphs; i++) {
	    double gx = (*glyphs)[i].x;
	    double gy = (*glyphs)[i].y;

	    cairo_matrix_transform_point (&scaled_font->base.font_matrix,
					  &gx, &gy);

	    (*glyphs)[i].x = gx + x;
	    (*glyphs)[i].y = gy + y;
	}
    }

    return status;
}
Пример #5
0
static void
text_layout_destroy(struct text_layout *layout)
{
	if (layout->glyphs)
		cairo_glyph_free(layout->glyphs);

	if (layout->clusters)
		cairo_text_cluster_free(layout->clusters);

	cairo_scaled_font_destroy(layout->font);

	free(layout);
}
Пример #6
0
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 */
}
Пример #7
0
static void
text_layout_set_text(struct text_layout *layout,
		     const char *text)
{
	if (layout->glyphs)
		cairo_glyph_free(layout->glyphs);

	if (layout->clusters)
		cairo_text_cluster_free(layout->clusters);

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

	cairo_scaled_font_text_to_glyphs(layout->font, 0, 0, text, -1,
					 &layout->glyphs, &layout->num_glyphs,
					 &layout->clusters, &layout->num_clusters,
					 &layout->cluster_flags);
}
Пример #8
0
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 ();
}
Пример #9
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 ();
}