1 /* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
2 /* cairo - a vector graphics library with display and print output
4 * Copyright © 2004 Red Hat, Inc
5 * Copyright © 2006 Red Hat, Inc
6 * Copyright © 2007, 2008 Adrian Johnson
8 * This library is free software; you can redistribute it and/or
9 * modify it either under the terms of the GNU Lesser General Public
10 * License version 2.1 as published by the Free Software Foundation
11 * (the "LGPL") or, at your option, under the terms of the Mozilla
12 * Public License Version 1.1 (the "MPL"). If you do not alter this
13 * notice, a recipient may use your version of this file under either
14 * the MPL or the LGPL.
16 * You should have received a copy of the LGPL along with this library
17 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
19 * You should have received a copy of the MPL along with this library
20 * in the file COPYING-MPL-1.1
22 * The contents of this file are subject to the Mozilla Public License
23 * Version 1.1 (the "License"); you may not use this file except in
24 * compliance with the License. You may obtain a copy of the License at
25 * http://www.mozilla.org/MPL/
27 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
28 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
29 * the specific language governing rights and limitations.
31 * The Original Code is the cairo graphics library.
33 * The Initial Developer of the Original Code is University of Southern
37 * Kristian Høgsberg <krh@redhat.com>
38 * Carl Worth <cworth@cworth.org>
39 * Adrian Johnson <ajohnson@redneon.com>
44 #if CAIRO_HAS_PDF_OPERATORS
46 #include "cairo-error-private.h"
47 #include "cairo-pdf-operators-private.h"
48 #include "cairo-path-fixed-private.h"
49 #include "cairo-output-stream-private.h"
50 #include "cairo-scaled-font-subsets-private.h"
53 _cairo_pdf_operators_end_text (cairo_pdf_operators_t
*pdf_operators
);
57 _cairo_pdf_operators_init (cairo_pdf_operators_t
*pdf_operators
,
58 cairo_output_stream_t
*stream
,
59 cairo_matrix_t
*cairo_to_pdf
,
60 cairo_scaled_font_subsets_t
*font_subsets
,
63 pdf_operators
->stream
= stream
;
64 pdf_operators
->cairo_to_pdf
= *cairo_to_pdf
;
65 pdf_operators
->font_subsets
= font_subsets
;
66 pdf_operators
->ps_output
= ps
;
67 pdf_operators
->use_font_subset
= NULL
;
68 pdf_operators
->use_font_subset_closure
= NULL
;
69 pdf_operators
->in_text_object
= FALSE
;
70 pdf_operators
->num_glyphs
= 0;
71 pdf_operators
->has_line_style
= FALSE
;
72 pdf_operators
->use_actual_text
= FALSE
;
76 _cairo_pdf_operators_fini (cairo_pdf_operators_t
*pdf_operators
)
78 return _cairo_pdf_operators_flush (pdf_operators
);
82 _cairo_pdf_operators_set_font_subsets_callback (cairo_pdf_operators_t
*pdf_operators
,
83 cairo_pdf_operators_use_font_subset_t use_font_subset
,
86 pdf_operators
->use_font_subset
= use_font_subset
;
87 pdf_operators
->use_font_subset_closure
= closure
;
90 /* Change the output stream to a different stream.
91 * _cairo_pdf_operators_flush() should always be called before calling
95 _cairo_pdf_operators_set_stream (cairo_pdf_operators_t
*pdf_operators
,
96 cairo_output_stream_t
*stream
)
98 pdf_operators
->stream
= stream
;
99 pdf_operators
->has_line_style
= FALSE
;
103 _cairo_pdf_operators_set_cairo_to_pdf_matrix (cairo_pdf_operators_t
*pdf_operators
,
104 cairo_matrix_t
*cairo_to_pdf
)
106 pdf_operators
->cairo_to_pdf
= *cairo_to_pdf
;
107 pdf_operators
->has_line_style
= FALSE
;
111 _cairo_pdf_operators_enable_actual_text (cairo_pdf_operators_t
*pdf_operators
,
114 pdf_operators
->use_actual_text
= enable
;
117 /* Finish writing out any pending commands to the stream. This
118 * function must be called by the surface before emitting anything
119 * into the PDF stream.
121 * pdf_operators may leave the emitted PDF for some operations
122 * unfinished in case subsequent operations can be merged. This
123 * function will finish off any incomplete operation so the stream
124 * will be in a state where the surface may emit its own PDF
125 * operations (eg changing patterns).
129 _cairo_pdf_operators_flush (cairo_pdf_operators_t
*pdf_operators
)
131 cairo_status_t status
= CAIRO_STATUS_SUCCESS
;
133 if (pdf_operators
->in_text_object
)
134 status
= _cairo_pdf_operators_end_text (pdf_operators
);
139 /* Reset the known graphics state of the PDF consumer. ie no
140 * assumptions will be made about the state. The next time a
141 * particular graphics state is required (eg line width) the state
142 * operator is always emitted and then remembered for subsequent
145 * This should be called when starting a new stream or after emitting
146 * the 'Q' operator (where pdf-operators functions were called inside
150 _cairo_pdf_operators_reset (cairo_pdf_operators_t
*pdf_operators
)
152 pdf_operators
->has_line_style
= FALSE
;
155 /* A word wrap stream can be used as a filter to do word wrapping on
156 * top of an existing output stream. The word wrapping is quite
157 * simple, using isspace to determine characters that separate
158 * words. Any word that will cause the column count exceed the given
159 * max_column will have a '\n' character emitted before it.
161 * The stream is careful to maintain integrity for words that cross
162 * the boundary from one call to write to the next.
164 * Note: This stream does not guarantee that the output will never
165 * exceed max_column. In particular, if a single word is larger than
166 * max_column it will not be broken up.
169 typedef enum _cairo_word_wrap_state
{
170 WRAP_STATE_DELIMITER
,
174 } cairo_word_wrap_state_t
;
177 typedef struct _word_wrap_stream
{
178 cairo_output_stream_t base
;
179 cairo_output_stream_t
*output
;
181 cairo_bool_t ps_output
;
183 cairo_word_wrap_state_t state
;
184 cairo_bool_t in_escape
;
186 } word_wrap_stream_t
;
190 /* Emit word bytes up to the next delimiter character */
192 _word_wrap_stream_count_word_up_to (word_wrap_stream_t
*stream
,
193 const unsigned char *data
, int length
)
195 const unsigned char *s
= data
;
199 if (_cairo_isspace (*s
) || *s
== '<' || *s
== '(') {
200 stream
->state
= WRAP_STATE_DELIMITER
;
210 _cairo_output_stream_write (stream
->output
, data
, count
);
216 /* Emit hexstring bytes up to either the end of the ASCII hexstring or the number
217 * of columns remaining.
220 _word_wrap_stream_count_hexstring_up_to (word_wrap_stream_t
*stream
,
221 const unsigned char *data
, int length
)
223 const unsigned char *s
= data
;
225 cairo_bool_t newline
= FALSE
;
231 stream
->state
= WRAP_STATE_DELIMITER
;
235 if (stream
->column
> stream
->max_column
) {
243 _cairo_output_stream_write (stream
->output
, data
, count
);
246 _cairo_output_stream_printf (stream
->output
, "\n");
253 /* Count up to either the end of the string or the number of columns
257 _word_wrap_stream_count_string_up_to (word_wrap_stream_t
*stream
,
258 const unsigned char *data
, int length
)
260 const unsigned char *s
= data
;
262 cairo_bool_t newline
= FALSE
;
267 if (!stream
->in_escape
) {
269 stream
->state
= WRAP_STATE_DELIMITER
;
273 stream
->in_escape
= TRUE
;
274 stream
->escape_digits
= 0;
275 } else if (stream
->ps_output
&& stream
->column
> stream
->max_column
) {
280 if (!_cairo_isdigit(*s
) || ++stream
->escape_digits
== 3)
281 stream
->in_escape
= FALSE
;
287 _cairo_output_stream_write (stream
->output
, data
, count
);
290 _cairo_output_stream_printf (stream
->output
, "\\\n");
297 static cairo_status_t
298 _word_wrap_stream_write (cairo_output_stream_t
*base
,
299 const unsigned char *data
,
302 word_wrap_stream_t
*stream
= (word_wrap_stream_t
*) base
;
306 switch (stream
->state
) {
307 case WRAP_STATE_WORD
:
308 count
= _word_wrap_stream_count_word_up_to (stream
, data
, length
);
310 case WRAP_STATE_HEXSTRING
:
311 count
= _word_wrap_stream_count_hexstring_up_to (stream
, data
, length
);
313 case WRAP_STATE_STRING
:
314 count
= _word_wrap_stream_count_string_up_to (stream
, data
, length
);
316 case WRAP_STATE_DELIMITER
:
319 if (*data
== '\n' || stream
->column
>= stream
->max_column
) {
320 _cairo_output_stream_printf (stream
->output
, "\n");
322 } else if (*data
== '<') {
323 stream
->state
= WRAP_STATE_HEXSTRING
;
324 } else if (*data
== '(') {
325 stream
->state
= WRAP_STATE_STRING
;
326 } else if (!_cairo_isspace (*data
)) {
327 stream
->state
= WRAP_STATE_WORD
;
330 _cairo_output_stream_write (stream
->output
, data
, 1);
342 return _cairo_output_stream_get_status (stream
->output
);
345 static cairo_status_t
346 _word_wrap_stream_close (cairo_output_stream_t
*base
)
348 word_wrap_stream_t
*stream
= (word_wrap_stream_t
*) base
;
350 return _cairo_output_stream_get_status (stream
->output
);
353 static cairo_output_stream_t
*
354 _word_wrap_stream_create (cairo_output_stream_t
*output
, cairo_bool_t ps
, int max_column
)
356 word_wrap_stream_t
*stream
;
359 return _cairo_output_stream_create_in_error (output
->status
);
361 stream
= malloc (sizeof (word_wrap_stream_t
));
362 if (unlikely (stream
== NULL
)) {
363 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY
);
364 return (cairo_output_stream_t
*) &_cairo_output_stream_nil
;
367 _cairo_output_stream_init (&stream
->base
,
368 _word_wrap_stream_write
,
370 _word_wrap_stream_close
);
371 stream
->output
= output
;
372 stream
->max_column
= max_column
;
373 stream
->ps_output
= ps
;
375 stream
->state
= WRAP_STATE_DELIMITER
;
376 stream
->in_escape
= FALSE
;
377 stream
->escape_digits
= 0;
379 return &stream
->base
;
382 typedef struct _pdf_path_info
{
383 cairo_output_stream_t
*output
;
384 cairo_matrix_t
*path_transform
;
385 cairo_line_cap_t line_cap
;
386 cairo_point_t last_move_to_point
;
387 cairo_bool_t has_sub_path
;
390 static cairo_status_t
391 _cairo_pdf_path_move_to (void *closure
,
392 const cairo_point_t
*point
)
394 pdf_path_info_t
*info
= closure
;
395 double x
= _cairo_fixed_to_double (point
->x
);
396 double y
= _cairo_fixed_to_double (point
->y
);
398 info
->last_move_to_point
= *point
;
399 info
->has_sub_path
= FALSE
;
400 cairo_matrix_transform_point (info
->path_transform
, &x
, &y
);
401 _cairo_output_stream_printf (info
->output
,
404 return _cairo_output_stream_get_status (info
->output
);
407 static cairo_status_t
408 _cairo_pdf_path_line_to (void *closure
,
409 const cairo_point_t
*point
)
411 pdf_path_info_t
*info
= closure
;
412 double x
= _cairo_fixed_to_double (point
->x
);
413 double y
= _cairo_fixed_to_double (point
->y
);
415 if (info
->line_cap
!= CAIRO_LINE_CAP_ROUND
&&
416 ! info
->has_sub_path
&&
417 point
->x
== info
->last_move_to_point
.x
&&
418 point
->y
== info
->last_move_to_point
.y
)
420 return CAIRO_STATUS_SUCCESS
;
423 info
->has_sub_path
= TRUE
;
424 cairo_matrix_transform_point (info
->path_transform
, &x
, &y
);
425 _cairo_output_stream_printf (info
->output
,
428 return _cairo_output_stream_get_status (info
->output
);
431 static cairo_status_t
432 _cairo_pdf_path_curve_to (void *closure
,
433 const cairo_point_t
*b
,
434 const cairo_point_t
*c
,
435 const cairo_point_t
*d
)
437 pdf_path_info_t
*info
= closure
;
438 double bx
= _cairo_fixed_to_double (b
->x
);
439 double by
= _cairo_fixed_to_double (b
->y
);
440 double cx
= _cairo_fixed_to_double (c
->x
);
441 double cy
= _cairo_fixed_to_double (c
->y
);
442 double dx
= _cairo_fixed_to_double (d
->x
);
443 double dy
= _cairo_fixed_to_double (d
->y
);
445 info
->has_sub_path
= TRUE
;
446 cairo_matrix_transform_point (info
->path_transform
, &bx
, &by
);
447 cairo_matrix_transform_point (info
->path_transform
, &cx
, &cy
);
448 cairo_matrix_transform_point (info
->path_transform
, &dx
, &dy
);
449 _cairo_output_stream_printf (info
->output
,
450 "%g %g %g %g %g %g c ",
451 bx
, by
, cx
, cy
, dx
, dy
);
452 return _cairo_output_stream_get_status (info
->output
);
455 static cairo_status_t
456 _cairo_pdf_path_close_path (void *closure
)
458 pdf_path_info_t
*info
= closure
;
460 if (info
->line_cap
!= CAIRO_LINE_CAP_ROUND
&&
461 ! info
->has_sub_path
)
463 return CAIRO_STATUS_SUCCESS
;
466 _cairo_output_stream_printf (info
->output
,
469 return _cairo_output_stream_get_status (info
->output
);
472 static cairo_status_t
473 _cairo_pdf_path_rectangle (pdf_path_info_t
*info
, cairo_box_t
*box
)
475 double x1
= _cairo_fixed_to_double (box
->p1
.x
);
476 double y1
= _cairo_fixed_to_double (box
->p1
.y
);
477 double x2
= _cairo_fixed_to_double (box
->p2
.x
);
478 double y2
= _cairo_fixed_to_double (box
->p2
.y
);
480 cairo_matrix_transform_point (info
->path_transform
, &x1
, &y1
);
481 cairo_matrix_transform_point (info
->path_transform
, &x2
, &y2
);
482 _cairo_output_stream_printf (info
->output
,
484 x1
, y1
, x2
- x1
, y2
- y1
);
486 return _cairo_output_stream_get_status (info
->output
);
489 /* The line cap value is needed to workaround the fact that PostScript
490 * and PDF semantics for stroking degenerate sub-paths do not match
491 * cairo semantics. (PostScript draws something for any line cap
492 * value, while cairo draws something only for round caps).
494 * When using this function to emit a path to be filled, rather than
495 * stroked, simply pass %CAIRO_LINE_CAP_ROUND which will guarantee that
496 * the stroke workaround will not modify the path being emitted.
498 static cairo_status_t
499 _cairo_pdf_operators_emit_path (cairo_pdf_operators_t
*pdf_operators
,
500 const cairo_path_fixed_t
*path
,
501 cairo_matrix_t
*path_transform
,
502 cairo_line_cap_t line_cap
)
504 cairo_output_stream_t
*word_wrap
;
505 cairo_status_t status
, status2
;
506 pdf_path_info_t info
;
509 word_wrap
= _word_wrap_stream_create (pdf_operators
->stream
, pdf_operators
->ps_output
, 72);
510 status
= _cairo_output_stream_get_status (word_wrap
);
511 if (unlikely (status
))
512 return _cairo_output_stream_destroy (word_wrap
);
514 info
.output
= word_wrap
;
515 info
.path_transform
= path_transform
;
516 info
.line_cap
= line_cap
;
517 if (_cairo_path_fixed_is_rectangle (path
, &box
) &&
518 ((path_transform
->xx
== 0 && path_transform
->yy
== 0) ||
519 (path_transform
->xy
== 0 && path_transform
->yx
== 0))) {
520 status
= _cairo_pdf_path_rectangle (&info
, &box
);
522 status
= _cairo_path_fixed_interpret (path
,
523 _cairo_pdf_path_move_to
,
524 _cairo_pdf_path_line_to
,
525 _cairo_pdf_path_curve_to
,
526 _cairo_pdf_path_close_path
,
530 status2
= _cairo_output_stream_destroy (word_wrap
);
531 if (status
== CAIRO_STATUS_SUCCESS
)
538 _cairo_pdf_operators_clip (cairo_pdf_operators_t
*pdf_operators
,
539 const cairo_path_fixed_t
*path
,
540 cairo_fill_rule_t fill_rule
)
542 const char *pdf_operator
;
543 cairo_status_t status
;
545 if (pdf_operators
->in_text_object
) {
546 status
= _cairo_pdf_operators_end_text (pdf_operators
);
547 if (unlikely (status
))
551 if (! path
->has_current_point
) {
552 /* construct an empty path */
553 _cairo_output_stream_printf (pdf_operators
->stream
, "0 0 m ");
555 status
= _cairo_pdf_operators_emit_path (pdf_operators
,
557 &pdf_operators
->cairo_to_pdf
,
558 CAIRO_LINE_CAP_ROUND
);
559 if (unlikely (status
))
566 case CAIRO_FILL_RULE_WINDING
:
569 case CAIRO_FILL_RULE_EVEN_ODD
:
574 _cairo_output_stream_printf (pdf_operators
->stream
,
578 return _cairo_output_stream_get_status (pdf_operators
->stream
);
582 _cairo_pdf_line_cap (cairo_line_cap_t cap
)
585 case CAIRO_LINE_CAP_BUTT
:
587 case CAIRO_LINE_CAP_ROUND
:
589 case CAIRO_LINE_CAP_SQUARE
:
598 _cairo_pdf_line_join (cairo_line_join_t join
)
601 case CAIRO_LINE_JOIN_MITER
:
603 case CAIRO_LINE_JOIN_ROUND
:
605 case CAIRO_LINE_JOIN_BEVEL
:
614 _cairo_pdf_operators_emit_stroke_style (cairo_pdf_operators_t
*pdf_operators
,
615 const cairo_stroke_style_t
*style
,
618 double *dash
= style
->dash
;
619 int num_dashes
= style
->num_dashes
;
620 double dash_offset
= style
->dash_offset
;
621 double line_width
= style
->line_width
* scale
;
623 /* PostScript has "special needs" when it comes to zero-length
624 * dash segments with butt caps. It apparently (at least
625 * according to ghostscript) draws hairlines for this
626 * case. That's not what the cairo semantics want, so we first
627 * touch up the array to eliminate any 0.0 values that will
628 * result in "on" segments.
630 if (num_dashes
&& style
->line_cap
== CAIRO_LINE_CAP_BUTT
) {
633 /* If there's an odd number of dash values they will each get
634 * interpreted as both on and off. So we first explicitly
635 * expand the array to remove the duplicate usage so that we
636 * can modify some of the values.
638 if (num_dashes
% 2) {
639 dash
= _cairo_malloc_abc (num_dashes
, 2, sizeof (double));
640 if (unlikely (dash
== NULL
))
641 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
643 memcpy (dash
, style
->dash
, num_dashes
* sizeof (double));
644 memcpy (dash
+ num_dashes
, style
->dash
, num_dashes
* sizeof (double));
649 for (i
= 0; i
< num_dashes
; i
+= 2) {
650 if (dash
[i
] == 0.0) {
651 /* Do not modify the dashes in-place, as we may need to also
652 * replay this stroke to an image fallback.
654 if (dash
== style
->dash
) {
655 dash
= _cairo_malloc_ab (num_dashes
, sizeof (double));
656 if (unlikely (dash
== NULL
))
657 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
658 memcpy (dash
, style
->dash
, num_dashes
* sizeof (double));
661 /* If we're at the front of the list, we first rotate
662 * two elements from the end of the list to the front
663 * of the list before folding away the 0.0. Or, if
664 * there are only two dash elements, then there is
665 * nothing at all to draw.
670 if (num_dashes
== 2) {
672 return CAIRO_INT_STATUS_NOTHING_TO_DO
;
675 /* The cases of num_dashes == 0, 1, or 3 elements
676 * cannot exist, so the rotation of 2 elements
677 * will always be safe */
678 memcpy (last_two
, dash
+ num_dashes
- 2, sizeof (last_two
));
679 memmove (dash
+ 2, dash
, (num_dashes
- 2) * sizeof (double));
680 memcpy (dash
, last_two
, sizeof (last_two
));
681 dash_offset
+= dash
[0] + dash
[1];
684 dash
[i
-1] += dash
[i
+1];
686 memmove (dash
+ i
, dash
+ i
+ 2, (num_dashes
- i
) * sizeof (double));
687 /* If we might have just rotated, it's possible that
688 * we rotated a 0.0 value to the front of the list.
689 * Set i to -2 so it will get incremented to 0. */
696 if (!pdf_operators
->has_line_style
|| pdf_operators
->line_width
!= line_width
) {
697 _cairo_output_stream_printf (pdf_operators
->stream
,
700 pdf_operators
->line_width
= line_width
;
703 if (!pdf_operators
->has_line_style
|| pdf_operators
->line_cap
!= style
->line_cap
) {
704 _cairo_output_stream_printf (pdf_operators
->stream
,
706 _cairo_pdf_line_cap (style
->line_cap
));
707 pdf_operators
->line_cap
= style
->line_cap
;
710 if (!pdf_operators
->has_line_style
|| pdf_operators
->line_join
!= style
->line_join
) {
711 _cairo_output_stream_printf (pdf_operators
->stream
,
713 _cairo_pdf_line_join (style
->line_join
));
714 pdf_operators
->line_join
= style
->line_join
;
720 _cairo_output_stream_printf (pdf_operators
->stream
, "[");
721 for (d
= 0; d
< num_dashes
; d
++)
722 _cairo_output_stream_printf (pdf_operators
->stream
, " %f", dash
[d
] * scale
);
723 _cairo_output_stream_printf (pdf_operators
->stream
, "] %f d\n",
724 dash_offset
* scale
);
725 pdf_operators
->has_dashes
= TRUE
;
726 } else if (!pdf_operators
->has_line_style
|| pdf_operators
->has_dashes
) {
727 _cairo_output_stream_printf (pdf_operators
->stream
, "[] 0.0 d\n");
728 pdf_operators
->has_dashes
= FALSE
;
730 if (dash
!= style
->dash
)
733 if (!pdf_operators
->has_line_style
|| pdf_operators
->miter_limit
!= style
->miter_limit
) {
734 _cairo_output_stream_printf (pdf_operators
->stream
,
736 style
->miter_limit
< 1.0 ? 1.0 : style
->miter_limit
);
737 pdf_operators
->miter_limit
= style
->miter_limit
;
739 pdf_operators
->has_line_style
= TRUE
;
741 return _cairo_output_stream_get_status (pdf_operators
->stream
);
744 /* Scale the matrix so the largest absolute value of the non
745 * translation components is 1.0. Return the scale required to restore
746 * the matrix to the original values.
748 * eg the matrix [ 100 0 0 50 20 10 ]
750 * is rescaled to [ 1 0 0 0.5 0.2 0.1 ]
751 * and the scale returned is 100
754 _cairo_matrix_factor_out_scale (cairo_matrix_t
*m
, double *scale
)
759 if (fabs (m
->xy
) > s
)
761 if (fabs (m
->yx
) > s
)
763 if (fabs (m
->yy
) > s
)
767 cairo_matrix_scale (m
, s
, s
);
770 static cairo_int_status_t
771 _cairo_pdf_operators_emit_stroke (cairo_pdf_operators_t
*pdf_operators
,
772 const cairo_path_fixed_t
*path
,
773 const cairo_stroke_style_t
*style
,
774 const cairo_matrix_t
*ctm
,
775 const cairo_matrix_t
*ctm_inverse
,
776 const char *pdf_operator
)
778 cairo_int_status_t status
;
779 cairo_matrix_t m
, path_transform
;
780 cairo_bool_t has_ctm
= TRUE
;
783 if (pdf_operators
->in_text_object
) {
784 status
= _cairo_pdf_operators_end_text (pdf_operators
);
785 if (unlikely (status
))
789 /* Optimize away the stroke ctm when it does not affect the
790 * stroke. There are other ctm cases that could be optimized
791 * however this is the most common.
793 if (fabs(ctm
->xx
) == 1.0 && fabs(ctm
->yy
) == 1.0 &&
794 fabs(ctm
->xy
) == 0.0 && fabs(ctm
->yx
) == 0.0)
799 /* The PDF CTM is transformed to the user space CTM when stroking
800 * so the corect pen shape will be used. This also requires that
801 * the path be transformed to user space when emitted. The
802 * conversion of path coordinates to user space may cause rounding
803 * errors. For example the device space point (1.234, 3.142) when
804 * transformed to a user space CTM of [100 0 0 100 0 0] will be
805 * emitted as (0.012, 0.031).
807 * To avoid the rounding problem we scale the user space CTM
808 * matrix so that all the non translation components of the matrix
809 * are <= 1. The line width and and dashes are scaled by the
810 * inverse of the scale applied to the CTM. This maintains the
811 * shape of the stroke pen while keeping the user space CTM within
812 * the range that maximizes the precision of the emitted path.
816 /* Zero out the translation since it does not affect the pen
817 * shape however it may cause unnecessary digits to be emitted.
821 _cairo_matrix_factor_out_scale (&m
, &scale
);
823 status
= cairo_matrix_invert (&path_transform
);
824 if (unlikely (status
))
827 cairo_matrix_multiply (&m
, &m
, &pdf_operators
->cairo_to_pdf
);
830 status
= _cairo_pdf_operators_emit_stroke_style (pdf_operators
, style
, scale
);
831 if (status
== CAIRO_INT_STATUS_NOTHING_TO_DO
)
832 return CAIRO_STATUS_SUCCESS
;
833 if (unlikely (status
))
837 _cairo_output_stream_printf (pdf_operators
->stream
, "q ");
838 _cairo_output_stream_print_matrix (pdf_operators
->stream
, &m
);
839 _cairo_output_stream_printf (pdf_operators
->stream
, " cm\n");
841 path_transform
= pdf_operators
->cairo_to_pdf
;
844 status
= _cairo_pdf_operators_emit_path (pdf_operators
,
848 if (unlikely (status
))
851 _cairo_output_stream_printf (pdf_operators
->stream
, "%s", pdf_operator
);
853 _cairo_output_stream_printf (pdf_operators
->stream
, " Q");
855 _cairo_output_stream_printf (pdf_operators
->stream
, "\n");
857 return _cairo_output_stream_get_status (pdf_operators
->stream
);
861 _cairo_pdf_operators_stroke (cairo_pdf_operators_t
*pdf_operators
,
862 const cairo_path_fixed_t
*path
,
863 const cairo_stroke_style_t
*style
,
864 const cairo_matrix_t
*ctm
,
865 const cairo_matrix_t
*ctm_inverse
)
867 return _cairo_pdf_operators_emit_stroke (pdf_operators
,
876 _cairo_pdf_operators_fill (cairo_pdf_operators_t
*pdf_operators
,
877 const cairo_path_fixed_t
*path
,
878 cairo_fill_rule_t fill_rule
)
880 const char *pdf_operator
;
881 cairo_status_t status
;
883 if (pdf_operators
->in_text_object
) {
884 status
= _cairo_pdf_operators_end_text (pdf_operators
);
885 if (unlikely (status
))
889 status
= _cairo_pdf_operators_emit_path (pdf_operators
,
891 &pdf_operators
->cairo_to_pdf
,
892 CAIRO_LINE_CAP_ROUND
);
893 if (unlikely (status
))
899 case CAIRO_FILL_RULE_WINDING
:
902 case CAIRO_FILL_RULE_EVEN_ODD
:
907 _cairo_output_stream_printf (pdf_operators
->stream
,
911 return _cairo_output_stream_get_status (pdf_operators
->stream
);
915 _cairo_pdf_operators_fill_stroke (cairo_pdf_operators_t
*pdf_operators
,
916 const cairo_path_fixed_t
*path
,
917 cairo_fill_rule_t fill_rule
,
918 const cairo_stroke_style_t
*style
,
919 const cairo_matrix_t
*ctm
,
920 const cairo_matrix_t
*ctm_inverse
)
922 const char *operator;
927 case CAIRO_FILL_RULE_WINDING
:
930 case CAIRO_FILL_RULE_EVEN_ODD
:
935 return _cairo_pdf_operators_emit_stroke (pdf_operators
,
944 _cairo_pdf_operators_emit_glyph_index (cairo_pdf_operators_t
*pdf_operators
,
945 cairo_output_stream_t
*stream
,
948 if (pdf_operators
->is_latin
) {
949 if (glyph
== '(' || glyph
== ')' || glyph
== '\\')
950 _cairo_output_stream_printf (stream
, "\\%c", glyph
);
951 else if (glyph
>= 0x20 && glyph
<= 0x7e)
952 _cairo_output_stream_printf (stream
, "%c", glyph
);
954 _cairo_output_stream_printf (stream
, "\\%03o", glyph
);
956 _cairo_output_stream_printf (stream
,
958 pdf_operators
->hex_width
,
963 #define GLYPH_POSITION_TOLERANCE 0.001
965 /* Emit the string of glyphs using the 'Tj' operator. This requires
966 * that the glyphs are positioned at their natural glyph advances. */
967 static cairo_status_t
968 _cairo_pdf_operators_emit_glyph_string (cairo_pdf_operators_t
*pdf_operators
,
969 cairo_output_stream_t
*stream
)
973 _cairo_output_stream_printf (stream
, "%s", pdf_operators
->is_latin
? "(" : "<");
974 for (i
= 0; i
< pdf_operators
->num_glyphs
; i
++) {
975 _cairo_pdf_operators_emit_glyph_index (pdf_operators
,
977 pdf_operators
->glyphs
[i
].glyph_index
);
978 pdf_operators
->cur_x
+= pdf_operators
->glyphs
[i
].x_advance
;
980 _cairo_output_stream_printf (stream
, "%sTj\n", pdf_operators
->is_latin
? ")" : ">");
982 return _cairo_output_stream_get_status (stream
);
985 /* Emit the string of glyphs using the 'TJ' operator.
987 * The TJ operator takes an array of strings of glyphs. Each string of
988 * glyphs is displayed using the glyph advances of each glyph to
989 * position the glyphs. A relative adjustment to the glyph advance may
990 * be specified by including the adjustment between two strings. The
991 * adjustment is in units of text space * -1000.
993 static cairo_status_t
994 _cairo_pdf_operators_emit_glyph_string_with_positioning (
995 cairo_pdf_operators_t
*pdf_operators
,
996 cairo_output_stream_t
*stream
)
1000 _cairo_output_stream_printf (stream
, "[%s", pdf_operators
->is_latin
? "(" : "<");
1001 for (i
= 0; i
< pdf_operators
->num_glyphs
; i
++) {
1002 if (pdf_operators
->glyphs
[i
].x_position
!= pdf_operators
->cur_x
)
1004 double delta
= pdf_operators
->glyphs
[i
].x_position
- pdf_operators
->cur_x
;
1007 delta
= -1000.0*delta
;
1008 /* As the delta is in 1/1000 of a unit of text space,
1009 * rounding to an integer should still provide sufficient
1010 * precision. We round the delta before adding to Tm_x so
1011 * that we keep track of the accumulated rounding error in
1012 * the PDF interpreter and compensate for it when
1013 * calculating subsequent deltas.
1015 rounded_delta
= _cairo_lround (delta
);
1016 if (abs(rounded_delta
) < 3)
1018 if (rounded_delta
!= 0) {
1019 if (pdf_operators
->is_latin
) {
1020 _cairo_output_stream_printf (stream
,
1024 _cairo_output_stream_printf (stream
,
1030 /* Convert the rounded delta back to text
1031 * space before adding to the current text
1033 delta
= rounded_delta
/-1000.0;
1034 pdf_operators
->cur_x
+= delta
;
1037 _cairo_pdf_operators_emit_glyph_index (pdf_operators
,
1039 pdf_operators
->glyphs
[i
].glyph_index
);
1040 pdf_operators
->cur_x
+= pdf_operators
->glyphs
[i
].x_advance
;
1042 _cairo_output_stream_printf (stream
, "%s]TJ\n", pdf_operators
->is_latin
? ")" : ">");
1044 return _cairo_output_stream_get_status (stream
);
1047 static cairo_status_t
1048 _cairo_pdf_operators_flush_glyphs (cairo_pdf_operators_t
*pdf_operators
)
1050 cairo_output_stream_t
*word_wrap_stream
;
1051 cairo_status_t status
, status2
;
1055 if (pdf_operators
->num_glyphs
== 0)
1056 return CAIRO_STATUS_SUCCESS
;
1058 word_wrap_stream
= _word_wrap_stream_create (pdf_operators
->stream
, pdf_operators
->ps_output
, 72);
1059 status
= _cairo_output_stream_get_status (word_wrap_stream
);
1060 if (unlikely (status
))
1061 return _cairo_output_stream_destroy (word_wrap_stream
);
1063 /* Check if glyph advance used to position every glyph */
1064 x
= pdf_operators
->cur_x
;
1065 for (i
= 0; i
< pdf_operators
->num_glyphs
; i
++) {
1066 if (fabs(pdf_operators
->glyphs
[i
].x_position
- x
) > GLYPH_POSITION_TOLERANCE
)
1068 x
+= pdf_operators
->glyphs
[i
].x_advance
;
1070 if (i
== pdf_operators
->num_glyphs
) {
1071 status
= _cairo_pdf_operators_emit_glyph_string (pdf_operators
,
1074 status
= _cairo_pdf_operators_emit_glyph_string_with_positioning (
1075 pdf_operators
, word_wrap_stream
);
1078 pdf_operators
->num_glyphs
= 0;
1079 pdf_operators
->glyph_buf_x_pos
= pdf_operators
->cur_x
;
1080 status2
= _cairo_output_stream_destroy (word_wrap_stream
);
1081 if (status
== CAIRO_STATUS_SUCCESS
)
1087 static cairo_status_t
1088 _cairo_pdf_operators_add_glyph (cairo_pdf_operators_t
*pdf_operators
,
1089 cairo_scaled_font_subsets_glyph_t
*glyph
,
1094 x
= glyph
->x_advance
;
1095 y
= glyph
->y_advance
;
1096 if (glyph
->is_scaled
)
1097 cairo_matrix_transform_distance (&pdf_operators
->font_matrix_inverse
, &x
, &y
);
1099 pdf_operators
->glyphs
[pdf_operators
->num_glyphs
].x_position
= x_position
;
1100 pdf_operators
->glyphs
[pdf_operators
->num_glyphs
].glyph_index
= glyph
->subset_glyph_index
;
1101 pdf_operators
->glyphs
[pdf_operators
->num_glyphs
].x_advance
= x
;
1102 pdf_operators
->glyph_buf_x_pos
+= x
;
1103 pdf_operators
->num_glyphs
++;
1104 if (pdf_operators
->num_glyphs
== PDF_GLYPH_BUFFER_SIZE
)
1105 return _cairo_pdf_operators_flush_glyphs (pdf_operators
);
1107 return CAIRO_STATUS_SUCCESS
;
1110 /* Use 'Tm' operator to set the PDF text matrix. */
1111 static cairo_status_t
1112 _cairo_pdf_operators_set_text_matrix (cairo_pdf_operators_t
*pdf_operators
,
1113 cairo_matrix_t
*matrix
)
1115 cairo_matrix_t inverse
;
1116 cairo_status_t status
;
1118 /* We require the matrix to be invertable. */
1120 status
= cairo_matrix_invert (&inverse
);
1121 if (unlikely (status
))
1124 pdf_operators
->text_matrix
= *matrix
;
1125 pdf_operators
->cur_x
= 0;
1126 pdf_operators
->cur_y
= 0;
1127 pdf_operators
->glyph_buf_x_pos
= 0;
1128 _cairo_output_stream_print_matrix (pdf_operators
->stream
, &pdf_operators
->text_matrix
);
1129 _cairo_output_stream_printf (pdf_operators
->stream
, " Tm\n");
1131 pdf_operators
->cairo_to_pdftext
= *matrix
;
1132 status
= cairo_matrix_invert (&pdf_operators
->cairo_to_pdftext
);
1133 assert (status
== CAIRO_STATUS_SUCCESS
);
1134 cairo_matrix_multiply (&pdf_operators
->cairo_to_pdftext
,
1135 &pdf_operators
->cairo_to_pdf
,
1136 &pdf_operators
->cairo_to_pdftext
);
1138 return _cairo_output_stream_get_status (pdf_operators
->stream
);
1141 #define TEXT_MATRIX_TOLERANCE 1e-6
1143 /* Set the translation components of the PDF text matrix to x, y. The
1144 * 'Td' operator is used to transform the text matrix.
1146 static cairo_status_t
1147 _cairo_pdf_operators_set_text_position (cairo_pdf_operators_t
*pdf_operators
,
1151 cairo_matrix_t translate
, inverse
;
1152 cairo_status_t status
;
1154 /* The Td operator transforms the text_matrix with:
1156 * text_matrix' = T x text_matrix
1158 * where T is a translation matrix with the translation components
1159 * set to the Td operands tx and ty.
1161 inverse
= pdf_operators
->text_matrix
;
1162 status
= cairo_matrix_invert (&inverse
);
1163 assert (status
== CAIRO_STATUS_SUCCESS
);
1164 pdf_operators
->text_matrix
.x0
= x
;
1165 pdf_operators
->text_matrix
.y0
= y
;
1166 cairo_matrix_multiply (&translate
, &pdf_operators
->text_matrix
, &inverse
);
1167 if (fabs(translate
.x0
) < TEXT_MATRIX_TOLERANCE
)
1169 if (fabs(translate
.y0
) < TEXT_MATRIX_TOLERANCE
)
1171 _cairo_output_stream_printf (pdf_operators
->stream
,
1175 pdf_operators
->cur_x
= 0;
1176 pdf_operators
->cur_y
= 0;
1177 pdf_operators
->glyph_buf_x_pos
= 0;
1179 pdf_operators
->cairo_to_pdftext
= pdf_operators
->text_matrix
;
1180 status
= cairo_matrix_invert (&pdf_operators
->cairo_to_pdftext
);
1181 assert (status
== CAIRO_STATUS_SUCCESS
);
1182 cairo_matrix_multiply (&pdf_operators
->cairo_to_pdftext
,
1183 &pdf_operators
->cairo_to_pdf
,
1184 &pdf_operators
->cairo_to_pdftext
);
1186 return _cairo_output_stream_get_status (pdf_operators
->stream
);
1189 /* Select the font using the 'Tf' operator. The font size is set to 1
1190 * as we use the 'Tm' operator to set the font scale.
1192 static cairo_status_t
1193 _cairo_pdf_operators_set_font_subset (cairo_pdf_operators_t
*pdf_operators
,
1194 cairo_scaled_font_subsets_glyph_t
*subset_glyph
)
1196 cairo_status_t status
;
1198 _cairo_output_stream_printf (pdf_operators
->stream
,
1200 subset_glyph
->font_id
,
1201 subset_glyph
->subset_id
);
1202 if (pdf_operators
->use_font_subset
) {
1203 status
= pdf_operators
->use_font_subset (subset_glyph
->font_id
,
1204 subset_glyph
->subset_id
,
1205 pdf_operators
->use_font_subset_closure
);
1206 if (unlikely (status
))
1209 pdf_operators
->font_id
= subset_glyph
->font_id
;
1210 pdf_operators
->subset_id
= subset_glyph
->subset_id
;
1211 pdf_operators
->is_latin
= subset_glyph
->is_latin
;
1213 if (subset_glyph
->is_composite
)
1214 pdf_operators
->hex_width
= 4;
1216 pdf_operators
->hex_width
= 2;
1218 return CAIRO_STATUS_SUCCESS
;
1221 static cairo_status_t
1222 _cairo_pdf_operators_begin_text (cairo_pdf_operators_t
*pdf_operators
)
1224 _cairo_output_stream_printf (pdf_operators
->stream
, "BT\n");
1226 pdf_operators
->in_text_object
= TRUE
;
1227 pdf_operators
->num_glyphs
= 0;
1228 pdf_operators
->glyph_buf_x_pos
= 0;
1230 return _cairo_output_stream_get_status (pdf_operators
->stream
);
1233 static cairo_status_t
1234 _cairo_pdf_operators_end_text (cairo_pdf_operators_t
*pdf_operators
)
1236 cairo_status_t status
;
1238 status
= _cairo_pdf_operators_flush_glyphs (pdf_operators
);
1239 if (unlikely (status
))
1242 _cairo_output_stream_printf (pdf_operators
->stream
, "ET\n");
1244 pdf_operators
->in_text_object
= FALSE
;
1246 return _cairo_output_stream_get_status (pdf_operators
->stream
);
1249 /* Compare the scale components of two matrices. The translation
1250 * components are ignored. */
1252 _cairo_matrix_scale_equal (cairo_matrix_t
*a
, cairo_matrix_t
*b
)
1254 return (a
->xx
== b
->xx
&&
1260 static cairo_status_t
1261 _cairo_pdf_operators_begin_actualtext (cairo_pdf_operators_t
*pdf_operators
,
1267 cairo_status_t status
;
1270 _cairo_output_stream_printf (pdf_operators
->stream
, "/Span << /ActualText <feff");
1272 status
= _cairo_utf8_to_utf16 (utf8
, utf8_len
, &utf16
, &utf16_len
);
1273 if (unlikely (status
))
1276 for (i
= 0; i
< utf16_len
; i
++) {
1277 _cairo_output_stream_printf (pdf_operators
->stream
,
1278 "%04x", (int) (utf16
[i
]));
1282 _cairo_output_stream_printf (pdf_operators
->stream
, "> >> BDC\n");
1284 return _cairo_output_stream_get_status (pdf_operators
->stream
);
1287 static cairo_status_t
1288 _cairo_pdf_operators_end_actualtext (cairo_pdf_operators_t
*pdf_operators
)
1290 _cairo_output_stream_printf (pdf_operators
->stream
, "EMC\n");
1292 return _cairo_output_stream_get_status (pdf_operators
->stream
);
1295 static cairo_status_t
1296 _cairo_pdf_operators_emit_glyph (cairo_pdf_operators_t
*pdf_operators
,
1297 cairo_glyph_t
*glyph
,
1298 cairo_scaled_font_subsets_glyph_t
*subset_glyph
)
1301 cairo_status_t status
;
1303 if (pdf_operators
->is_new_text_object
||
1304 pdf_operators
->font_id
!= subset_glyph
->font_id
||
1305 pdf_operators
->subset_id
!= subset_glyph
->subset_id
)
1307 status
= _cairo_pdf_operators_flush_glyphs (pdf_operators
);
1308 if (unlikely (status
))
1311 status
= _cairo_pdf_operators_set_font_subset (pdf_operators
, subset_glyph
);
1312 if (unlikely (status
))
1315 pdf_operators
->is_new_text_object
= FALSE
;
1320 cairo_matrix_transform_point (&pdf_operators
->cairo_to_pdftext
, &x
, &y
);
1322 /* The TJ operator for displaying text strings can only set
1323 * the horizontal position of the glyphs. If the y position
1324 * (in text space) changes, use the Td operator to change the
1325 * current position to the next glyph. We also use the Td
1326 * operator to move the current position if the horizontal
1327 * position changes by more than 10 (in text space
1328 * units). This is becauses the horizontal glyph positioning
1329 * in the TJ operator is intended for kerning and there may be
1330 * PDF consumers that do not handle very large position
1331 * adjustments in TJ.
1333 if (fabs(x
- pdf_operators
->glyph_buf_x_pos
) > 10 ||
1334 fabs(y
- pdf_operators
->cur_y
) > GLYPH_POSITION_TOLERANCE
)
1336 status
= _cairo_pdf_operators_flush_glyphs (pdf_operators
);
1337 if (unlikely (status
))
1342 cairo_matrix_transform_point (&pdf_operators
->cairo_to_pdf
, &x
, &y
);
1343 status
= _cairo_pdf_operators_set_text_position (pdf_operators
, x
, y
);
1344 if (unlikely (status
))
1351 status
= _cairo_pdf_operators_add_glyph (pdf_operators
,
1357 /* A utf8_len of -1 indicates no unicode text. A utf8_len = 0 is an
1360 static cairo_int_status_t
1361 _cairo_pdf_operators_emit_cluster (cairo_pdf_operators_t
*pdf_operators
,
1364 cairo_glyph_t
*glyphs
,
1366 cairo_text_cluster_flags_t cluster_flags
,
1367 cairo_scaled_font_t
*scaled_font
)
1369 cairo_scaled_font_subsets_glyph_t subset_glyph
;
1370 cairo_glyph_t
*cur_glyph
;
1371 cairo_status_t status
= CAIRO_STATUS_SUCCESS
;
1374 /* If the cluster maps 1 glyph to 1 or more unicode characters, we
1375 * first try _map_glyph() with the unicode string to see if it can
1376 * use toUnicode to map our glyph to the unicode. This will fail
1377 * if the glyph is already mapped to a different unicode string.
1379 * We also go through this path if no unicode mapping was
1380 * supplied (utf8_len < 0).
1382 * Mapping a glyph to a zero length unicode string requires the
1383 * use of ActualText.
1385 if (num_glyphs
== 1 && utf8_len
!= 0) {
1386 status
= _cairo_scaled_font_subsets_map_glyph (pdf_operators
->font_subsets
,
1392 if (unlikely (status
))
1395 if (subset_glyph
.utf8_is_mapped
|| utf8_len
< 0) {
1396 status
= _cairo_pdf_operators_emit_glyph (pdf_operators
,
1399 if (unlikely (status
))
1402 return CAIRO_STATUS_SUCCESS
;
1406 if (pdf_operators
->use_actual_text
) {
1407 /* Fallback to using ActualText to map zero or more glyphs to a
1408 * unicode string. */
1409 status
= _cairo_pdf_operators_flush_glyphs (pdf_operators
);
1410 if (unlikely (status
))
1413 status
= _cairo_pdf_operators_begin_actualtext (pdf_operators
, utf8
, utf8_len
);
1414 if (unlikely (status
))
1418 if (cluster_flags
& CAIRO_TEXT_CLUSTER_FLAG_BACKWARD
)
1419 cur_glyph
= glyphs
+ num_glyphs
- 1;
1424 * If no glyphs, we should put *something* here for the text to be selectable. */
1425 for (i
= 0; i
< num_glyphs
; i
++) {
1426 status
= _cairo_scaled_font_subsets_map_glyph (pdf_operators
->font_subsets
,
1431 if (unlikely (status
))
1434 status
= _cairo_pdf_operators_emit_glyph (pdf_operators
,
1437 if (unlikely (status
))
1440 if ((cluster_flags
& CAIRO_TEXT_CLUSTER_FLAG_BACKWARD
))
1446 if (pdf_operators
->use_actual_text
) {
1447 status
= _cairo_pdf_operators_flush_glyphs (pdf_operators
);
1448 if (unlikely (status
))
1451 status
= _cairo_pdf_operators_end_actualtext (pdf_operators
);
1458 _cairo_pdf_operators_show_text_glyphs (cairo_pdf_operators_t
*pdf_operators
,
1461 cairo_glyph_t
*glyphs
,
1463 const cairo_text_cluster_t
*clusters
,
1465 cairo_text_cluster_flags_t cluster_flags
,
1466 cairo_scaled_font_t
*scaled_font
)
1468 cairo_status_t status
;
1470 cairo_matrix_t text_matrix
, invert_y_axis
;
1472 const char *cur_text
;
1473 cairo_glyph_t
*cur_glyph
;
1475 pdf_operators
->font_matrix_inverse
= scaled_font
->font_matrix
;
1476 status
= cairo_matrix_invert (&pdf_operators
->font_matrix_inverse
);
1477 if (status
== CAIRO_STATUS_INVALID_MATRIX
)
1478 return CAIRO_STATUS_SUCCESS
;
1479 assert (status
== CAIRO_STATUS_SUCCESS
);
1481 pdf_operators
->is_new_text_object
= FALSE
;
1482 if (pdf_operators
->in_text_object
== FALSE
) {
1483 status
= _cairo_pdf_operators_begin_text (pdf_operators
);
1484 if (unlikely (status
))
1487 /* Force Tm and Tf to be emitted when starting a new text
1489 pdf_operators
->is_new_text_object
= TRUE
;
1492 cairo_matrix_init_scale (&invert_y_axis
, 1, -1);
1493 text_matrix
= scaled_font
->scale
;
1495 /* Invert y axis in font space */
1496 cairo_matrix_multiply (&text_matrix
, &text_matrix
, &invert_y_axis
);
1498 /* Invert y axis in device space */
1499 cairo_matrix_multiply (&text_matrix
, &invert_y_axis
, &text_matrix
);
1501 if (pdf_operators
->is_new_text_object
||
1502 ! _cairo_matrix_scale_equal (&pdf_operators
->text_matrix
, &text_matrix
))
1504 status
= _cairo_pdf_operators_flush_glyphs (pdf_operators
);
1505 if (unlikely (status
))
1510 cairo_matrix_transform_point (&pdf_operators
->cairo_to_pdf
, &x
, &y
);
1513 status
= _cairo_pdf_operators_set_text_matrix (pdf_operators
, &text_matrix
);
1514 if (status
== CAIRO_STATUS_INVALID_MATRIX
)
1515 return CAIRO_STATUS_SUCCESS
;
1516 if (unlikely (status
))
1520 if (num_clusters
> 0) {
1522 if ((cluster_flags
& CAIRO_TEXT_CLUSTER_FLAG_BACKWARD
))
1523 cur_glyph
= glyphs
+ num_glyphs
;
1526 for (i
= 0; i
< num_clusters
; i
++) {
1527 if ((cluster_flags
& CAIRO_TEXT_CLUSTER_FLAG_BACKWARD
))
1528 cur_glyph
-= clusters
[i
].num_glyphs
;
1529 status
= _cairo_pdf_operators_emit_cluster (pdf_operators
,
1531 clusters
[i
].num_bytes
,
1533 clusters
[i
].num_glyphs
,
1536 if (unlikely (status
))
1539 cur_text
+= clusters
[i
].num_bytes
;
1540 if (!(cluster_flags
& CAIRO_TEXT_CLUSTER_FLAG_BACKWARD
))
1541 cur_glyph
+= clusters
[i
].num_glyphs
;
1544 for (i
= 0; i
< num_glyphs
; i
++) {
1545 status
= _cairo_pdf_operators_emit_cluster (pdf_operators
,
1547 -1, /* no unicode string available */
1552 if (unlikely (status
))
1557 return _cairo_output_stream_get_status (pdf_operators
->stream
);
1560 #endif /* CAIRO_HAS_PDF_OPERATORS */