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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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-pdf-operators-private.h"
47 #include "cairo-path-fixed-private.h"
48 #include "cairo-output-stream-private.h"
49 #include "cairo-scaled-font-subsets-private.h"
54 _cairo_pdf_operators_end_text (cairo_pdf_operators_t
*pdf_operators
);
58 _cairo_pdf_operators_init (cairo_pdf_operators_t
*pdf_operators
,
59 cairo_output_stream_t
*stream
,
60 cairo_matrix_t
*cairo_to_pdf
,
61 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
->use_font_subset
= NULL
;
67 pdf_operators
->use_font_subset_closure
= NULL
;
68 pdf_operators
->in_text_object
= FALSE
;
69 pdf_operators
->num_glyphs
= 0;
70 pdf_operators
->has_line_style
= FALSE
;
74 _cairo_pdf_operators_fini (cairo_pdf_operators_t
*pdf_operators
)
76 return _cairo_pdf_operators_flush (pdf_operators
);
80 _cairo_pdf_operators_set_font_subsets_callback (cairo_pdf_operators_t
*pdf_operators
,
81 cairo_pdf_operators_use_font_subset_t use_font_subset
,
84 pdf_operators
->use_font_subset
= use_font_subset
;
85 pdf_operators
->use_font_subset_closure
= closure
;
88 /* Change the output stream to a different stream.
89 * _cairo_pdf_operators_flush() should always be called before calling
93 _cairo_pdf_operators_set_stream (cairo_pdf_operators_t
*pdf_operators
,
94 cairo_output_stream_t
*stream
)
96 pdf_operators
->stream
= stream
;
97 pdf_operators
->has_line_style
= FALSE
;
101 _cairo_pdf_operators_set_cairo_to_pdf_matrix (cairo_pdf_operators_t
*pdf_operators
,
102 cairo_matrix_t
*cairo_to_pdf
)
104 pdf_operators
->cairo_to_pdf
= *cairo_to_pdf
;
105 pdf_operators
->has_line_style
= FALSE
;
108 /* Finish writing out any pending commands to the stream. This
109 * function must be called by the surface before emitting anything
110 * into the PDF stream.
112 * pdf_operators may leave the emitted PDF for some operations
113 * unfinished in case subsequent operations can be merged. This
114 * function will finish off any incomplete operation so the stream
115 * will be in a state where the surface may emit it's own PDF
116 * operations (eg changing patterns).
120 _cairo_pdf_operators_flush (cairo_pdf_operators_t
*pdf_operators
)
122 cairo_status_t status
= CAIRO_STATUS_SUCCESS
;
124 if (pdf_operators
->in_text_object
)
125 status
= _cairo_pdf_operators_end_text (pdf_operators
);
130 /* Reset the known graphics state of the PDF consumer. ie no
131 * assumptions will be made about the state. The next time a
132 * particular graphics state is required (eg line width) the state
133 * operator is always emitted and then remembered for subsequent
136 * This should be called when starting a new stream or after emitting
137 * the 'Q' operator (where pdf-operators functions were called inside
141 _cairo_pdf_operators_reset (cairo_pdf_operators_t
*pdf_operators
)
143 pdf_operators
->has_line_style
= FALSE
;
146 /* A word wrap stream can be used as a filter to do word wrapping on
147 * top of an existing output stream. The word wrapping is quite
148 * simple, using isspace to determine characters that separate
149 * words. Any word that will cause the column count exceed the given
150 * max_column will have a '\n' character emitted before it.
152 * The stream is careful to maintain integrity for words that cross
153 * the boundary from one call to write to the next.
155 * Note: This stream does not guarantee that the output will never
156 * exceed max_column. In particular, if a single word is larger than
157 * max_column it will not be broken up.
159 typedef struct _word_wrap_stream
{
160 cairo_output_stream_t base
;
161 cairo_output_stream_t
*output
;
164 cairo_bool_t last_write_was_space
;
165 cairo_bool_t in_hexstring
;
166 cairo_bool_t empty_hexstring
;
167 } word_wrap_stream_t
;
170 _count_word_up_to (const unsigned char *s
, int length
)
175 if (! (isspace (*s
) || *s
== '<')) {
187 /* Count up to either the end of the ASCII hexstring or the number
188 * of columns remaining.
191 _count_hexstring_up_to (const unsigned char *s
, int length
, int columns
)
202 if (columns
< 0 && word
> 1)
209 static cairo_status_t
210 _word_wrap_stream_write (cairo_output_stream_t
*base
,
211 const unsigned char *data
,
214 word_wrap_stream_t
*stream
= (word_wrap_stream_t
*) base
;
215 cairo_bool_t newline
;
220 stream
->in_hexstring
= TRUE
;
221 stream
->empty_hexstring
= TRUE
;
222 stream
->last_write_was_space
= FALSE
;
225 _cairo_output_stream_printf (stream
->output
, "<");
227 } else if (*data
== '>') {
228 stream
->in_hexstring
= FALSE
;
229 stream
->last_write_was_space
= FALSE
;
232 _cairo_output_stream_printf (stream
->output
, ">");
234 } else if (isspace (*data
)) {
235 newline
= (*data
== '\n' || *data
== '\r');
236 if (! newline
&& stream
->column
>= stream
->max_column
) {
237 _cairo_output_stream_printf (stream
->output
, "\n");
240 _cairo_output_stream_write (stream
->output
, data
, 1);
248 stream
->last_write_was_space
= TRUE
;
250 if (stream
->in_hexstring
) {
251 word
= _count_hexstring_up_to (data
, length
,
252 MAX (stream
->max_column
- stream
->column
, 0));
254 word
= _count_word_up_to (data
, length
);
256 /* Don't wrap if this word is a continuation of a non hex
257 * string word from a previous call to write. */
258 if (stream
->column
+ word
>= stream
->max_column
) {
259 if (stream
->last_write_was_space
||
260 (stream
->in_hexstring
&& !stream
->empty_hexstring
))
262 _cairo_output_stream_printf (stream
->output
, "\n");
266 _cairo_output_stream_write (stream
->output
, data
, word
);
269 stream
->column
+= word
;
270 stream
->last_write_was_space
= FALSE
;
271 if (stream
->in_hexstring
)
272 stream
->empty_hexstring
= FALSE
;
276 return _cairo_output_stream_get_status (stream
->output
);
279 static cairo_status_t
280 _word_wrap_stream_close (cairo_output_stream_t
*base
)
282 word_wrap_stream_t
*stream
= (word_wrap_stream_t
*) base
;
284 return _cairo_output_stream_get_status (stream
->output
);
287 static cairo_output_stream_t
*
288 _word_wrap_stream_create (cairo_output_stream_t
*output
, int max_column
)
290 word_wrap_stream_t
*stream
;
293 return _cairo_output_stream_create_in_error (output
->status
);
295 stream
= malloc (sizeof (word_wrap_stream_t
));
296 if (stream
== NULL
) {
297 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY
);
298 return (cairo_output_stream_t
*) &_cairo_output_stream_nil
;
301 _cairo_output_stream_init (&stream
->base
,
302 _word_wrap_stream_write
,
303 _word_wrap_stream_close
);
304 stream
->output
= output
;
305 stream
->max_column
= max_column
;
307 stream
->last_write_was_space
= FALSE
;
308 stream
->in_hexstring
= FALSE
;
309 stream
->empty_hexstring
= TRUE
;
311 return &stream
->base
;
314 typedef struct _pdf_path_info
{
315 cairo_output_stream_t
*output
;
316 cairo_matrix_t
*path_transform
;
317 cairo_line_cap_t line_cap
;
318 cairo_point_t last_move_to_point
;
319 cairo_bool_t has_sub_path
;
322 static cairo_status_t
323 _cairo_pdf_path_move_to (void *closure
, cairo_point_t
*point
)
325 pdf_path_info_t
*info
= closure
;
326 double x
= _cairo_fixed_to_double (point
->x
);
327 double y
= _cairo_fixed_to_double (point
->y
);
329 info
->last_move_to_point
= *point
;
330 info
->has_sub_path
= FALSE
;
331 cairo_matrix_transform_point (info
->path_transform
, &x
, &y
);
332 _cairo_output_stream_printf (info
->output
,
335 return _cairo_output_stream_get_status (info
->output
);
338 static cairo_status_t
339 _cairo_pdf_path_line_to (void *closure
, cairo_point_t
*point
)
341 pdf_path_info_t
*info
= closure
;
342 double x
= _cairo_fixed_to_double (point
->x
);
343 double y
= _cairo_fixed_to_double (point
->y
);
345 if (info
->line_cap
!= CAIRO_LINE_CAP_ROUND
&&
346 ! info
->has_sub_path
&&
347 point
->x
== info
->last_move_to_point
.x
&&
348 point
->y
== info
->last_move_to_point
.y
)
350 return CAIRO_STATUS_SUCCESS
;
353 info
->has_sub_path
= TRUE
;
354 cairo_matrix_transform_point (info
->path_transform
, &x
, &y
);
355 _cairo_output_stream_printf (info
->output
,
358 return _cairo_output_stream_get_status (info
->output
);
361 static cairo_status_t
362 _cairo_pdf_path_curve_to (void *closure
,
367 pdf_path_info_t
*info
= closure
;
368 double bx
= _cairo_fixed_to_double (b
->x
);
369 double by
= _cairo_fixed_to_double (b
->y
);
370 double cx
= _cairo_fixed_to_double (c
->x
);
371 double cy
= _cairo_fixed_to_double (c
->y
);
372 double dx
= _cairo_fixed_to_double (d
->x
);
373 double dy
= _cairo_fixed_to_double (d
->y
);
375 info
->has_sub_path
= TRUE
;
376 cairo_matrix_transform_point (info
->path_transform
, &bx
, &by
);
377 cairo_matrix_transform_point (info
->path_transform
, &cx
, &cy
);
378 cairo_matrix_transform_point (info
->path_transform
, &dx
, &dy
);
379 _cairo_output_stream_printf (info
->output
,
380 "%g %g %g %g %g %g c ",
381 bx
, by
, cx
, cy
, dx
, dy
);
382 return _cairo_output_stream_get_status (info
->output
);
385 static cairo_status_t
386 _cairo_pdf_path_close_path (void *closure
)
388 pdf_path_info_t
*info
= closure
;
390 if (info
->line_cap
!= CAIRO_LINE_CAP_ROUND
&&
391 ! info
->has_sub_path
)
393 return CAIRO_STATUS_SUCCESS
;
396 _cairo_output_stream_printf (info
->output
,
399 return _cairo_output_stream_get_status (info
->output
);
402 static cairo_status_t
403 _cairo_pdf_path_rectangle (pdf_path_info_t
*info
, cairo_box_t
*box
)
405 double x1
= _cairo_fixed_to_double (box
->p1
.x
);
406 double y1
= _cairo_fixed_to_double (box
->p1
.y
);
407 double x2
= _cairo_fixed_to_double (box
->p2
.x
);
408 double y2
= _cairo_fixed_to_double (box
->p2
.y
);
410 cairo_matrix_transform_point (info
->path_transform
, &x1
, &y1
);
411 cairo_matrix_transform_point (info
->path_transform
, &x2
, &y2
);
412 _cairo_output_stream_printf (info
->output
,
414 x1
, y1
, x2
- x1
, y2
- y1
);
416 return _cairo_output_stream_get_status (info
->output
);
419 /* The line cap value is needed to workaround the fact that PostScript
420 * and PDF semantics for stroking degenerate sub-paths do not match
421 * cairo semantics. (PostScript draws something for any line cap
422 * value, while cairo draws something only for round caps).
424 * When using this function to emit a path to be filled, rather than
425 * stroked, simply pass %CAIRO_LINE_CAP_ROUND which will guarantee that
426 * the stroke workaround will not modify the path being emitted.
428 static cairo_status_t
429 _cairo_pdf_operators_emit_path (cairo_pdf_operators_t
*pdf_operators
,
430 cairo_path_fixed_t
*path
,
431 cairo_matrix_t
*path_transform
,
432 cairo_line_cap_t line_cap
)
434 cairo_output_stream_t
*word_wrap
;
435 cairo_status_t status
, status2
;
436 pdf_path_info_t info
;
439 word_wrap
= _word_wrap_stream_create (pdf_operators
->stream
, 72);
440 status
= _cairo_output_stream_get_status (word_wrap
);
442 return _cairo_output_stream_destroy (word_wrap
);
444 info
.output
= word_wrap
;
445 info
.path_transform
= path_transform
;
446 info
.line_cap
= line_cap
;
447 if (_cairo_path_fixed_is_rectangle (path
, &box
)) {
448 status
= _cairo_pdf_path_rectangle (&info
, &box
);
450 status
= _cairo_path_fixed_interpret (path
,
451 CAIRO_DIRECTION_FORWARD
,
452 _cairo_pdf_path_move_to
,
453 _cairo_pdf_path_line_to
,
454 _cairo_pdf_path_curve_to
,
455 _cairo_pdf_path_close_path
,
459 status2
= _cairo_output_stream_destroy (word_wrap
);
460 if (status
== CAIRO_STATUS_SUCCESS
)
467 _cairo_pdf_operators_clip (cairo_pdf_operators_t
*pdf_operators
,
468 cairo_path_fixed_t
*path
,
469 cairo_fill_rule_t fill_rule
)
471 const char *pdf_operator
;
472 cairo_status_t status
;
474 if (! path
->has_current_point
) {
475 /* construct an empty path */
476 _cairo_output_stream_printf (pdf_operators
->stream
, "0 0 m ");
478 status
= _cairo_pdf_operators_emit_path (pdf_operators
,
480 &pdf_operators
->cairo_to_pdf
,
481 CAIRO_LINE_CAP_ROUND
);
487 case CAIRO_FILL_RULE_WINDING
:
490 case CAIRO_FILL_RULE_EVEN_ODD
:
497 _cairo_output_stream_printf (pdf_operators
->stream
,
501 return _cairo_output_stream_get_status (pdf_operators
->stream
);
505 _cairo_pdf_line_cap (cairo_line_cap_t cap
)
508 case CAIRO_LINE_CAP_BUTT
:
510 case CAIRO_LINE_CAP_ROUND
:
512 case CAIRO_LINE_CAP_SQUARE
:
521 _cairo_pdf_line_join (cairo_line_join_t join
)
524 case CAIRO_LINE_JOIN_MITER
:
526 case CAIRO_LINE_JOIN_ROUND
:
528 case CAIRO_LINE_JOIN_BEVEL
:
537 _cairo_pdf_operators_emit_stroke_style (cairo_pdf_operators_t
*pdf_operators
,
538 cairo_stroke_style_t
*style
,
541 double *dash
= style
->dash
;
542 int num_dashes
= style
->num_dashes
;
543 double dash_offset
= style
->dash_offset
;
544 double line_width
= style
->line_width
* scale
;
546 /* PostScript has "special needs" when it comes to zero-length
547 * dash segments with butt caps. It apparently (at least
548 * according to ghostscript) draws hairlines for this
549 * case. That's not what the cairo semantics want, so we first
550 * touch up the array to eliminate any 0.0 values that will
551 * result in "on" segments.
553 if (num_dashes
&& style
->line_cap
== CAIRO_LINE_CAP_BUTT
) {
556 /* If there's an odd number of dash values they will each get
557 * interpreted as both on and off. So we first explicitly
558 * expand the array to remove the duplicate usage so that we
559 * can modify some of the values.
561 if (num_dashes
% 2) {
562 dash
= _cairo_malloc_abc (num_dashes
, 2, sizeof (double));
564 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
566 memcpy (dash
, style
->dash
, num_dashes
* sizeof (double));
567 memcpy (dash
+ num_dashes
, style
->dash
, num_dashes
* sizeof (double));
572 for (i
= 0; i
< num_dashes
; i
+= 2) {
573 if (dash
[i
] == 0.0) {
574 /* Do not modify the dashes in-place, as we may need to also
575 * replay this stroke to an image fallback.
577 if (dash
== style
->dash
) {
578 dash
= _cairo_malloc_ab (num_dashes
, sizeof (double));
580 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
581 memcpy (dash
, style
->dash
, num_dashes
* sizeof (double));
584 /* If we're at the front of the list, we first rotate
585 * two elements from the end of the list to the front
586 * of the list before folding away the 0.0. Or, if
587 * there are only two dash elements, then there is
588 * nothing at all to draw.
593 if (num_dashes
== 2) {
595 return CAIRO_INT_STATUS_NOTHING_TO_DO
;
598 /* The cases of num_dashes == 0, 1, or 3 elements
599 * cannot exist, so the rotation of 2 elements
600 * will always be safe */
601 memcpy (last_two
, dash
+ num_dashes
- 2, sizeof (last_two
));
602 memmove (dash
+ 2, dash
, (num_dashes
- 2) * sizeof (double));
603 memcpy (dash
, last_two
, sizeof (last_two
));
604 dash_offset
+= dash
[0] + dash
[1];
607 dash
[i
-1] += dash
[i
+1];
609 memmove (dash
+ i
, dash
+ i
+ 2, (num_dashes
- i
) * sizeof (double));
610 /* If we might have just rotated, it's possible that
611 * we rotated a 0.0 value to the front of the list.
612 * Set i to -2 so it will get incremented to 0. */
619 if (!pdf_operators
->has_line_style
|| pdf_operators
->line_width
!= line_width
) {
620 _cairo_output_stream_printf (pdf_operators
->stream
,
623 pdf_operators
->line_width
= line_width
;
626 if (!pdf_operators
->has_line_style
|| pdf_operators
->line_cap
!= style
->line_cap
) {
627 _cairo_output_stream_printf (pdf_operators
->stream
,
629 _cairo_pdf_line_cap (style
->line_cap
));
630 pdf_operators
->line_cap
= style
->line_cap
;
633 if (!pdf_operators
->has_line_style
|| pdf_operators
->line_join
!= style
->line_join
) {
634 _cairo_output_stream_printf (pdf_operators
->stream
,
636 _cairo_pdf_line_join (style
->line_join
));
637 pdf_operators
->line_join
= style
->line_join
;
643 _cairo_output_stream_printf (pdf_operators
->stream
, "[");
644 for (d
= 0; d
< num_dashes
; d
++)
645 _cairo_output_stream_printf (pdf_operators
->stream
, " %f", dash
[d
] * scale
);
646 _cairo_output_stream_printf (pdf_operators
->stream
, "] %f d\n",
647 dash_offset
* scale
);
648 pdf_operators
->has_dashes
= TRUE
;
649 } else if (!pdf_operators
->has_line_style
|| pdf_operators
->has_dashes
) {
650 _cairo_output_stream_printf (pdf_operators
->stream
, "[] 0.0 d\n");
651 pdf_operators
->has_dashes
= FALSE
;
653 if (dash
!= style
->dash
)
656 if (!pdf_operators
->has_line_style
|| pdf_operators
->miter_limit
!= style
->miter_limit
) {
657 _cairo_output_stream_printf (pdf_operators
->stream
,
659 style
->miter_limit
< 1.0 ? 1.0 : style
->miter_limit
);
660 pdf_operators
->miter_limit
= style
->miter_limit
;
662 pdf_operators
->has_line_style
= TRUE
;
664 return _cairo_output_stream_get_status (pdf_operators
->stream
);
667 /* Scale the matrix so the largest absolute value of the non
668 * translation components is 1.0. Return the scale required to restore
669 * the matrix to the original values.
671 * eg the matrix [ 100 0 0 50 20 10 ]
673 * is rescaled to [ 1 0 0 0.5 0.2 0.1 ]
674 * and the scale returned is 100
677 _cairo_matrix_factor_out_scale (cairo_matrix_t
*m
, double *scale
)
682 if (fabs (m
->xy
) > s
)
684 if (fabs (m
->yx
) > s
)
686 if (fabs (m
->yy
) > s
)
690 cairo_matrix_scale (m
, s
, s
);
693 static cairo_int_status_t
694 _cairo_pdf_operators_emit_stroke (cairo_pdf_operators_t
*pdf_operators
,
695 cairo_path_fixed_t
*path
,
696 cairo_stroke_style_t
*style
,
698 cairo_matrix_t
*ctm_inverse
,
699 const char *pdf_operator
)
701 cairo_status_t status
;
702 cairo_matrix_t m
, path_transform
;
703 cairo_bool_t has_ctm
= TRUE
;
706 if (pdf_operators
->in_text_object
) {
707 status
= _cairo_pdf_operators_end_text (pdf_operators
);
712 /* Optimize away the stroke ctm when it does not affect the
713 * stroke. There are other ctm cases that could be optimized
714 * however this is the most common.
716 if (fabs(ctm
->xx
) == 1.0 && fabs(ctm
->yy
) == 1.0 &&
717 fabs(ctm
->xy
) == 0.0 && fabs(ctm
->yx
) == 0.0)
722 /* The PDF CTM is transformed to the user space CTM when stroking
723 * so the corect pen shape will be used. This also requires that
724 * the path be transformed to user space when emitted. The
725 * conversion of path coordinates to user space may cause rounding
726 * errors. For example the device space point (1.234, 3.142) when
727 * transformed to a user space CTM of [100 0 0 100 0 0] will be
728 * emitted as (0.012, 0.031).
730 * To avoid the rounding problem we scale the user space CTM
731 * matrix so that all the non translation components of the matrix
732 * are <= 1. The line width and and dashes are scaled by the
733 * inverse of the scale applied to the CTM. This maintains the
734 * shape of the stroke pen while keeping the user space CTM within
735 * the range that maximizes the precision of the emitted path.
739 /* Zero out the translation since it does not affect the pen
740 * shape however it may cause unnecessary digits to be emitted.
744 _cairo_matrix_factor_out_scale (&m
, &scale
);
746 status
= cairo_matrix_invert (&path_transform
);
750 cairo_matrix_multiply (&m
, &m
, &pdf_operators
->cairo_to_pdf
);
753 status
= _cairo_pdf_operators_emit_stroke_style (pdf_operators
, style
, scale
);
754 if (status
== CAIRO_INT_STATUS_NOTHING_TO_DO
)
755 return CAIRO_STATUS_SUCCESS
;
760 _cairo_output_stream_printf (pdf_operators
->stream
,
761 "q %f %f %f %f %f %f cm\n",
762 m
.xx
, m
.yx
, m
.xy
, m
.yy
,
765 path_transform
= pdf_operators
->cairo_to_pdf
;
768 status
= _cairo_pdf_operators_emit_path (pdf_operators
,
775 _cairo_output_stream_printf (pdf_operators
->stream
, "%s", pdf_operator
);
777 _cairo_output_stream_printf (pdf_operators
->stream
, " Q");
779 _cairo_output_stream_printf (pdf_operators
->stream
, "\n");
781 return _cairo_output_stream_get_status (pdf_operators
->stream
);
785 _cairo_pdf_operators_stroke (cairo_pdf_operators_t
*pdf_operators
,
786 cairo_path_fixed_t
*path
,
787 cairo_stroke_style_t
*style
,
789 cairo_matrix_t
*ctm_inverse
)
791 return _cairo_pdf_operators_emit_stroke (pdf_operators
,
800 _cairo_pdf_operators_fill (cairo_pdf_operators_t
*pdf_operators
,
801 cairo_path_fixed_t
*path
,
802 cairo_fill_rule_t fill_rule
)
804 const char *pdf_operator
;
805 cairo_status_t status
;
807 if (pdf_operators
->in_text_object
) {
808 status
= _cairo_pdf_operators_end_text (pdf_operators
);
813 status
= _cairo_pdf_operators_emit_path (pdf_operators
,
815 &pdf_operators
->cairo_to_pdf
,
816 CAIRO_LINE_CAP_ROUND
);
821 case CAIRO_FILL_RULE_WINDING
:
824 case CAIRO_FILL_RULE_EVEN_ODD
:
831 _cairo_output_stream_printf (pdf_operators
->stream
,
835 return _cairo_output_stream_get_status (pdf_operators
->stream
);
839 _cairo_pdf_operators_fill_stroke (cairo_pdf_operators_t
*pdf_operators
,
840 cairo_path_fixed_t
*path
,
841 cairo_fill_rule_t fill_rule
,
842 cairo_stroke_style_t
*style
,
844 cairo_matrix_t
*ctm_inverse
)
846 const char *operator;
849 case CAIRO_FILL_RULE_WINDING
:
852 case CAIRO_FILL_RULE_EVEN_ODD
:
859 return _cairo_pdf_operators_emit_stroke (pdf_operators
,
867 #define GLYPH_POSITION_TOLERANCE 0.001
869 /* Emit the string of glyphs using the 'Tj' operator. This requires
870 * that the glyphs are positioned at their natural glyph advances. */
871 static cairo_status_t
872 _cairo_pdf_operators_emit_glyph_string (cairo_pdf_operators_t
*pdf_operators
,
873 cairo_output_stream_t
*stream
)
877 _cairo_output_stream_printf (stream
, "<");
878 for (i
= 0; i
< pdf_operators
->num_glyphs
; i
++) {
879 _cairo_output_stream_printf (stream
,
881 pdf_operators
->hex_width
,
882 pdf_operators
->glyphs
[i
].glyph_index
);
883 pdf_operators
->cur_x
+= pdf_operators
->glyphs
[i
].x_advance
;
885 _cairo_output_stream_printf (stream
, ">Tj\n");
887 return _cairo_output_stream_get_status (stream
);
890 /* Emit the string of glyphs using the 'TJ' operator.
892 * The TJ operator takes an array of strings of glyphs. Each string of
893 * glyphs is displayed using the glyph advances of each glyph to
894 * position the glyphs. A relative adjustment to the glyph advance may
895 * be specified by including the adjustment between two strings. The
896 * adjustment is in units of text space * -1000.
898 static cairo_status_t
899 _cairo_pdf_operators_emit_glyph_string_with_positioning (
900 cairo_pdf_operators_t
*pdf_operators
,
901 cairo_output_stream_t
*stream
)
905 _cairo_output_stream_printf (stream
, "[<");
906 for (i
= 0; i
< pdf_operators
->num_glyphs
; i
++) {
907 if (pdf_operators
->glyphs
[i
].x_position
!= pdf_operators
->cur_x
)
909 double delta
= pdf_operators
->glyphs
[i
].x_position
- pdf_operators
->cur_x
;
912 delta
= -1000.0*delta
;
913 /* As the delta is in 1/1000 of a unit of text space,
914 * rounding to an integer should still provide sufficient
915 * precision. We round the delta before adding to Tm_x so
916 * that we keep track of the accumulated rounding error in
917 * the PDF interpreter and compensate for it when
918 * calculating subsequent deltas.
920 rounded_delta
= _cairo_lround (delta
);
921 if (rounded_delta
!= 0) {
922 _cairo_output_stream_printf (stream
,
927 /* Convert the rounded delta back to text
928 * space before adding to the current text
930 delta
= rounded_delta
/-1000.0;
931 pdf_operators
->cur_x
+= delta
;
934 _cairo_output_stream_printf (stream
,
936 pdf_operators
->hex_width
,
937 pdf_operators
->glyphs
[i
].glyph_index
);
938 pdf_operators
->cur_x
+= pdf_operators
->glyphs
[i
].x_advance
;
940 _cairo_output_stream_printf (stream
, ">]TJ\n");
942 return _cairo_output_stream_get_status (stream
);
945 static cairo_status_t
946 _cairo_pdf_operators_flush_glyphs (cairo_pdf_operators_t
*pdf_operators
)
948 cairo_output_stream_t
*word_wrap_stream
;
949 cairo_status_t status
, status2
;
953 if (pdf_operators
->num_glyphs
== 0)
954 return CAIRO_STATUS_SUCCESS
;
956 word_wrap_stream
= _word_wrap_stream_create (pdf_operators
->stream
, 72);
957 status
= _cairo_output_stream_get_status (word_wrap_stream
);
959 return _cairo_output_stream_destroy (word_wrap_stream
);
961 /* Check if glyph advance used to position every glyph */
962 x
= pdf_operators
->cur_x
;
963 for (i
= 0; i
< pdf_operators
->num_glyphs
; i
++) {
964 if (fabs(pdf_operators
->glyphs
[i
].x_position
- x
) > GLYPH_POSITION_TOLERANCE
)
966 x
+= pdf_operators
->glyphs
[i
].x_advance
;
968 if (i
== pdf_operators
->num_glyphs
) {
969 status
= _cairo_pdf_operators_emit_glyph_string (pdf_operators
,
972 status
= _cairo_pdf_operators_emit_glyph_string_with_positioning (
973 pdf_operators
, word_wrap_stream
);
976 pdf_operators
->num_glyphs
= 0;
977 status2
= _cairo_output_stream_destroy (word_wrap_stream
);
978 if (status
== CAIRO_STATUS_SUCCESS
)
984 static cairo_status_t
985 _cairo_pdf_operators_add_glyph (cairo_pdf_operators_t
*pdf_operators
,
986 cairo_scaled_font_subsets_glyph_t
*glyph
,
991 x
= glyph
->x_advance
;
992 y
= glyph
->y_advance
;
993 if (glyph
->is_scaled
)
994 cairo_matrix_transform_distance (&pdf_operators
->font_matrix_inverse
, &x
, &y
);
996 pdf_operators
->glyphs
[pdf_operators
->num_glyphs
].x_position
= x_position
;
997 pdf_operators
->glyphs
[pdf_operators
->num_glyphs
].glyph_index
= glyph
->subset_glyph_index
;
998 pdf_operators
->glyphs
[pdf_operators
->num_glyphs
].x_advance
= x
;
999 pdf_operators
->num_glyphs
++;
1000 if (pdf_operators
->num_glyphs
== PDF_GLYPH_BUFFER_SIZE
)
1001 return _cairo_pdf_operators_flush_glyphs (pdf_operators
);
1003 return CAIRO_STATUS_SUCCESS
;
1006 /* Use 'Tm' operator to set the PDF text matrix. */
1007 static cairo_status_t
1008 _cairo_pdf_operators_set_text_matrix (cairo_pdf_operators_t
*pdf_operators
,
1009 cairo_matrix_t
*matrix
)
1011 cairo_matrix_t inverse
;
1012 cairo_status_t status
;
1014 /* We require the matrix to be invertable. */
1016 status
= cairo_matrix_invert (&inverse
);
1020 pdf_operators
->text_matrix
= *matrix
;
1021 pdf_operators
->cur_x
= 0;
1022 pdf_operators
->cur_y
= 0;
1023 _cairo_output_stream_printf (pdf_operators
->stream
,
1024 "%f %f %f %f %f %f Tm\n",
1025 pdf_operators
->text_matrix
.xx
,
1026 pdf_operators
->text_matrix
.yx
,
1027 pdf_operators
->text_matrix
.xy
,
1028 pdf_operators
->text_matrix
.yy
,
1029 pdf_operators
->text_matrix
.x0
,
1030 pdf_operators
->text_matrix
.y0
);
1032 pdf_operators
->cairo_to_pdftext
= *matrix
;
1033 status
= cairo_matrix_invert (&pdf_operators
->cairo_to_pdftext
);
1034 assert (status
== CAIRO_STATUS_SUCCESS
);
1035 cairo_matrix_multiply (&pdf_operators
->cairo_to_pdftext
,
1036 &pdf_operators
->cairo_to_pdf
,
1037 &pdf_operators
->cairo_to_pdftext
);
1039 return _cairo_output_stream_get_status (pdf_operators
->stream
);
1042 #define TEXT_MATRIX_TOLERANCE 1e-6
1044 /* Set the translation components of the PDF text matrix to x, y. The
1045 * 'Td' operator is used to transform the text matrix.
1047 static cairo_status_t
1048 _cairo_pdf_operators_set_text_position (cairo_pdf_operators_t
*pdf_operators
,
1052 cairo_matrix_t translate
, inverse
;
1053 cairo_status_t status
;
1055 /* The Td operator transforms the text_matrix with:
1057 * text_matrix' = T x text_matrix
1059 * where T is a translation matrix with the translation components
1060 * set to the Td operands tx and ty.
1062 inverse
= pdf_operators
->text_matrix
;
1063 status
= cairo_matrix_invert (&inverse
);
1064 assert (status
== CAIRO_STATUS_SUCCESS
);
1065 pdf_operators
->text_matrix
.x0
= x
;
1066 pdf_operators
->text_matrix
.y0
= y
;
1067 cairo_matrix_multiply (&translate
, &pdf_operators
->text_matrix
, &inverse
);
1068 if (fabs(translate
.x0
) < TEXT_MATRIX_TOLERANCE
)
1070 if (fabs(translate
.y0
) < TEXT_MATRIX_TOLERANCE
)
1072 _cairo_output_stream_printf (pdf_operators
->stream
,
1076 pdf_operators
->cur_x
= 0;
1077 pdf_operators
->cur_y
= 0;
1079 pdf_operators
->cairo_to_pdftext
= pdf_operators
->text_matrix
;
1080 status
= cairo_matrix_invert (&pdf_operators
->cairo_to_pdftext
);
1081 assert (status
== CAIRO_STATUS_SUCCESS
);
1082 cairo_matrix_multiply (&pdf_operators
->cairo_to_pdftext
,
1083 &pdf_operators
->cairo_to_pdf
,
1084 &pdf_operators
->cairo_to_pdftext
);
1086 return _cairo_output_stream_get_status (pdf_operators
->stream
);
1089 /* Select the font using the 'Tf' operator. The font size is set to 1
1090 * as we use the 'Tm' operator to set the font scale.
1092 static cairo_status_t
1093 _cairo_pdf_operators_set_font_subset (cairo_pdf_operators_t
*pdf_operators
,
1094 cairo_scaled_font_subsets_glyph_t
*subset_glyph
)
1096 cairo_status_t status
;
1098 _cairo_output_stream_printf (pdf_operators
->stream
,
1100 subset_glyph
->font_id
,
1101 subset_glyph
->subset_id
);
1102 if (pdf_operators
->use_font_subset
) {
1103 status
= pdf_operators
->use_font_subset (subset_glyph
->font_id
,
1104 subset_glyph
->subset_id
,
1105 pdf_operators
->use_font_subset_closure
);
1109 pdf_operators
->font_id
= subset_glyph
->font_id
;
1110 pdf_operators
->subset_id
= subset_glyph
->subset_id
;
1112 if (subset_glyph
->is_composite
)
1113 pdf_operators
->hex_width
= 4;
1115 pdf_operators
->hex_width
= 2;
1117 return CAIRO_STATUS_SUCCESS
;
1120 static cairo_status_t
1121 _cairo_pdf_operators_begin_text (cairo_pdf_operators_t
*pdf_operators
)
1123 _cairo_output_stream_printf (pdf_operators
->stream
, "BT\n");
1125 pdf_operators
->in_text_object
= TRUE
;
1126 pdf_operators
->num_glyphs
= 0;
1128 return _cairo_output_stream_get_status (pdf_operators
->stream
);
1131 static cairo_status_t
1132 _cairo_pdf_operators_end_text (cairo_pdf_operators_t
*pdf_operators
)
1134 cairo_status_t status
;
1136 status
= _cairo_pdf_operators_flush_glyphs (pdf_operators
);
1140 _cairo_output_stream_printf (pdf_operators
->stream
, "ET\n");
1142 pdf_operators
->in_text_object
= FALSE
;
1144 return _cairo_output_stream_get_status (pdf_operators
->stream
);
1147 /* Compare the scale components of two matrices. The translation
1148 * components are ignored. */
1150 _cairo_matrix_scale_equal (cairo_matrix_t
*a
, cairo_matrix_t
*b
)
1152 return (a
->xx
== b
->xx
&&
1158 static cairo_status_t
1159 _cairo_pdf_operators_begin_actualtext (cairo_pdf_operators_t
*pdf_operators
,
1165 cairo_status_t status
;
1168 _cairo_output_stream_printf (pdf_operators
->stream
, "/Span << /ActualText <feff");
1170 status
= _cairo_utf8_to_utf16 (utf8
, utf8_len
, &utf16
, &utf16_len
);
1174 for (i
= 0; i
< utf16_len
; i
++) {
1175 _cairo_output_stream_printf (pdf_operators
->stream
,
1176 "%04x", (int) (utf16
[i
]));
1180 _cairo_output_stream_printf (pdf_operators
->stream
, "> >> BDC\n");
1182 return _cairo_output_stream_get_status (pdf_operators
->stream
);
1185 static cairo_status_t
1186 _cairo_pdf_operators_end_actualtext (cairo_pdf_operators_t
*pdf_operators
)
1188 _cairo_output_stream_printf (pdf_operators
->stream
, "EMC\n");
1190 return _cairo_output_stream_get_status (pdf_operators
->stream
);
1193 static cairo_status_t
1194 _cairo_pdf_operators_emit_glyph (cairo_pdf_operators_t
*pdf_operators
,
1195 cairo_glyph_t
*glyph
,
1196 cairo_scaled_font_subsets_glyph_t
*subset_glyph
)
1199 cairo_status_t status
;
1201 if (pdf_operators
->is_new_text_object
||
1202 pdf_operators
->font_id
!= subset_glyph
->font_id
||
1203 pdf_operators
->subset_id
!= subset_glyph
->subset_id
)
1205 status
= _cairo_pdf_operators_flush_glyphs (pdf_operators
);
1209 status
= _cairo_pdf_operators_set_font_subset (pdf_operators
, subset_glyph
);
1213 pdf_operators
->is_new_text_object
= FALSE
;
1218 cairo_matrix_transform_point (&pdf_operators
->cairo_to_pdftext
, &x
, &y
);
1220 /* The TJ operator for displaying text strings can only set
1221 * the horizontal position of the glyphs. If the y position
1222 * (in text space) changes, use the Td operator to change the
1223 * current position to the next glyph. We also use the Td
1224 * operator to move the current position if the horizontal
1225 * position changes by more than 10 (in text space
1226 * units). This is becauses the horizontal glyph positioning
1227 * in the TJ operator is intended for kerning and there may be
1228 * PDF consumers that do not handle very large position
1229 * adjustments in TJ.
1231 if (fabs(x
- pdf_operators
->cur_x
) > 10 ||
1232 fabs(y
- pdf_operators
->cur_y
) > GLYPH_POSITION_TOLERANCE
)
1234 status
= _cairo_pdf_operators_flush_glyphs (pdf_operators
);
1240 cairo_matrix_transform_point (&pdf_operators
->cairo_to_pdf
, &x
, &y
);
1241 status
= _cairo_pdf_operators_set_text_position (pdf_operators
, x
, y
);
1249 status
= _cairo_pdf_operators_add_glyph (pdf_operators
,
1255 /* A utf8_len of -1 indicates no unicode text. A utf8_len = 0 is an
1258 static cairo_int_status_t
1259 _cairo_pdf_operators_emit_cluster (cairo_pdf_operators_t
*pdf_operators
,
1262 cairo_glyph_t
*glyphs
,
1264 cairo_text_cluster_flags_t cluster_flags
,
1265 cairo_scaled_font_t
*scaled_font
)
1267 cairo_scaled_font_subsets_glyph_t subset_glyph
;
1268 cairo_glyph_t
*cur_glyph
;
1269 cairo_status_t status
;
1272 /* If the cluster maps 1 glyph to 1 or more unicode characters, we
1273 * first try _map_glyph() with the unicode string to see if it can
1274 * use toUnicode to map our glyph to the unicode. This will fail
1275 * if the glyph is already mapped to a different unicode string.
1277 * We also go through this path if no unicode mapping was
1278 * supplied (utf8_len < 0).
1280 * Mapping a glyph to a zero length unicode string requires the
1281 * use of ActualText.
1283 if (num_glyphs
== 1 && utf8_len
!= 0) {
1284 status
= _cairo_scaled_font_subsets_map_glyph (pdf_operators
->font_subsets
,
1293 if (subset_glyph
.utf8_is_mapped
|| utf8_len
< 0) {
1294 status
= _cairo_pdf_operators_emit_glyph (pdf_operators
,
1300 return CAIRO_STATUS_SUCCESS
;
1304 /* Fallback to using ActualText to map zero or more glyphs to a
1305 * unicode string. */
1306 status
= _cairo_pdf_operators_flush_glyphs (pdf_operators
);
1310 status
= _cairo_pdf_operators_begin_actualtext (pdf_operators
, utf8
, utf8_len
);
1316 * If no glyphs, we should put *something* here for the text to be selectable. */
1317 for (i
= 0; i
< num_glyphs
; i
++) {
1318 status
= _cairo_scaled_font_subsets_map_glyph (pdf_operators
->font_subsets
,
1326 status
= _cairo_pdf_operators_emit_glyph (pdf_operators
,
1332 if ((cluster_flags
& CAIRO_TEXT_CLUSTER_FLAG_BACKWARD
))
1337 status
= _cairo_pdf_operators_flush_glyphs (pdf_operators
);
1341 status
= _cairo_pdf_operators_end_actualtext (pdf_operators
);
1347 _cairo_pdf_operators_show_text_glyphs (cairo_pdf_operators_t
*pdf_operators
,
1350 cairo_glyph_t
*glyphs
,
1352 const cairo_text_cluster_t
*clusters
,
1354 cairo_text_cluster_flags_t cluster_flags
,
1355 cairo_scaled_font_t
*scaled_font
)
1357 cairo_status_t status
;
1359 cairo_matrix_t text_matrix
, invert_y_axis
;
1361 const char *cur_text
;
1362 cairo_glyph_t
*cur_glyph
;
1364 pdf_operators
->font_matrix_inverse
= scaled_font
->font_matrix
;
1365 status
= cairo_matrix_invert (&pdf_operators
->font_matrix_inverse
);
1366 if (status
== CAIRO_STATUS_INVALID_MATRIX
)
1367 return CAIRO_STATUS_SUCCESS
;
1371 pdf_operators
->is_new_text_object
= FALSE
;
1372 if (pdf_operators
->in_text_object
== FALSE
) {
1373 status
= _cairo_pdf_operators_begin_text (pdf_operators
);
1377 /* Force Tm and Tf to be emitted when starting a new text
1379 pdf_operators
->is_new_text_object
= TRUE
;
1382 cairo_matrix_init_scale (&invert_y_axis
, 1, -1);
1383 text_matrix
= scaled_font
->scale
;
1385 /* Invert y axis in font space */
1386 cairo_matrix_multiply (&text_matrix
, &text_matrix
, &invert_y_axis
);
1388 /* Invert y axis in device space */
1389 cairo_matrix_multiply (&text_matrix
, &invert_y_axis
, &text_matrix
);
1391 if (pdf_operators
->is_new_text_object
||
1392 ! _cairo_matrix_scale_equal (&pdf_operators
->text_matrix
, &text_matrix
))
1394 status
= _cairo_pdf_operators_flush_glyphs (pdf_operators
);
1400 cairo_matrix_transform_point (&pdf_operators
->cairo_to_pdf
, &x
, &y
);
1403 status
= _cairo_pdf_operators_set_text_matrix (pdf_operators
, &text_matrix
);
1404 if (status
== CAIRO_STATUS_INVALID_MATRIX
)
1405 return CAIRO_STATUS_SUCCESS
;
1410 if (num_clusters
> 0) {
1412 if ((cluster_flags
& CAIRO_TEXT_CLUSTER_FLAG_BACKWARD
))
1413 cur_glyph
= glyphs
+ num_glyphs
;
1416 for (i
= 0; i
< num_clusters
; i
++) {
1417 if ((cluster_flags
& CAIRO_TEXT_CLUSTER_FLAG_BACKWARD
))
1418 cur_glyph
-= clusters
[i
].num_glyphs
;
1419 status
= _cairo_pdf_operators_emit_cluster (pdf_operators
,
1421 clusters
[i
].num_bytes
,
1423 clusters
[i
].num_glyphs
,
1429 cur_text
+= clusters
[i
].num_bytes
;
1430 if (!(cluster_flags
& CAIRO_TEXT_CLUSTER_FLAG_BACKWARD
))
1431 cur_glyph
+= clusters
[i
].num_glyphs
;
1434 for (i
= 0; i
< num_glyphs
; i
++) {
1435 status
= _cairo_pdf_operators_emit_cluster (pdf_operators
,
1437 -1, /* no unicode string available */
1447 return _cairo_output_stream_get_status (pdf_operators
->stream
);
1450 #endif /* CAIRO_HAS_PDF_OPERATORS */