static void
cairo_gl_shader_emit_variable (cairo_output_stream_t *stream,
                               cairo_gl_var_type_t type,
                               cairo_gl_tex_t name)
{
    switch (type) {
    default:
        ASSERT_NOT_REACHED;
    case CAIRO_GL_VAR_NONE:
        break;
    case CAIRO_GL_VAR_TEXCOORDS:
        _cairo_output_stream_printf (stream,
				     "attribute vec4 MultiTexCoord%d;\n"
                                     "varying vec2 %s_texcoords;\n",
                                     name,
                                     operand_names[name]);
        break;
    case CAIRO_GL_VAR_TEXGEN:
        _cairo_output_stream_printf (stream,
				     "uniform mat3 %s_texgen;\n"
                                     "varying vec2 %s_texcoords;\n",
                                     operand_names[name],
                                     operand_names[name]);
        break;
    }
}
static cairo_status_t
_cairo_type3_glyph_surface_emit_image (cairo_type3_glyph_surface_t *surface,
				       cairo_image_surface_t       *image,
				       cairo_matrix_t              *image_matrix)
{
    cairo_status_t status;

    /* The only image type supported by Type 3 fonts are 1-bit masks */
    image = _cairo_image_surface_coerce_to_format (image, CAIRO_FORMAT_A1);
    status = image->base.status;
    if (unlikely (status))
	return status;

    _cairo_output_stream_printf (surface->stream,
				 "q %f %f %f %f %f %f cm\n",
				 image_matrix->xx,
				 image_matrix->xy,
				 image_matrix->yx,
				 image_matrix->yy,
				 image_matrix->x0,
				 image_matrix->y0);

    status = surface->emit_image (image, surface->stream);
    cairo_surface_destroy (&image->base);

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

    return status;
}
static cairo_status_t
_cairo_pdf_operators_begin_actualtext (cairo_pdf_operators_t *pdf_operators,
				       const char 	     *utf8,
				       int		      utf8_len)
{
    uint16_t *utf16;
    int utf16_len;
    cairo_status_t status;
    int i;

    _cairo_output_stream_printf (pdf_operators->stream, "/Span << /ActualText <feff");
    if (utf8_len) {
	status = _cairo_utf8_to_utf16 (utf8, utf8_len, &utf16, &utf16_len);
	if (unlikely (status))
	    return status;

	for (i = 0; i < utf16_len; i++) {
	    _cairo_output_stream_printf (pdf_operators->stream,
					 "%04x", (int) (utf16[i]));
	}
	free (utf16);
    }
    _cairo_output_stream_printf (pdf_operators->stream, "> >> BDC\n");

    return _cairo_output_stream_get_status (pdf_operators->stream);
}
Exemple #4
0
static void
cairo_gl_shader_emit_variable (cairo_output_stream_t *stream,
                               cairo_gl_var_type_t type,
                               cairo_gl_tex_t name,
                               cairo_bool_t use_atlas)
{
    switch (type) {
    default:
        ASSERT_NOT_REACHED;
    case CAIRO_GL_VAR_NONE:
        break;
    case CAIRO_GL_VAR_COLOR:
        _cairo_output_stream_printf (stream,
                                     "varying vec4 fragment_color;\n");
        break;
    case CAIRO_GL_VAR_TEXCOORDS:
        _cairo_output_stream_printf (stream,
                                     "varying vec2 %s_texcoords;\n",
                                     operand_names[name]);
        if (use_atlas)
            _cairo_output_stream_printf (stream,
                                         "varying vec2 %s_start_coords;\n"
                                         "varying vec2 %s_stop_coords;\n",
                                         operand_names[name], operand_names[name]);
        break;
    }
}
/*
 * Emits the wrap function used by an operand.
 *
 * In OpenGL ES 2.0, repeat wrap modes (GL_REPEAT and GL_MIRRORED REPEAT) are
 * only available for NPOT textures if the GL_OES_texture_npot is supported.
 * If GL_OES_texture_npot is not supported, we need to implement the wrapping
 * functionality in the shader.
 */
static void
_cairo_gl_shader_emit_wrap (cairo_gl_context_t *ctx,
			    cairo_output_stream_t *stream,
			    cairo_gl_operand_t *operand,
			    cairo_gl_tex_t name)
{
    const char *namestr = operand_names[name];
    cairo_extend_t extend = _cairo_gl_operand_get_extend (operand);

    _cairo_output_stream_printf (stream,
	"vec2 %s_wrap(vec2 coords)\n"
	"{\n",
	namestr);

    if (! ctx->has_npot_repeat &&
	(extend == CAIRO_EXTEND_REPEAT || extend == CAIRO_EXTEND_REFLECT))
    {
	if (extend == CAIRO_EXTEND_REPEAT) {
	    _cairo_output_stream_printf (stream,
		"    return fract(coords);\n");
	} else { /* CAIRO_EXTEND_REFLECT */
	    _cairo_output_stream_printf (stream,
		"    return mix(fract(coords), 1.0 - fract(coords), floor(mod(coords, 2.0)));\n");
	}
    }
    else
    {
	_cairo_output_stream_printf (stream, "    return coords;\n");
    }

    _cairo_output_stream_printf (stream, "}\n");
}
/* Emit the string of glyphs using the 'TJ' operator.
 *
 * The TJ operator takes an array of strings of glyphs. Each string of
 * glyphs is displayed using the glyph advances of each glyph to
 * position the glyphs. A relative adjustment to the glyph advance may
 * be specified by including the adjustment between two strings. The
 * adjustment is in units of text space * -1000.
 */
static cairo_status_t
_cairo_pdf_operators_emit_glyph_string_with_positioning (
    cairo_pdf_operators_t   *pdf_operators,
    cairo_output_stream_t   *stream)
{
    int i;

    _cairo_output_stream_printf (stream, "[%s", pdf_operators->is_latin ? "(" : "<");
    for (i = 0; i < pdf_operators->num_glyphs; i++) {
	if (pdf_operators->glyphs[i].x_position != pdf_operators->cur_x)
	{
	    double delta = pdf_operators->glyphs[i].x_position - pdf_operators->cur_x;
	    int rounded_delta;

	    delta = -1000.0*delta;
	    /* As the delta is in 1/1000 of a unit of text space,
	     * rounding to an integer should still provide sufficient
	     * precision. We round the delta before adding to Tm_x so
	     * that we keep track of the accumulated rounding error in
	     * the PDF interpreter and compensate for it when
	     * calculating subsequent deltas.
	     */
	    rounded_delta = _cairo_lround (delta);
	    if (abs(rounded_delta) < 3)
		rounded_delta = 0;
	    if (rounded_delta != 0) {
		if (pdf_operators->is_latin) {
		    _cairo_output_stream_printf (stream,
						 ")%d(",
						 rounded_delta);
		} else {
		    _cairo_output_stream_printf (stream,
						 ">%d<",
						 rounded_delta);
		}
	    }

	    /* Convert the rounded delta back to text
	     * space before adding to the current text
	     * position. */
	    delta = rounded_delta/-1000.0;
	    pdf_operators->cur_x += delta;
	}

	_cairo_pdf_operators_emit_glyph_index (pdf_operators,
					       stream,
					       pdf_operators->glyphs[i].glyph_index);
	pdf_operators->cur_x += pdf_operators->glyphs[i].x_advance;
    }
    _cairo_output_stream_printf (stream, "%s]TJ\n", pdf_operators->is_latin ? ")" : ">");

    return _cairo_output_stream_get_status (stream);
}
/* Use 'Tm' operator to set the PDF text matrix. */
static cairo_status_t
_cairo_pdf_operators_set_text_matrix (cairo_pdf_operators_t  *pdf_operators,
				      cairo_matrix_t         *matrix)
{
    cairo_matrix_t inverse;
    cairo_status_t status;

    /* We require the matrix to be invertable. */
    inverse = *matrix;
    status = cairo_matrix_invert (&inverse);
    if (unlikely (status))
	return status;

    pdf_operators->text_matrix = *matrix;
    pdf_operators->cur_x = 0;
    pdf_operators->cur_y = 0;
    pdf_operators->glyph_buf_x_pos = 0;
    _cairo_output_stream_printf (pdf_operators->stream,
				 "%f %f %f %f %f %f Tm\n",
				 pdf_operators->text_matrix.xx,
				 pdf_operators->text_matrix.yx,
				 pdf_operators->text_matrix.xy,
				 pdf_operators->text_matrix.yy,
				 pdf_operators->text_matrix.x0,
				 pdf_operators->text_matrix.y0);

    pdf_operators->cairo_to_pdftext = *matrix;
    status = cairo_matrix_invert (&pdf_operators->cairo_to_pdftext);
    assert (status == CAIRO_STATUS_SUCCESS);
    cairo_matrix_multiply (&pdf_operators->cairo_to_pdftext,
			   &pdf_operators->cairo_to_pdf,
			   &pdf_operators->cairo_to_pdftext);

    return _cairo_output_stream_get_status (pdf_operators->stream);
}
static cairo_status_t
_cairo_pdf_operators_end_actualtext (cairo_pdf_operators_t    *pdf_operators)
{
    _cairo_output_stream_printf (pdf_operators->stream, "EMC\n");

    return _cairo_output_stream_get_status (pdf_operators->stream);
}
/* Emit hexstring bytes up to either the end of the ASCII hexstring or the number
 * of columns remaining.
 */
static int
_word_wrap_stream_count_hexstring_up_to (word_wrap_stream_t *stream,
					 const unsigned char *data, int length)
{
    const unsigned char *s = data;
    int count = 0;
    cairo_bool_t newline = FALSE;

    while (length--) {
	count++;
	stream->column++;
	if (*s == '>') {
	    stream->state = WRAP_STATE_DELIMITER;
	    break;
	}

	if (stream->column > stream->max_column) {
	    newline = TRUE;
	    break;
	}
	s++;
    }

    if (count)
	_cairo_output_stream_write (stream->output, data, count);

    if (newline) {
	_cairo_output_stream_printf (stream->output, "\n");
	stream->column = 0;
    }

    return count;
}
/* Select the font using the 'Tf' operator. The font size is set to 1
 * as we use the 'Tm' operator to set the font scale.
 */
static cairo_status_t
_cairo_pdf_operators_set_font_subset (cairo_pdf_operators_t             *pdf_operators,
				      cairo_scaled_font_subsets_glyph_t *subset_glyph)
{
    cairo_status_t status;

    _cairo_output_stream_printf (pdf_operators->stream,
				 "/f-%d-%d 1 Tf\n",
				 subset_glyph->font_id,
				 subset_glyph->subset_id);
    if (pdf_operators->use_font_subset) {
	status = pdf_operators->use_font_subset (subset_glyph->font_id,
						 subset_glyph->subset_id,
						 pdf_operators->use_font_subset_closure);
	if (unlikely (status))
	    return status;
    }
    pdf_operators->font_id = subset_glyph->font_id;
    pdf_operators->subset_id = subset_glyph->subset_id;
    pdf_operators->is_latin = subset_glyph->is_latin;

    if (subset_glyph->is_composite)
	pdf_operators->hex_width = 4;
    else
	pdf_operators->hex_width = 2;

    return CAIRO_STATUS_SUCCESS;
}
Exemple #11
0
static cairo_status_t
cairo_gl_shader_get_vertex_source (cairo_gl_var_type_t src,
                                   cairo_gl_var_type_t mask,
                                   cairo_gl_var_type_t dest,
				   char **out)
{
    cairo_output_stream_t *stream = _cairo_memory_stream_create ();
    unsigned char *source;
    unsigned int length;
    cairo_status_t status;

    cairo_gl_shader_emit_variable (stream, src, CAIRO_GL_TEX_SOURCE);
    cairo_gl_shader_emit_variable (stream, mask, CAIRO_GL_TEX_MASK);

    _cairo_output_stream_printf (stream,
				 "void main()\n"
				 "{\n"
				 "    gl_Position = ftransform();\n");

    cairo_gl_shader_emit_vertex (stream, src, CAIRO_GL_TEX_SOURCE);
    cairo_gl_shader_emit_vertex (stream, mask, CAIRO_GL_TEX_MASK);

    _cairo_output_stream_write (stream,
				"}\n\0", 3);

    status = _cairo_memory_stream_destroy (stream, &source, &length);
    if (unlikely (status))
	return status;

    *out = (char *) source;
    return CAIRO_STATUS_SUCCESS;
}
Exemple #12
0
static cairo_status_t
cairo_gl_shader_get_fragment_source (GLuint tex_target,
                                     cairo_gl_shader_in_t in,
                                     cairo_gl_operand_type_t src,
                                     cairo_gl_operand_type_t mask,
                                     cairo_gl_operand_type_t dest,
				     char **out)
{
    cairo_output_stream_t *stream = _cairo_memory_stream_create ();
    unsigned char *source;
    unsigned int length;
    cairo_status_t status;

    cairo_gl_shader_emit_color (stream, tex_target, src, CAIRO_GL_TEX_SOURCE);
    cairo_gl_shader_emit_color (stream, tex_target, mask, CAIRO_GL_TEX_MASK);

    _cairo_output_stream_printf (stream,
        "void main()\n"
        "{\n");
    switch (in) {
    case CAIRO_GL_SHADER_IN_COUNT:
    default:
        ASSERT_NOT_REACHED;
    case CAIRO_GL_SHADER_IN_NORMAL:
        _cairo_output_stream_printf (stream,
            "    gl_FragColor = get_source() * get_mask().a;\n");
        break;
    case CAIRO_GL_SHADER_IN_CA_SOURCE:
        _cairo_output_stream_printf (stream,
            "    gl_FragColor = get_source() * get_mask();\n");
        break;
    case CAIRO_GL_SHADER_IN_CA_SOURCE_ALPHA:
        _cairo_output_stream_printf (stream,
            "    gl_FragColor = get_source().a * get_mask();\n");
        break;
    }

    _cairo_output_stream_write (stream,
                                "}\n\0", 3);

    status = _cairo_memory_stream_destroy (stream, &source, &length);
    if (unlikely (status))
        return status;

    *out = (char *) source;
    return CAIRO_STATUS_SUCCESS;
}
/* Emit the string of glyphs using the 'Tj' operator. This requires
 * that the glyphs are positioned at their natural glyph advances. */
static cairo_status_t
_cairo_pdf_operators_emit_glyph_string (cairo_pdf_operators_t   *pdf_operators,
					cairo_output_stream_t  	*stream)
{
    int i;

    _cairo_output_stream_printf (stream, "%s", pdf_operators->is_latin ? "(" : "<");
    for (i = 0; i < pdf_operators->num_glyphs; i++) {
	_cairo_pdf_operators_emit_glyph_index (pdf_operators,
					       stream,
					       pdf_operators->glyphs[i].glyph_index);
	pdf_operators->cur_x += pdf_operators->glyphs[i].x_advance;
    }
    _cairo_output_stream_printf (stream, "%sTj\n", pdf_operators->is_latin ? ")" : ">");

    return _cairo_output_stream_get_status (stream);
}
/* Emit the string of glyphs using the 'Tj' operator. This requires
 * that the glyphs are positioned at their natural glyph advances. */
static cairo_status_t
_cairo_pdf_operators_emit_glyph_string (cairo_pdf_operators_t   *pdf_operators,
					cairo_output_stream_t  	*stream)
{
    int i;

    _cairo_output_stream_printf (stream, "<");
    for (i = 0; i < pdf_operators->num_glyphs; i++) {
	_cairo_output_stream_printf (stream,
				     "%0*x",
				     pdf_operators->hex_width,
				     pdf_operators->glyphs[i].glyph_index);
	pdf_operators->cur_x += pdf_operators->glyphs[i].x_advance;
    }
    _cairo_output_stream_printf (stream, ">Tj\n");

    return _cairo_output_stream_get_status (stream);
}
Exemple #15
0
static cairo_status_t
cairo_gl_shader_get_vertex_source (cairo_gl_var_type_t src_type,
                                   cairo_gl_var_type_t mask_type,
                                   cairo_bool_t src_use_atlas,
                                   cairo_bool_t mask_use_atlas,
                                   cairo_bool_t use_coverage,
                                   cairo_gl_var_type_t dest,
                                   char **out)
{
    cairo_output_stream_t *stream = _cairo_memory_stream_create ();
    unsigned char *source;
    unsigned long length;
    cairo_status_t status;

    cairo_gl_shader_emit_variable (stream, src_type, CAIRO_GL_TEX_SOURCE,
				   src_use_atlas);
    cairo_gl_shader_emit_variable (stream, mask_type, CAIRO_GL_TEX_MASK,
				   mask_use_atlas);
    if (use_coverage)
	cairo_gl_shader_dcl_coverage (stream);

    _cairo_output_stream_printf (stream,
				 "attribute vec4 Vertex;\n"
				 "attribute vec4 Color;\n"
				 "attribute vec4 Coverage;\n"
				 "attribute vec4 MultiTexCoord0;\n"
				 "attribute vec4 MultiTexCoord1;\n"
				 "attribute vec2 StartCoords0;\n"
				 "attribute vec2 StartCoords1;\n"
				 "attribute vec2 StopCoords0;\n"
				 "attribute vec2 StopCoords1;\n"
				 "uniform mat4 ModelViewProjectionMatrix;\n"
				 "void main()\n"
				 "{\n"
				 "    gl_Position = ModelViewProjectionMatrix * Vertex;\n");

    cairo_gl_shader_emit_vertex (stream, src_type, CAIRO_GL_TEX_SOURCE);
    cairo_gl_shader_emit_vertex (stream, mask_type, CAIRO_GL_TEX_MASK);

    if (use_coverage)
	cairo_gl_shader_def_coverage (stream);

    if (src_use_atlas)
	cairo_gl_shader_def_use_atlas (stream, src_type, CAIRO_GL_TEX_SOURCE);
    if (mask_use_atlas)
	cairo_gl_shader_def_use_atlas (stream, mask_type, CAIRO_GL_TEX_MASK);

    _cairo_output_stream_write (stream,
				"}\n\0", 3);

    status = _cairo_memory_stream_destroy (stream, &source, &length);
    if (unlikely (status))
	return status;

    *out = (char *) source;
    return CAIRO_STATUS_SUCCESS;
}
static void
_cairo_pdf_operators_emit_glyph_index (cairo_pdf_operators_t *pdf_operators,
				       cairo_output_stream_t *stream,
				       unsigned int 	      glyph)
{
    if (pdf_operators->is_latin) {
	if (glyph == '(' || glyph == ')' || glyph == '\\')
	    _cairo_output_stream_printf (stream, "\\%c", glyph);
	else if (glyph >= 0x20 && glyph <= 0x7e)
	    _cairo_output_stream_printf (stream, "%c", glyph);
	else
	    _cairo_output_stream_printf (stream, "\\%03o", glyph);
    } else {
	_cairo_output_stream_printf (stream,
				     "%0*x",
				     pdf_operators->hex_width,
				     glyph);
    }
}
cairo_int_status_t
_cairo_pdf_operators_clip (cairo_pdf_operators_t	*pdf_operators,
			   const cairo_path_fixed_t	*path,
			   cairo_fill_rule_t		 fill_rule)
{
    const char *pdf_operator;
    cairo_status_t status;

    if (pdf_operators->in_text_object) {
	status = _cairo_pdf_operators_end_text (pdf_operators);
	if (unlikely (status))
	    return status;
    }

    if (! path->has_current_point) {
	/* construct an empty path */
	_cairo_output_stream_printf (pdf_operators->stream, "0 0 m ");
    } else {
	status = _cairo_pdf_operators_emit_path (pdf_operators,
						 path,
						 &pdf_operators->cairo_to_pdf,
						 CAIRO_LINE_CAP_ROUND);
	if (unlikely (status))
	    return status;
    }

    switch (fill_rule) {
    default:
	ASSERT_NOT_REACHED;
    case CAIRO_FILL_RULE_WINDING:
	pdf_operator = "W";
	break;
    case CAIRO_FILL_RULE_EVEN_ODD:
	pdf_operator = "W*";
	break;
    }

    _cairo_output_stream_printf (pdf_operators->stream,
				 "%s n\n",
				 pdf_operator);

    return _cairo_output_stream_get_status (pdf_operators->stream);
}
static cairo_status_t
_cairo_pdf_operators_begin_text (cairo_pdf_operators_t    *pdf_operators)
{
    _cairo_output_stream_printf (pdf_operators->stream, "BT\n");

    pdf_operators->in_text_object = TRUE;
    pdf_operators->num_glyphs = 0;
    pdf_operators->glyph_buf_x_pos = 0;

    return _cairo_output_stream_get_status (pdf_operators->stream);
}
Exemple #19
0
static void
cairo_gl_shader_emit_vertex (cairo_output_stream_t *stream,
                             cairo_gl_var_type_t type,
                             cairo_gl_tex_t name)
{
    switch (type) {
    default:
        ASSERT_NOT_REACHED;
    case CAIRO_GL_VAR_NONE:
        break;
    case CAIRO_GL_VAR_COLOR:
        _cairo_output_stream_printf (stream,
                                     "    fragment_color = Color;\n");
        break;
    case CAIRO_GL_VAR_TEXCOORDS:
        _cairo_output_stream_printf (stream,
                                     "    %s_texcoords = MultiTexCoord%d.xy;\n",
                                     operand_names[name], name);
        break;
    }
}
Exemple #20
0
static void
cairo_gl_shader_emit_variable (cairo_output_stream_t *stream,
                               cairo_gl_var_type_t type,
                               cairo_gl_tex_t name)
{
    switch (type) {
    default:
        ASSERT_NOT_REACHED;
    case CAIRO_GL_VAR_NONE:
        break;
    case CAIRO_GL_VAR_TEXCOORDS:
        _cairo_output_stream_printf (stream, 
                                     "varying vec2 %s_texcoords;\n", 
                                     operand_names[name]);
        break;
    case CAIRO_GL_VAR_COVERAGE:
        _cairo_output_stream_printf (stream, 
                                     "varying float %s_coverage;\n", 
                                     operand_names[name]);
        break;
    }
}
Exemple #21
0
static void
cairo_gl_shader_def_use_atlas (cairo_output_stream_t *stream,
                               cairo_gl_var_type_t type,
                               cairo_gl_tex_t name)
{
    if (type == CAIRO_GL_VAR_TEXCOORDS) {
            _cairo_output_stream_printf (stream,
					 "    %s_start_coords = StartCoords%d.xy;\n"
					 "    %s_stop_coords = StopCoords%d.xy;\n",
					 operand_names[name], name,
					 operand_names[name], name);
    }
}
static cairo_status_t
_cairo_type3_glyph_surface_emit_image (cairo_type3_glyph_surface_t *surface,
				       cairo_image_surface_t       *image,
				       cairo_matrix_t              *image_matrix)
{
    cairo_status_t status;
    cairo_image_surface_t *image_mask;

    /* The only image type supported by Type 3 fonts are 1-bit image
     * masks */
    if (image->format == CAIRO_FORMAT_A1) {
	image_mask = image;
    } else {
	image_mask = _cairo_image_surface_clone (image, CAIRO_FORMAT_A1);
	status = cairo_surface_status (&image->base);
	if (status)
	    return status;
    }

    _cairo_output_stream_printf (surface->stream,
				 "q %f %f %f %f %f %f cm\n",
				 image_matrix->xx,
				 image_matrix->xy,
				 image_matrix->yx,
				 image_matrix->yy,
				 image_matrix->x0,
				 image_matrix->y0);

    status = surface->emit_image (image_mask, surface->stream);

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

    if (image_mask != image)
	cairo_surface_destroy (&image_mask->base);

    return status;
}
cairo_status_t
_cairo_type3_glyph_surface_emit_notdef_glyph (void		    *abstract_surface,
					      cairo_output_stream_t *stream,
					      cairo_box_t           *bbox,
					      double                *width)
{
    bbox->p1.x = 0;
    bbox->p1.y = 0;
    bbox->p2.x = 0;
    bbox->p2.y = 0;
    *width = 0.0;
    _cairo_output_stream_printf (stream, "0 0 0 0 0 0 d1\n");

    return CAIRO_STATUS_SUCCESS;
}
cairo_int_status_t
_cairo_pdf_operators_tag_end (cairo_pdf_operators_t *pdf_operators)
{
    cairo_status_t status;

    if (pdf_operators->in_text_object) {
	status = _cairo_pdf_operators_end_text (pdf_operators);
	if (unlikely (status))
	    return status;
    }

    _cairo_output_stream_printf (pdf_operators->stream, "EMC\n");

    return _cairo_output_stream_get_status (pdf_operators->stream);
}
static cairo_status_t
_cairo_pdf_operators_end_text (cairo_pdf_operators_t    *pdf_operators)
{
    cairo_status_t status;

    status = _cairo_pdf_operators_flush_glyphs (pdf_operators);
    if (unlikely (status))
	return status;

    _cairo_output_stream_printf (pdf_operators->stream, "ET\n");

    pdf_operators->in_text_object = FALSE;

    return _cairo_output_stream_get_status (pdf_operators->stream);
}
static cairo_status_t
_word_wrap_stream_write (cairo_output_stream_t  *base,
			 const unsigned char	*data,
			 unsigned int		 length)
{
    word_wrap_stream_t *stream = (word_wrap_stream_t *) base;
    int count;

    while (length) {
	switch (stream->state) {
	case WRAP_STATE_WORD:
	    count = _word_wrap_stream_count_word_up_to (stream, data, length);
	    break;
	case WRAP_STATE_HEXSTRING:
	    count = _word_wrap_stream_count_hexstring_up_to (stream, data, length);
	    break;
	case WRAP_STATE_STRING:
	    count = _word_wrap_stream_count_string_up_to (stream, data, length);
	    break;
	case WRAP_STATE_DELIMITER:
	    count = 1;
	    stream->column++;
	    if (*data == '\n' || stream->column >= stream->max_column) {
		_cairo_output_stream_printf (stream->output, "\n");
		stream->column = 0;
	    }
	    if (*data == '<') {
		stream->state = WRAP_STATE_HEXSTRING;
	    } else if (*data == '(') {
		stream->state = WRAP_STATE_STRING;
	    } else if (!_cairo_isspace (*data)) {
		stream->state = WRAP_STATE_WORD;
	    }
	    if (*data != '\n')
		_cairo_output_stream_write (stream->output, data, 1);
	    break;

	default:
	    ASSERT_NOT_REACHED;
	    count = length;
	    break;
	}
	data += count;
	length -= count;
    }

    return _cairo_output_stream_get_status (stream->output);
}
static cairo_status_t
_cairo_pdf_path_move_to (void *closure,
			 const cairo_point_t *point)
{
    pdf_path_info_t *info = closure;
    double x = _cairo_fixed_to_double (point->x);
    double y = _cairo_fixed_to_double (point->y);

    info->last_move_to_point = *point;
    info->has_sub_path = FALSE;
    cairo_matrix_transform_point (info->path_transform, &x, &y);
    _cairo_output_stream_printf (info->output,
				 "%g %g m ", x, y);

    return _cairo_output_stream_get_status (info->output);
}
static cairo_status_t
_cairo_pdf_path_close_path (void *closure)
{
    pdf_path_info_t *info = closure;

    if (info->line_cap != CAIRO_LINE_CAP_ROUND &&
	! info->has_sub_path)
    {
	return CAIRO_STATUS_SUCCESS;
    }

    _cairo_output_stream_printf (info->output,
				 "h\n");

    return _cairo_output_stream_get_status (info->output);
}
static cairo_status_t
_cairo_pdf_path_rectangle (pdf_path_info_t *info, cairo_box_t *box)
{
    double x1 = _cairo_fixed_to_double (box->p1.x);
    double y1 = _cairo_fixed_to_double (box->p1.y);
    double x2 = _cairo_fixed_to_double (box->p2.x);
    double y2 = _cairo_fixed_to_double (box->p2.y);

    cairo_matrix_transform_point (info->path_transform, &x1, &y1);
    cairo_matrix_transform_point (info->path_transform, &x2, &y2);
    _cairo_output_stream_printf (info->output,
				 "%g %g %g %g re ",
				 x1, y1, x2 - x1, y2 - y1);

    return _cairo_output_stream_get_status (info->output);
}
static cairo_int_status_t
_cairo_type3_glyph_surface_intersect_clip_path (void		   *abstract_surface,
						cairo_path_fixed_t *path,
						cairo_fill_rule_t   fill_rule,
						double		    tolerance,
						cairo_antialias_t   antialias)
{
    cairo_type3_glyph_surface_t *surface = abstract_surface;

    if (path == NULL) {
	_cairo_output_stream_printf (surface->stream, "Q q\n");
	return CAIRO_STATUS_SUCCESS;
    }

    return _cairo_pdf_operators_clip (&surface->pdf_operators,
				      path,
				      fill_rule);
}