Example #1
0
static cairo_status_t
_cairo_xml_emit_type42_font (cairo_xml_t *xml,
			     cairo_scaled_font_t *scaled_font)
{
    const cairo_scaled_font_backend_t *backend;
    cairo_output_stream_t *base64_stream;
    cairo_output_stream_t *zlib_stream;
    cairo_status_t status, status2;
    unsigned long size;
    uint32_t len;
    uint8_t *buf;

    backend = scaled_font->backend;
    if (backend->load_truetype_table == NULL)
	return CAIRO_INT_STATUS_UNSUPPORTED;

    size = 0;
    status = backend->load_truetype_table (scaled_font, 0, 0, NULL, &size);
    if (unlikely (status))
	return status;

    buf = malloc (size);
    if (unlikely (buf == NULL))
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);

    status = backend->load_truetype_table (scaled_font, 0, 0, buf, &size);
    if (unlikely (status)) {
	free (buf);
	return status;
    }

    _cairo_xml_printf_start (xml, "<font type='42' flags='%d' index='0'>",
		       _cairo_ft_scaled_font_get_load_flags (scaled_font));


    base64_stream = _cairo_base64_stream_create (xml->stream);
    len = size;
    _cairo_output_stream_write (base64_stream, &len, sizeof (len));

    zlib_stream = _cairo_deflate_stream_create (base64_stream);

    _cairo_output_stream_write (zlib_stream, buf, size);
    free (buf);

    status2 = _cairo_output_stream_destroy (zlib_stream);
    if (status == CAIRO_STATUS_SUCCESS)
	status = status2;

    status2 = _cairo_output_stream_destroy (base64_stream);
    if (status == CAIRO_STATUS_SUCCESS)
	status = status2;

    _cairo_xml_printf_end (xml, "</font>");

    return status;
}
Example #2
0
static void
_device_destroy (void *abstract_device)
{
    cairo_xml_t *xml = abstract_device;
    cairo_status_t status;

    status = _cairo_output_stream_destroy (xml->stream);

    free (xml);
}
static cairo_status_t
_cairo_pdf_operators_flush_glyphs (cairo_pdf_operators_t    *pdf_operators)
{
    cairo_output_stream_t *word_wrap_stream;
    cairo_status_t status, status2;
    int i;
    double x;

    if (pdf_operators->num_glyphs == 0)
	return CAIRO_STATUS_SUCCESS;

    word_wrap_stream = _word_wrap_stream_create (pdf_operators->stream, 72);
    status = _cairo_output_stream_get_status (word_wrap_stream);
    if (unlikely (status))
	return _cairo_output_stream_destroy (word_wrap_stream);

    /* Check if glyph advance used to position every glyph */
    x = pdf_operators->cur_x;
    for (i = 0; i < pdf_operators->num_glyphs; i++) {
	if (fabs(pdf_operators->glyphs[i].x_position - x) > GLYPH_POSITION_TOLERANCE)
	    break;
	x += pdf_operators->glyphs[i].x_advance;
    }
    if (i == pdf_operators->num_glyphs) {
	status = _cairo_pdf_operators_emit_glyph_string (pdf_operators,
							 word_wrap_stream);
    } else {
	status = _cairo_pdf_operators_emit_glyph_string_with_positioning (
	    pdf_operators, word_wrap_stream);
    }

    pdf_operators->num_glyphs = 0;
    pdf_operators->glyph_buf_x_pos = pdf_operators->cur_x;
    status2 = _cairo_output_stream_destroy (word_wrap_stream);
    if (status == CAIRO_STATUS_SUCCESS)
	status = status2;

    return status;
}
/* The line cap value is needed to workaround the fact that PostScript
 * and PDF semantics for stroking degenerate sub-paths do not match
 * cairo semantics. (PostScript draws something for any line cap
 * value, while cairo draws something only for round caps).
 *
 * When using this function to emit a path to be filled, rather than
 * stroked, simply pass %CAIRO_LINE_CAP_ROUND which will guarantee that
 * the stroke workaround will not modify the path being emitted.
 */
static cairo_status_t
_cairo_pdf_operators_emit_path (cairo_pdf_operators_t	*pdf_operators,
				const cairo_path_fixed_t*path,
				cairo_matrix_t          *path_transform,
				cairo_line_cap_t         line_cap)
{
    cairo_output_stream_t *word_wrap;
    cairo_status_t status, status2;
    pdf_path_info_t info;
    cairo_box_t box;

    word_wrap = _word_wrap_stream_create (pdf_operators->stream, 72);
    status = _cairo_output_stream_get_status (word_wrap);
    if (unlikely (status))
	return _cairo_output_stream_destroy (word_wrap);

    info.output = word_wrap;
    info.path_transform = path_transform;
    info.line_cap = line_cap;
    if (_cairo_path_fixed_is_rectangle (path, &box) &&
	((path_transform->xx == 0 && path_transform->yy == 0) ||
	 (path_transform->xy == 0 && path_transform->yx == 0))) {
	status = _cairo_pdf_path_rectangle (&info, &box);
    } else {
	status = _cairo_path_fixed_interpret (path,
					      _cairo_pdf_path_move_to,
					      _cairo_pdf_path_line_to,
					      _cairo_pdf_path_curve_to,
					      _cairo_pdf_path_close_path,
					      &info);
    }

    status2 = _cairo_output_stream_destroy (word_wrap);
    if (status == CAIRO_STATUS_SUCCESS)
	status = status2;

    return status;
}
Example #5
0
cairo_status_t
_cairo_type3_glyph_surface_analyze_glyph (void		     *abstract_surface,
					  unsigned long	      glyph_index)
{
    cairo_type3_glyph_surface_t *surface = abstract_surface;
    cairo_scaled_glyph_t *scaled_glyph;
    cairo_status_t status, status2;
    cairo_output_stream_t *null_stream;

    if (unlikely (surface->base.status))
	return surface->base.status;

    null_stream = _cairo_null_stream_create ();
    if (unlikely (null_stream->status))
	return null_stream->status;

    _cairo_type3_glyph_surface_set_stream (surface, null_stream);

    _cairo_scaled_font_freeze_cache (surface->scaled_font);
    status = _cairo_scaled_glyph_lookup (surface->scaled_font,
					 glyph_index,
					 CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE,
					 &scaled_glyph);

    if (_cairo_status_is_error (status))
	goto cleanup;

    if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
	status = CAIRO_STATUS_SUCCESS;
	goto cleanup;
    }

    status = _cairo_recording_surface_replay (scaled_glyph->recording_surface,
					      &surface->base);
    if (unlikely (status))
	goto cleanup;

    status = _cairo_pdf_operators_flush (&surface->pdf_operators);
    if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK)
	status = CAIRO_STATUS_SUCCESS;

cleanup:
    _cairo_scaled_font_thaw_cache (surface->scaled_font);

    status2 = _cairo_output_stream_destroy (null_stream);
    if (status == CAIRO_STATUS_SUCCESS)
	status = status2;

    return status;
}
cairo_status_t
_cairo_type3_glyph_surface_analyze_glyph (void		     *abstract_surface,
					  unsigned long	      glyph_index)
{
    cairo_type3_glyph_surface_t *surface = abstract_surface;
    cairo_scaled_glyph_t *scaled_glyph;
    cairo_status_t status, status2;
    cairo_output_stream_t *null_stream;

    null_stream = _cairo_null_stream_create ();
    _cairo_type3_glyph_surface_set_stream (surface, null_stream);
    status = _cairo_scaled_glyph_lookup (surface->scaled_font,
					 glyph_index,
					 CAIRO_SCALED_GLYPH_INFO_METRICS |
					 CAIRO_SCALED_GLYPH_INFO_META_SURFACE,
					 &scaled_glyph);
    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
	goto cleanup;

    if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
	status = CAIRO_STATUS_SUCCESS;
	goto cleanup;
    }

    status = _cairo_meta_surface_replay (scaled_glyph->meta_surface,
					 &surface->base);

    status = _cairo_pdf_operators_flush (&surface->pdf_operators);
    if (status)
	return status;

    if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK)
	status = CAIRO_STATUS_SUCCESS;

cleanup:
    status2 = _cairo_output_stream_destroy (null_stream);
    if (status)
	return status;

    return status2;
}
Example #7
0
static cairo_status_t
_cairo_xml_emit_image (cairo_xml_t *xml,
		       cairo_image_surface_t *image)
{
    cairo_output_stream_t *stream;
    cairo_status_t status;

    _cairo_xml_printf_start (xml,
			     "<image width='%d' height='%d' format='%s'>",
			     image->width, image->height,
			     _format_to_string (image->format));

    stream = _cairo_base64_stream_create (xml->stream);
    status = cairo_surface_write_to_png_stream (&image->base,
						_write_func, stream);
    assert (status == CAIRO_STATUS_SUCCESS);
    status = _cairo_output_stream_destroy (stream);
    if (unlikely (status))
	return status;

    _cairo_xml_printf_end (xml, "</image>");

    return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
_cairo_type3_glyph_surface_emit_glyph (void		     *abstract_surface,
				       cairo_output_stream_t *stream,
				       unsigned long	      glyph_index,
				       cairo_box_t           *bbox,
				       double                *width)
{
    cairo_type3_glyph_surface_t *surface = abstract_surface;
    cairo_scaled_glyph_t *scaled_glyph;
    cairo_status_t status, status2;
    double x_advance, y_advance;
    cairo_output_stream_t *mem_stream;
    cairo_matrix_t font_matrix_inverse;

    _cairo_type3_glyph_surface_set_stream (surface, stream);
    status = _cairo_scaled_glyph_lookup (surface->scaled_font,
					 glyph_index,
					 CAIRO_SCALED_GLYPH_INFO_METRICS |
					 CAIRO_SCALED_GLYPH_INFO_META_SURFACE,
					 &scaled_glyph);
    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
	return status;

    if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
	status = _cairo_scaled_glyph_lookup (surface->scaled_font,
					     glyph_index,
					     CAIRO_SCALED_GLYPH_INFO_METRICS,
					     &scaled_glyph);
	if (status)
	    return status;

	status = CAIRO_INT_STATUS_IMAGE_FALLBACK;
    }

    x_advance = scaled_glyph->metrics.x_advance;
    y_advance = scaled_glyph->metrics.y_advance;
    font_matrix_inverse = surface->scaled_font->font_matrix;
    status2 = cairo_matrix_invert (&font_matrix_inverse);

    /* The invertability of font_matrix is tested in
     * pdf_operators_show_glyphs before any glyphs are mappped to the
     * subset. */
    assert (status2 == CAIRO_STATUS_SUCCESS);

    cairo_matrix_transform_distance (&font_matrix_inverse, &x_advance, &y_advance);
    *width = x_advance;

    *bbox = scaled_glyph->bbox;
    _cairo_matrix_transform_bounding_box_fixed (&surface->scaled_font->scale_inverse,
						bbox, NULL);

    _cairo_output_stream_printf (surface->stream,
				 "%f 0 %f %f %f %f d1\n",
                                 x_advance,
				 _cairo_fixed_to_double (bbox->p1.x),
				 - _cairo_fixed_to_double (bbox->p2.y),
				 _cairo_fixed_to_double (bbox->p2.x),
				 - _cairo_fixed_to_double (bbox->p1.y));

    if (status == CAIRO_STATUS_SUCCESS) {
	mem_stream = _cairo_memory_stream_create ();
	_cairo_type3_glyph_surface_set_stream (surface, mem_stream);

	_cairo_output_stream_printf (surface->stream, "q\n");
	status = _cairo_meta_surface_replay (scaled_glyph->meta_surface,
					 &surface->base);

	status = _cairo_pdf_operators_flush (&surface->pdf_operators);
	if (status)
	    return status;

	_cairo_output_stream_printf (surface->stream, "Q\n");

	_cairo_type3_glyph_surface_set_stream (surface, stream);
	if (status == CAIRO_STATUS_SUCCESS)
	    _cairo_memory_stream_copy (mem_stream, stream);

	status2 = _cairo_output_stream_destroy (mem_stream);
	if (status2)
	    return status2;
    }

    if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK)
	status = _cairo_type3_glyph_surface_emit_fallback_image (surface, glyph_index);

    return status;
}