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
;
71 pdf_operators
->use_actual_text
= FALSE
;
75 _cairo_pdf_operators_fini (cairo_pdf_operators_t
*pdf_operators
)
77 return _cairo_pdf_operators_flush (pdf_operators
);
81 _cairo_pdf_operators_set_font_subsets_callback (cairo_pdf_operators_t
*pdf_operators
,
82 cairo_pdf_operators_use_font_subset_t use_font_subset
,
85 pdf_operators
->use_font_subset
= use_font_subset
;
86 pdf_operators
->use_font_subset_closure
= closure
;
89 /* Change the output stream to a different stream.
90 * _cairo_pdf_operators_flush() should always be called before calling
94 _cairo_pdf_operators_set_stream (cairo_pdf_operators_t
*pdf_operators
,
95 cairo_output_stream_t
*stream
)
97 pdf_operators
->stream
= stream
;
98 pdf_operators
->has_line_style
= FALSE
;
102 _cairo_pdf_operators_set_cairo_to_pdf_matrix (cairo_pdf_operators_t
*pdf_operators
,
103 cairo_matrix_t
*cairo_to_pdf
)
105 pdf_operators
->cairo_to_pdf
= *cairo_to_pdf
;
106 pdf_operators
->has_line_style
= FALSE
;
110 _cairo_pdf_operators_enable_actual_text (cairo_pdf_operators_t
*pdf_operators
,
113 pdf_operators
->use_actual_text
= enable
;
116 /* Finish writing out any pending commands to the stream. This
117 * function must be called by the surface before emitting anything
118 * into the PDF stream.
120 * pdf_operators may leave the emitted PDF for some operations
121 * unfinished in case subsequent operations can be merged. This
122 * function will finish off any incomplete operation so the stream
123 * will be in a state where the surface may emit its own PDF
124 * operations (eg changing patterns).
128 _cairo_pdf_operators_flush (cairo_pdf_operators_t
*pdf_operators
)
130 cairo_status_t status
= CAIRO_STATUS_SUCCESS
;
132 if (pdf_operators
->in_text_object
)
133 status
= _cairo_pdf_operators_end_text (pdf_operators
);
138 /* Reset the known graphics state of the PDF consumer. ie no
139 * assumptions will be made about the state. The next time a
140 * particular graphics state is required (eg line width) the state
141 * operator is always emitted and then remembered for subsequent
144 * This should be called when starting a new stream or after emitting
145 * the 'Q' operator (where pdf-operators functions were called inside
149 _cairo_pdf_operators_reset (cairo_pdf_operators_t
*pdf_operators
)
151 pdf_operators
->has_line_style
= FALSE
;
154 /* A word wrap stream can be used as a filter to do word wrapping on
155 * top of an existing output stream. The word wrapping is quite
156 * simple, using isspace to determine characters that separate
157 * words. Any word that will cause the column count exceed the given
158 * max_column will have a '\n' character emitted before it.
160 * The stream is careful to maintain integrity for words that cross
161 * the boundary from one call to write to the next.
163 * Note: This stream does not guarantee that the output will never
164 * exceed max_column. In particular, if a single word is larger than
165 * max_column it will not be broken up.
167 typedef struct _word_wrap_stream
{
168 cairo_output_stream_t base
;
169 cairo_output_stream_t
*output
;
172 cairo_bool_t last_write_was_space
;
173 cairo_bool_t in_hexstring
;
174 cairo_bool_t empty_hexstring
;
175 } word_wrap_stream_t
;
178 _count_word_up_to (const unsigned char *s
, int length
)
183 if (! (isspace (*s
) || *s
== '<')) {
195 /* Count up to either the end of the ASCII hexstring or the number
196 * of columns remaining.
199 _count_hexstring_up_to (const unsigned char *s
, int length
, int columns
)
210 if (columns
< 0 && word
> 1)
217 static cairo_status_t
218 _word_wrap_stream_write (cairo_output_stream_t
*base
,
219 const unsigned char *data
,
222 word_wrap_stream_t
*stream
= (word_wrap_stream_t
*) base
;
223 cairo_bool_t newline
;
228 stream
->in_hexstring
= TRUE
;
229 stream
->empty_hexstring
= TRUE
;
230 stream
->last_write_was_space
= FALSE
;
233 _cairo_output_stream_printf (stream
->output
, "<");
235 } else if (*data
== '>') {
236 stream
->in_hexstring
= FALSE
;
237 stream
->last_write_was_space
= FALSE
;
240 _cairo_output_stream_printf (stream
->output
, ">");
242 } else if (isspace (*data
)) {
243 newline
= (*data
== '\n' || *data
== '\r');
244 if (! newline
&& stream
->column
>= stream
->max_column
) {
245 _cairo_output_stream_printf (stream
->output
, "\n");
248 _cairo_output_stream_write (stream
->output
, data
, 1);
256 stream
->last_write_was_space
= TRUE
;
258 if (stream
->in_hexstring
) {
259 word
= _count_hexstring_up_to (data
, length
,
260 MAX (stream
->max_column
- stream
->column
, 0));
262 word
= _count_word_up_to (data
, length
);
264 /* Don't wrap if this word is a continuation of a non hex
265 * string word from a previous call to write. */
266 if (stream
->column
+ word
>= stream
->max_column
) {
267 if (stream
->last_write_was_space
||
268 (stream
->in_hexstring
&& !stream
->empty_hexstring
))
270 _cairo_output_stream_printf (stream
->output
, "\n");
274 _cairo_output_stream_write (stream
->output
, data
, word
);
277 stream
->column
+= word
;
278 stream
->last_write_was_space
= FALSE
;
279 if (stream
->in_hexstring
)
280 stream
->empty_hexstring
= FALSE
;
284 return _cairo_output_stream_get_status (stream
->output
);
287 static cairo_status_t
288 _word_wrap_stream_close (cairo_output_stream_t
*base
)
290 word_wrap_stream_t
*stream
= (word_wrap_stream_t
*) base
;
292 return _cairo_output_stream_get_status (stream
->output
);
295 static cairo_output_stream_t
*
296 _word_wrap_stream_create (cairo_output_stream_t
*output
, int max_column
)
298 word_wrap_stream_t
*stream
;
301 return _cairo_output_stream_create_in_error (output
->status
);
303 stream
= malloc (sizeof (word_wrap_stream_t
));
304 if (unlikely (stream
== NULL
)) {
305 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY
);
306 return (cairo_output_stream_t
*) &_cairo_output_stream_nil
;
309 _cairo_output_stream_init (&stream
->base
,
310 _word_wrap_stream_write
,
312 _word_wrap_stream_close
);
313 stream
->output
= output
;
314 stream
->max_column
= max_column
;
316 stream
->last_write_was_space
= FALSE
;
317 stream
->in_hexstring
= FALSE
;
318 stream
->empty_hexstring
= TRUE
;
320 return &stream
->base
;
323 typedef struct _pdf_path_info
{
324 cairo_output_stream_t
*output
;
325 cairo_matrix_t
*path_transform
;
326 cairo_line_cap_t line_cap
;
327 cairo_point_t last_move_to_point
;
328 cairo_bool_t has_sub_path
;
331 static cairo_status_t
332 _cairo_pdf_path_move_to (void *closure
,
333 const cairo_point_t
*point
)
335 pdf_path_info_t
*info
= closure
;
336 double x
= _cairo_fixed_to_double (point
->x
);
337 double y
= _cairo_fixed_to_double (point
->y
);
339 info
->last_move_to_point
= *point
;
340 info
->has_sub_path
= FALSE
;
341 cairo_matrix_transform_point (info
->path_transform
, &x
, &y
);
342 _cairo_output_stream_printf (info
->output
,
345 return _cairo_output_stream_get_status (info
->output
);
348 static cairo_status_t
349 _cairo_pdf_path_line_to (void *closure
,
350 const cairo_point_t
*point
)
352 pdf_path_info_t
*info
= closure
;
353 double x
= _cairo_fixed_to_double (point
->x
);
354 double y
= _cairo_fixed_to_double (point
->y
);
356 if (info
->line_cap
!= CAIRO_LINE_CAP_ROUND
&&
357 ! info
->has_sub_path
&&
358 point
->x
== info
->last_move_to_point
.x
&&
359 point
->y
== info
->last_move_to_point
.y
)
361 return CAIRO_STATUS_SUCCESS
;
364 info
->has_sub_path
= TRUE
;
365 cairo_matrix_transform_point (info
->path_transform
, &x
, &y
);
366 _cairo_output_stream_printf (info
->output
,
369 return _cairo_output_stream_get_status (info
->output
);
372 static cairo_status_t
373 _cairo_pdf_path_curve_to (void *closure
,
374 const cairo_point_t
*b
,
375 const cairo_point_t
*c
,
376 const cairo_point_t
*d
)
378 pdf_path_info_t
*info
= closure
;
379 double bx
= _cairo_fixed_to_double (b
->x
);
380 double by
= _cairo_fixed_to_double (b
->y
);
381 double cx
= _cairo_fixed_to_double (c
->x
);
382 double cy
= _cairo_fixed_to_double (c
->y
);
383 double dx
= _cairo_fixed_to_double (d
->x
);
384 double dy
= _cairo_fixed_to_double (d
->y
);
386 info
->has_sub_path
= TRUE
;
387 cairo_matrix_transform_point (info
->path_transform
, &bx
, &by
);
388 cairo_matrix_transform_point (info
->path_transform
, &cx
, &cy
);
389 cairo_matrix_transform_point (info
->path_transform
, &dx
, &dy
);
390 _cairo_output_stream_printf (info
->output
,
391 "%g %g %g %g %g %g c ",
392 bx
, by
, cx
, cy
, dx
, dy
);
393 return _cairo_output_stream_get_status (info
->output
);
396 static cairo_status_t
397 _cairo_pdf_path_close_path (void *closure
)
399 pdf_path_info_t
*info
= closure
;
401 if (info
->line_cap
!= CAIRO_LINE_CAP_ROUND
&&
402 ! info
->has_sub_path
)
404 return CAIRO_STATUS_SUCCESS
;
407 _cairo_output_stream_printf (info
->output
,
410 return _cairo_output_stream_get_status (info
->output
);
413 static cairo_status_t
414 _cairo_pdf_path_rectangle (pdf_path_info_t
*info
, cairo_box_t
*box
)
416 double x1
= _cairo_fixed_to_double (box
->p1
.x
);
417 double y1
= _cairo_fixed_to_double (box
->p1
.y
);
418 double x2
= _cairo_fixed_to_double (box
->p2
.x
);
419 double y2
= _cairo_fixed_to_double (box
->p2
.y
);
421 cairo_matrix_transform_point (info
->path_transform
, &x1
, &y1
);
422 cairo_matrix_transform_point (info
->path_transform
, &x2
, &y2
);
423 _cairo_output_stream_printf (info
->output
,
425 x1
, y1
, x2
- x1
, y2
- y1
);
427 return _cairo_output_stream_get_status (info
->output
);
430 /* The line cap value is needed to workaround the fact that PostScript
431 * and PDF semantics for stroking degenerate sub-paths do not match
432 * cairo semantics. (PostScript draws something for any line cap
433 * value, while cairo draws something only for round caps).
435 * When using this function to emit a path to be filled, rather than
436 * stroked, simply pass %CAIRO_LINE_CAP_ROUND which will guarantee that
437 * the stroke workaround will not modify the path being emitted.
439 static cairo_status_t
440 _cairo_pdf_operators_emit_path (cairo_pdf_operators_t
*pdf_operators
,
441 cairo_path_fixed_t
*path
,
442 cairo_matrix_t
*path_transform
,
443 cairo_line_cap_t line_cap
)
445 cairo_output_stream_t
*word_wrap
;
446 cairo_status_t status
, status2
;
447 pdf_path_info_t info
;
450 word_wrap
= _word_wrap_stream_create (pdf_operators
->stream
, 72);
451 status
= _cairo_output_stream_get_status (word_wrap
);
452 if (unlikely (status
))
453 return _cairo_output_stream_destroy (word_wrap
);
455 info
.output
= word_wrap
;
456 info
.path_transform
= path_transform
;
457 info
.line_cap
= line_cap
;
458 if (_cairo_path_fixed_is_rectangle (path
, &box
)) {
459 status
= _cairo_pdf_path_rectangle (&info
, &box
);
461 status
= _cairo_path_fixed_interpret (path
,
462 CAIRO_DIRECTION_FORWARD
,
463 _cairo_pdf_path_move_to
,
464 _cairo_pdf_path_line_to
,
465 _cairo_pdf_path_curve_to
,
466 _cairo_pdf_path_close_path
,
470 status2
= _cairo_output_stream_destroy (word_wrap
);
471 if (status
== CAIRO_STATUS_SUCCESS
)
478 _cairo_pdf_operators_clip (cairo_pdf_operators_t
*pdf_operators
,
479 cairo_path_fixed_t
*path
,
480 cairo_fill_rule_t fill_rule
)
482 const char *pdf_operator
;
483 cairo_status_t status
;
485 if (! path
->has_current_point
) {
486 /* construct an empty path */
487 _cairo_output_stream_printf (pdf_operators
->stream
, "0 0 m ");
489 status
= _cairo_pdf_operators_emit_path (pdf_operators
,
491 &pdf_operators
->cairo_to_pdf
,
492 CAIRO_LINE_CAP_ROUND
);
493 if (unlikely (status
))
498 case CAIRO_FILL_RULE_WINDING
:
501 case CAIRO_FILL_RULE_EVEN_ODD
:
508 _cairo_output_stream_printf (pdf_operators
->stream
,
512 return _cairo_output_stream_get_status (pdf_operators
->stream
);
516 _cairo_pdf_line_cap (cairo_line_cap_t cap
)
519 case CAIRO_LINE_CAP_BUTT
:
521 case CAIRO_LINE_CAP_ROUND
:
523 case CAIRO_LINE_CAP_SQUARE
:
532 _cairo_pdf_line_join (cairo_line_join_t join
)
535 case CAIRO_LINE_JOIN_MITER
:
537 case CAIRO_LINE_JOIN_ROUND
:
539 case CAIRO_LINE_JOIN_BEVEL
:
548 _cairo_pdf_operators_emit_stroke_style (cairo_pdf_operators_t
*pdf_operators
,
549 cairo_stroke_style_t
*style
,
552 double *dash
= style
->dash
;
553 int num_dashes
= style
->num_dashes
;
554 double dash_offset
= style
->dash_offset
;
555 double line_width
= style
->line_width
* scale
;
557 /* PostScript has "special needs" when it comes to zero-length
558 * dash segments with butt caps. It apparently (at least
559 * according to ghostscript) draws hairlines for this
560 * case. That's not what the cairo semantics want, so we first
561 * touch up the array to eliminate any 0.0 values that will
562 * result in "on" segments.
564 if (num_dashes
&& style
->line_cap
== CAIRO_LINE_CAP_BUTT
) {
567 /* If there's an odd number of dash values they will each get
568 * interpreted as both on and off. So we first explicitly
569 * expand the array to remove the duplicate usage so that we
570 * can modify some of the values.
572 if (num_dashes
% 2) {
573 dash
= _cairo_malloc_abc (num_dashes
, 2, sizeof (double));
574 if (unlikely (dash
== NULL
))
575 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
577 memcpy (dash
, style
->dash
, num_dashes
* sizeof (double));
578 memcpy (dash
+ num_dashes
, style
->dash
, num_dashes
* sizeof (double));
583 for (i
= 0; i
< num_dashes
; i
+= 2) {
584 if (dash
[i
] == 0.0) {
585 /* Do not modify the dashes in-place, as we may need to also
586 * replay this stroke to an image fallback.
588 if (dash
== style
->dash
) {
589 dash
= _cairo_malloc_ab (num_dashes
, sizeof (double));
590 if (unlikely (dash
== NULL
))
591 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
592 memcpy (dash
, style
->dash
, num_dashes
* sizeof (double));
595 /* If we're at the front of the list, we first rotate
596 * two elements from the end of the list to the front
597 * of the list before folding away the 0.0. Or, if
598 * there are only two dash elements, then there is
599 * nothing at all to draw.
604 if (num_dashes
== 2) {
606 return CAIRO_INT_STATUS_NOTHING_TO_DO
;
609 /* The cases of num_dashes == 0, 1, or 3 elements
610 * cannot exist, so the rotation of 2 elements
611 * will always be safe */
612 memcpy (last_two
, dash
+ num_dashes
- 2, sizeof (last_two
));
613 memmove (dash
+ 2, dash
, (num_dashes
- 2) * sizeof (double));
614 memcpy (dash
, last_two
, sizeof (last_two
));
615 dash_offset
+= dash
[0] + dash
[1];
618 dash
[i
-1] += dash
[i
+1];
620 memmove (dash
+ i
, dash
+ i
+ 2, (num_dashes
- i
) * sizeof (double));
621 /* If we might have just rotated, it's possible that
622 * we rotated a 0.0 value to the front of the list.
623 * Set i to -2 so it will get incremented to 0. */
630 if (!pdf_operators
->has_line_style
|| pdf_operators
->line_width
!= line_width
) {
631 _cairo_output_stream_printf (pdf_operators
->stream
,
634 pdf_operators
->line_width
= line_width
;
637 if (!pdf_operators
->has_line_style
|| pdf_operators
->line_cap
!= style
->line_cap
) {
638 _cairo_output_stream_printf (pdf_operators
->stream
,
640 _cairo_pdf_line_cap (style
->line_cap
));
641 pdf_operators
->line_cap
= style
->line_cap
;
644 if (!pdf_operators
->has_line_style
|| pdf_operators
->line_join
!= style
->line_join
) {
645 _cairo_output_stream_printf (pdf_operators
->stream
,
647 _cairo_pdf_line_join (style
->line_join
));
648 pdf_operators
->line_join
= style
->line_join
;
654 _cairo_output_stream_printf (pdf_operators
->stream
, "[");
655 for (d
= 0; d
< num_dashes
; d
++)
656 _cairo_output_stream_printf (pdf_operators
->stream
, " %f", dash
[d
] * scale
);
657 _cairo_output_stream_printf (pdf_operators
->stream
, "] %f d\n",
658 dash_offset
* scale
);
659 pdf_operators
->has_dashes
= TRUE
;
660 } else if (!pdf_operators
->has_line_style
|| pdf_operators
->has_dashes
) {
661 _cairo_output_stream_printf (pdf_operators
->stream
, "[] 0.0 d\n");
662 pdf_operators
->has_dashes
= FALSE
;
664 if (dash
!= style
->dash
)
667 if (!pdf_operators
->has_line_style
|| pdf_operators
->miter_limit
!= style
->miter_limit
) {
668 _cairo_output_stream_printf (pdf_operators
->stream
,
670 style
->miter_limit
< 1.0 ? 1.0 : style
->miter_limit
);
671 pdf_operators
->miter_limit
= style
->miter_limit
;
673 pdf_operators
->has_line_style
= TRUE
;
675 return _cairo_output_stream_get_status (pdf_operators
->stream
);
678 /* Scale the matrix so the largest absolute value of the non
679 * translation components is 1.0. Return the scale required to restore
680 * the matrix to the original values.
682 * eg the matrix [ 100 0 0 50 20 10 ]
684 * is rescaled to [ 1 0 0 0.5 0.2 0.1 ]
685 * and the scale returned is 100
688 _cairo_matrix_factor_out_scale (cairo_matrix_t
*m
, double *scale
)
693 if (fabs (m
->xy
) > s
)
695 if (fabs (m
->yx
) > s
)
697 if (fabs (m
->yy
) > s
)
701 cairo_matrix_scale (m
, s
, s
);
704 static cairo_int_status_t
705 _cairo_pdf_operators_emit_stroke (cairo_pdf_operators_t
*pdf_operators
,
706 cairo_path_fixed_t
*path
,
707 cairo_stroke_style_t
*style
,
709 cairo_matrix_t
*ctm_inverse
,
710 const char *pdf_operator
)
712 cairo_status_t status
;
713 cairo_matrix_t m
, path_transform
;
714 cairo_bool_t has_ctm
= TRUE
;
717 if (pdf_operators
->in_text_object
) {
718 status
= _cairo_pdf_operators_end_text (pdf_operators
);
719 if (unlikely (status
))
723 /* Optimize away the stroke ctm when it does not affect the
724 * stroke. There are other ctm cases that could be optimized
725 * however this is the most common.
727 if (fabs(ctm
->xx
) == 1.0 && fabs(ctm
->yy
) == 1.0 &&
728 fabs(ctm
->xy
) == 0.0 && fabs(ctm
->yx
) == 0.0)
733 /* The PDF CTM is transformed to the user space CTM when stroking
734 * so the corect pen shape will be used. This also requires that
735 * the path be transformed to user space when emitted. The
736 * conversion of path coordinates to user space may cause rounding
737 * errors. For example the device space point (1.234, 3.142) when
738 * transformed to a user space CTM of [100 0 0 100 0 0] will be
739 * emitted as (0.012, 0.031).
741 * To avoid the rounding problem we scale the user space CTM
742 * matrix so that all the non translation components of the matrix
743 * are <= 1. The line width and and dashes are scaled by the
744 * inverse of the scale applied to the CTM. This maintains the
745 * shape of the stroke pen while keeping the user space CTM within
746 * the range that maximizes the precision of the emitted path.
750 /* Zero out the translation since it does not affect the pen
751 * shape however it may cause unnecessary digits to be emitted.
755 _cairo_matrix_factor_out_scale (&m
, &scale
);
757 status
= cairo_matrix_invert (&path_transform
);
758 if (unlikely (status
))
761 cairo_matrix_multiply (&m
, &m
, &pdf_operators
->cairo_to_pdf
);
764 status
= _cairo_pdf_operators_emit_stroke_style (pdf_operators
, style
, scale
);
765 if (status
== CAIRO_INT_STATUS_NOTHING_TO_DO
)
766 return CAIRO_STATUS_SUCCESS
;
767 if (unlikely (status
))
771 _cairo_output_stream_printf (pdf_operators
->stream
,
772 "q %f %f %f %f %f %f cm\n",
773 m
.xx
, m
.yx
, m
.xy
, m
.yy
,
776 path_transform
= pdf_operators
->cairo_to_pdf
;
779 status
= _cairo_pdf_operators_emit_path (pdf_operators
,
783 if (unlikely (status
))
786 _cairo_output_stream_printf (pdf_operators
->stream
, "%s", pdf_operator
);
788 _cairo_output_stream_printf (pdf_operators
->stream
, " Q");
790 _cairo_output_stream_printf (pdf_operators
->stream
, "\n");
792 return _cairo_output_stream_get_status (pdf_operators
->stream
);
796 _cairo_pdf_operators_stroke (cairo_pdf_operators_t
*pdf_operators
,
797 cairo_path_fixed_t
*path
,
798 cairo_stroke_style_t
*style
,
800 cairo_matrix_t
*ctm_inverse
)
802 return _cairo_pdf_operators_emit_stroke (pdf_operators
,
811 _cairo_pdf_operators_fill (cairo_pdf_operators_t
*pdf_operators
,
812 cairo_path_fixed_t
*path
,
813 cairo_fill_rule_t fill_rule
)
815 const char *pdf_operator
;
816 cairo_status_t status
;
818 if (pdf_operators
->in_text_object
) {
819 status
= _cairo_pdf_operators_end_text (pdf_operators
);
820 if (unlikely (status
))
824 status
= _cairo_pdf_operators_emit_path (pdf_operators
,
826 &pdf_operators
->cairo_to_pdf
,
827 CAIRO_LINE_CAP_ROUND
);
828 if (unlikely (status
))
832 case CAIRO_FILL_RULE_WINDING
:
835 case CAIRO_FILL_RULE_EVEN_ODD
:
842 _cairo_output_stream_printf (pdf_operators
->stream
,
846 return _cairo_output_stream_get_status (pdf_operators
->stream
);
850 _cairo_pdf_operators_fill_stroke (cairo_pdf_operators_t
*pdf_operators
,
851 cairo_path_fixed_t
*path
,
852 cairo_fill_rule_t fill_rule
,
853 cairo_stroke_style_t
*style
,
855 cairo_matrix_t
*ctm_inverse
)
857 const char *operator;
860 case CAIRO_FILL_RULE_WINDING
:
863 case CAIRO_FILL_RULE_EVEN_ODD
:
870 return _cairo_pdf_operators_emit_stroke (pdf_operators
,
878 #define GLYPH_POSITION_TOLERANCE 0.001
880 /* Emit the string of glyphs using the 'Tj' operator. This requires
881 * that the glyphs are positioned at their natural glyph advances. */
882 static cairo_status_t
883 _cairo_pdf_operators_emit_glyph_string (cairo_pdf_operators_t
*pdf_operators
,
884 cairo_output_stream_t
*stream
)
888 _cairo_output_stream_printf (stream
, "<");
889 for (i
= 0; i
< pdf_operators
->num_glyphs
; i
++) {
890 _cairo_output_stream_printf (stream
,
892 pdf_operators
->hex_width
,
893 pdf_operators
->glyphs
[i
].glyph_index
);
894 pdf_operators
->cur_x
+= pdf_operators
->glyphs
[i
].x_advance
;
896 _cairo_output_stream_printf (stream
, ">Tj\n");
898 return _cairo_output_stream_get_status (stream
);
901 /* Emit the string of glyphs using the 'TJ' operator.
903 * The TJ operator takes an array of strings of glyphs. Each string of
904 * glyphs is displayed using the glyph advances of each glyph to
905 * position the glyphs. A relative adjustment to the glyph advance may
906 * be specified by including the adjustment between two strings. The
907 * adjustment is in units of text space * -1000.
909 static cairo_status_t
910 _cairo_pdf_operators_emit_glyph_string_with_positioning (
911 cairo_pdf_operators_t
*pdf_operators
,
912 cairo_output_stream_t
*stream
)
916 _cairo_output_stream_printf (stream
, "[<");
917 for (i
= 0; i
< pdf_operators
->num_glyphs
; i
++) {
918 if (pdf_operators
->glyphs
[i
].x_position
!= pdf_operators
->cur_x
)
920 double delta
= pdf_operators
->glyphs
[i
].x_position
- pdf_operators
->cur_x
;
923 delta
= -1000.0*delta
;
924 /* As the delta is in 1/1000 of a unit of text space,
925 * rounding to an integer should still provide sufficient
926 * precision. We round the delta before adding to Tm_x so
927 * that we keep track of the accumulated rounding error in
928 * the PDF interpreter and compensate for it when
929 * calculating subsequent deltas.
931 rounded_delta
= _cairo_lround (delta
);
932 if (rounded_delta
!= 0) {
933 _cairo_output_stream_printf (stream
,
938 /* Convert the rounded delta back to text
939 * space before adding to the current text
941 delta
= rounded_delta
/-1000.0;
942 pdf_operators
->cur_x
+= delta
;
945 _cairo_output_stream_printf (stream
,
947 pdf_operators
->hex_width
,
948 pdf_operators
->glyphs
[i
].glyph_index
);
949 pdf_operators
->cur_x
+= pdf_operators
->glyphs
[i
].x_advance
;
951 _cairo_output_stream_printf (stream
, ">]TJ\n");
953 return _cairo_output_stream_get_status (stream
);
956 static cairo_status_t
957 _cairo_pdf_operators_flush_glyphs (cairo_pdf_operators_t
*pdf_operators
)
959 cairo_output_stream_t
*word_wrap_stream
;
960 cairo_status_t status
, status2
;
964 if (pdf_operators
->num_glyphs
== 0)
965 return CAIRO_STATUS_SUCCESS
;
967 word_wrap_stream
= _word_wrap_stream_create (pdf_operators
->stream
, 72);
968 status
= _cairo_output_stream_get_status (word_wrap_stream
);
969 if (unlikely (status
))
970 return _cairo_output_stream_destroy (word_wrap_stream
);
972 /* Check if glyph advance used to position every glyph */
973 x
= pdf_operators
->cur_x
;
974 for (i
= 0; i
< pdf_operators
->num_glyphs
; i
++) {
975 if (fabs(pdf_operators
->glyphs
[i
].x_position
- x
) > GLYPH_POSITION_TOLERANCE
)
977 x
+= pdf_operators
->glyphs
[i
].x_advance
;
979 if (i
== pdf_operators
->num_glyphs
) {
980 status
= _cairo_pdf_operators_emit_glyph_string (pdf_operators
,
983 status
= _cairo_pdf_operators_emit_glyph_string_with_positioning (
984 pdf_operators
, word_wrap_stream
);
987 pdf_operators
->num_glyphs
= 0;
988 status2
= _cairo_output_stream_destroy (word_wrap_stream
);
989 if (status
== CAIRO_STATUS_SUCCESS
)
995 static cairo_status_t
996 _cairo_pdf_operators_add_glyph (cairo_pdf_operators_t
*pdf_operators
,
997 cairo_scaled_font_subsets_glyph_t
*glyph
,
1002 x
= glyph
->x_advance
;
1003 y
= glyph
->y_advance
;
1004 if (glyph
->is_scaled
)
1005 cairo_matrix_transform_distance (&pdf_operators
->font_matrix_inverse
, &x
, &y
);
1007 pdf_operators
->glyphs
[pdf_operators
->num_glyphs
].x_position
= x_position
;
1008 pdf_operators
->glyphs
[pdf_operators
->num_glyphs
].glyph_index
= glyph
->subset_glyph_index
;
1009 pdf_operators
->glyphs
[pdf_operators
->num_glyphs
].x_advance
= x
;
1010 pdf_operators
->num_glyphs
++;
1011 if (pdf_operators
->num_glyphs
== PDF_GLYPH_BUFFER_SIZE
)
1012 return _cairo_pdf_operators_flush_glyphs (pdf_operators
);
1014 return CAIRO_STATUS_SUCCESS
;
1017 /* Use 'Tm' operator to set the PDF text matrix. */
1018 static cairo_status_t
1019 _cairo_pdf_operators_set_text_matrix (cairo_pdf_operators_t
*pdf_operators
,
1020 cairo_matrix_t
*matrix
)
1022 cairo_matrix_t inverse
;
1023 cairo_status_t status
;
1025 /* We require the matrix to be invertable. */
1027 status
= cairo_matrix_invert (&inverse
);
1028 if (unlikely (status
))
1031 pdf_operators
->text_matrix
= *matrix
;
1032 pdf_operators
->cur_x
= 0;
1033 pdf_operators
->cur_y
= 0;
1034 _cairo_output_stream_printf (pdf_operators
->stream
,
1035 "%f %f %f %f %f %f Tm\n",
1036 pdf_operators
->text_matrix
.xx
,
1037 pdf_operators
->text_matrix
.yx
,
1038 pdf_operators
->text_matrix
.xy
,
1039 pdf_operators
->text_matrix
.yy
,
1040 pdf_operators
->text_matrix
.x0
,
1041 pdf_operators
->text_matrix
.y0
);
1043 pdf_operators
->cairo_to_pdftext
= *matrix
;
1044 status
= cairo_matrix_invert (&pdf_operators
->cairo_to_pdftext
);
1045 assert (status
== CAIRO_STATUS_SUCCESS
);
1046 cairo_matrix_multiply (&pdf_operators
->cairo_to_pdftext
,
1047 &pdf_operators
->cairo_to_pdf
,
1048 &pdf_operators
->cairo_to_pdftext
);
1050 return _cairo_output_stream_get_status (pdf_operators
->stream
);
1053 #define TEXT_MATRIX_TOLERANCE 1e-6
1055 /* Set the translation components of the PDF text matrix to x, y. The
1056 * 'Td' operator is used to transform the text matrix.
1058 static cairo_status_t
1059 _cairo_pdf_operators_set_text_position (cairo_pdf_operators_t
*pdf_operators
,
1063 cairo_matrix_t translate
, inverse
;
1064 cairo_status_t status
;
1066 /* The Td operator transforms the text_matrix with:
1068 * text_matrix' = T x text_matrix
1070 * where T is a translation matrix with the translation components
1071 * set to the Td operands tx and ty.
1073 inverse
= pdf_operators
->text_matrix
;
1074 status
= cairo_matrix_invert (&inverse
);
1075 assert (status
== CAIRO_STATUS_SUCCESS
);
1076 pdf_operators
->text_matrix
.x0
= x
;
1077 pdf_operators
->text_matrix
.y0
= y
;
1078 cairo_matrix_multiply (&translate
, &pdf_operators
->text_matrix
, &inverse
);
1079 if (fabs(translate
.x0
) < TEXT_MATRIX_TOLERANCE
)
1081 if (fabs(translate
.y0
) < TEXT_MATRIX_TOLERANCE
)
1083 _cairo_output_stream_printf (pdf_operators
->stream
,
1087 pdf_operators
->cur_x
= 0;
1088 pdf_operators
->cur_y
= 0;
1090 pdf_operators
->cairo_to_pdftext
= pdf_operators
->text_matrix
;
1091 status
= cairo_matrix_invert (&pdf_operators
->cairo_to_pdftext
);
1092 assert (status
== CAIRO_STATUS_SUCCESS
);
1093 cairo_matrix_multiply (&pdf_operators
->cairo_to_pdftext
,
1094 &pdf_operators
->cairo_to_pdf
,
1095 &pdf_operators
->cairo_to_pdftext
);
1097 return _cairo_output_stream_get_status (pdf_operators
->stream
);
1100 /* Select the font using the 'Tf' operator. The font size is set to 1
1101 * as we use the 'Tm' operator to set the font scale.
1103 static cairo_status_t
1104 _cairo_pdf_operators_set_font_subset (cairo_pdf_operators_t
*pdf_operators
,
1105 cairo_scaled_font_subsets_glyph_t
*subset_glyph
)
1107 cairo_status_t status
;
1109 _cairo_output_stream_printf (pdf_operators
->stream
,
1111 subset_glyph
->font_id
,
1112 subset_glyph
->subset_id
);
1113 if (pdf_operators
->use_font_subset
) {
1114 status
= pdf_operators
->use_font_subset (subset_glyph
->font_id
,
1115 subset_glyph
->subset_id
,
1116 pdf_operators
->use_font_subset_closure
);
1117 if (unlikely (status
))
1120 pdf_operators
->font_id
= subset_glyph
->font_id
;
1121 pdf_operators
->subset_id
= subset_glyph
->subset_id
;
1123 if (subset_glyph
->is_composite
)
1124 pdf_operators
->hex_width
= 4;
1126 pdf_operators
->hex_width
= 2;
1128 return CAIRO_STATUS_SUCCESS
;
1131 static cairo_status_t
1132 _cairo_pdf_operators_begin_text (cairo_pdf_operators_t
*pdf_operators
)
1134 _cairo_output_stream_printf (pdf_operators
->stream
, "BT\n");
1136 pdf_operators
->in_text_object
= TRUE
;
1137 pdf_operators
->num_glyphs
= 0;
1139 return _cairo_output_stream_get_status (pdf_operators
->stream
);
1142 static cairo_status_t
1143 _cairo_pdf_operators_end_text (cairo_pdf_operators_t
*pdf_operators
)
1145 cairo_status_t status
;
1147 status
= _cairo_pdf_operators_flush_glyphs (pdf_operators
);
1148 if (unlikely (status
))
1151 _cairo_output_stream_printf (pdf_operators
->stream
, "ET\n");
1153 pdf_operators
->in_text_object
= FALSE
;
1155 return _cairo_output_stream_get_status (pdf_operators
->stream
);
1158 /* Compare the scale components of two matrices. The translation
1159 * components are ignored. */
1161 _cairo_matrix_scale_equal (cairo_matrix_t
*a
, cairo_matrix_t
*b
)
1163 return (a
->xx
== b
->xx
&&
1169 static cairo_status_t
1170 _cairo_pdf_operators_begin_actualtext (cairo_pdf_operators_t
*pdf_operators
,
1176 cairo_status_t status
;
1179 _cairo_output_stream_printf (pdf_operators
->stream
, "/Span << /ActualText <feff");
1181 status
= _cairo_utf8_to_utf16 (utf8
, utf8_len
, &utf16
, &utf16_len
);
1182 if (unlikely (status
))
1185 for (i
= 0; i
< utf16_len
; i
++) {
1186 _cairo_output_stream_printf (pdf_operators
->stream
,
1187 "%04x", (int) (utf16
[i
]));
1191 _cairo_output_stream_printf (pdf_operators
->stream
, "> >> BDC\n");
1193 return _cairo_output_stream_get_status (pdf_operators
->stream
);
1196 static cairo_status_t
1197 _cairo_pdf_operators_end_actualtext (cairo_pdf_operators_t
*pdf_operators
)
1199 _cairo_output_stream_printf (pdf_operators
->stream
, "EMC\n");
1201 return _cairo_output_stream_get_status (pdf_operators
->stream
);
1204 static cairo_status_t
1205 _cairo_pdf_operators_emit_glyph (cairo_pdf_operators_t
*pdf_operators
,
1206 cairo_glyph_t
*glyph
,
1207 cairo_scaled_font_subsets_glyph_t
*subset_glyph
)
1210 cairo_status_t status
;
1212 if (pdf_operators
->is_new_text_object
||
1213 pdf_operators
->font_id
!= subset_glyph
->font_id
||
1214 pdf_operators
->subset_id
!= subset_glyph
->subset_id
)
1216 status
= _cairo_pdf_operators_flush_glyphs (pdf_operators
);
1217 if (unlikely (status
))
1220 status
= _cairo_pdf_operators_set_font_subset (pdf_operators
, subset_glyph
);
1221 if (unlikely (status
))
1224 pdf_operators
->is_new_text_object
= FALSE
;
1229 cairo_matrix_transform_point (&pdf_operators
->cairo_to_pdftext
, &x
, &y
);
1231 /* The TJ operator for displaying text strings can only set
1232 * the horizontal position of the glyphs. If the y position
1233 * (in text space) changes, use the Td operator to change the
1234 * current position to the next glyph. We also use the Td
1235 * operator to move the current position if the horizontal
1236 * position changes by more than 10 (in text space
1237 * units). This is becauses the horizontal glyph positioning
1238 * in the TJ operator is intended for kerning and there may be
1239 * PDF consumers that do not handle very large position
1240 * adjustments in TJ.
1242 if (fabs(x
- pdf_operators
->cur_x
) > 10 ||
1243 fabs(y
- pdf_operators
->cur_y
) > GLYPH_POSITION_TOLERANCE
)
1245 status
= _cairo_pdf_operators_flush_glyphs (pdf_operators
);
1246 if (unlikely (status
))
1251 cairo_matrix_transform_point (&pdf_operators
->cairo_to_pdf
, &x
, &y
);
1252 status
= _cairo_pdf_operators_set_text_position (pdf_operators
, x
, y
);
1253 if (unlikely (status
))
1260 status
= _cairo_pdf_operators_add_glyph (pdf_operators
,
1266 /* A utf8_len of -1 indicates no unicode text. A utf8_len = 0 is an
1269 static cairo_int_status_t
1270 _cairo_pdf_operators_emit_cluster (cairo_pdf_operators_t
*pdf_operators
,
1273 cairo_glyph_t
*glyphs
,
1275 cairo_text_cluster_flags_t cluster_flags
,
1276 cairo_scaled_font_t
*scaled_font
)
1278 cairo_scaled_font_subsets_glyph_t subset_glyph
;
1279 cairo_glyph_t
*cur_glyph
;
1280 cairo_status_t status
;
1283 /* If the cluster maps 1 glyph to 1 or more unicode characters, we
1284 * first try _map_glyph() with the unicode string to see if it can
1285 * use toUnicode to map our glyph to the unicode. This will fail
1286 * if the glyph is already mapped to a different unicode string.
1288 * We also go through this path if no unicode mapping was
1289 * supplied (utf8_len < 0).
1291 * Mapping a glyph to a zero length unicode string requires the
1292 * use of ActualText.
1294 if (num_glyphs
== 1 && utf8_len
!= 0) {
1295 status
= _cairo_scaled_font_subsets_map_glyph (pdf_operators
->font_subsets
,
1301 if (unlikely (status
))
1304 if (subset_glyph
.utf8_is_mapped
|| utf8_len
< 0) {
1305 status
= _cairo_pdf_operators_emit_glyph (pdf_operators
,
1308 if (unlikely (status
))
1311 return CAIRO_STATUS_SUCCESS
;
1315 /* Fallback to using ActualText to map zero or more glyphs to a
1316 * unicode string. */
1317 status
= _cairo_pdf_operators_flush_glyphs (pdf_operators
);
1318 if (unlikely (status
))
1321 status
= _cairo_pdf_operators_begin_actualtext (pdf_operators
, utf8
, utf8_len
);
1322 if (unlikely (status
))
1327 * If no glyphs, we should put *something* here for the text to be selectable. */
1328 for (i
= 0; i
< num_glyphs
; i
++) {
1329 status
= _cairo_scaled_font_subsets_map_glyph (pdf_operators
->font_subsets
,
1334 if (unlikely (status
))
1337 status
= _cairo_pdf_operators_emit_glyph (pdf_operators
,
1340 if (unlikely (status
))
1343 if ((cluster_flags
& CAIRO_TEXT_CLUSTER_FLAG_BACKWARD
))
1348 status
= _cairo_pdf_operators_flush_glyphs (pdf_operators
);
1349 if (unlikely (status
))
1352 status
= _cairo_pdf_operators_end_actualtext (pdf_operators
);
1358 _cairo_pdf_operators_show_text_glyphs (cairo_pdf_operators_t
*pdf_operators
,
1361 cairo_glyph_t
*glyphs
,
1363 const cairo_text_cluster_t
*clusters
,
1365 cairo_text_cluster_flags_t cluster_flags
,
1366 cairo_scaled_font_t
*scaled_font
)
1368 cairo_status_t status
;
1370 cairo_matrix_t text_matrix
, invert_y_axis
;
1372 const char *cur_text
;
1373 cairo_glyph_t
*cur_glyph
;
1375 pdf_operators
->font_matrix_inverse
= scaled_font
->font_matrix
;
1376 status
= cairo_matrix_invert (&pdf_operators
->font_matrix_inverse
);
1377 if (status
== CAIRO_STATUS_INVALID_MATRIX
)
1378 return CAIRO_STATUS_SUCCESS
;
1379 if (unlikely (status
))
1382 pdf_operators
->is_new_text_object
= FALSE
;
1383 if (pdf_operators
->in_text_object
== FALSE
) {
1384 status
= _cairo_pdf_operators_begin_text (pdf_operators
);
1385 if (unlikely (status
))
1388 /* Force Tm and Tf to be emitted when starting a new text
1390 pdf_operators
->is_new_text_object
= TRUE
;
1393 cairo_matrix_init_scale (&invert_y_axis
, 1, -1);
1394 text_matrix
= scaled_font
->scale
;
1396 /* Invert y axis in font space */
1397 cairo_matrix_multiply (&text_matrix
, &text_matrix
, &invert_y_axis
);
1399 /* Invert y axis in device space */
1400 cairo_matrix_multiply (&text_matrix
, &invert_y_axis
, &text_matrix
);
1402 if (pdf_operators
->is_new_text_object
||
1403 ! _cairo_matrix_scale_equal (&pdf_operators
->text_matrix
, &text_matrix
))
1405 status
= _cairo_pdf_operators_flush_glyphs (pdf_operators
);
1406 if (unlikely (status
))
1411 cairo_matrix_transform_point (&pdf_operators
->cairo_to_pdf
, &x
, &y
);
1414 status
= _cairo_pdf_operators_set_text_matrix (pdf_operators
, &text_matrix
);
1415 if (status
== CAIRO_STATUS_INVALID_MATRIX
)
1416 return CAIRO_STATUS_SUCCESS
;
1417 if (unlikely (status
))
1421 if (num_clusters
> 0) {
1423 if ((cluster_flags
& CAIRO_TEXT_CLUSTER_FLAG_BACKWARD
))
1424 cur_glyph
= glyphs
+ num_glyphs
;
1427 for (i
= 0; i
< num_clusters
; i
++) {
1428 if ((cluster_flags
& CAIRO_TEXT_CLUSTER_FLAG_BACKWARD
))
1429 cur_glyph
-= clusters
[i
].num_glyphs
;
1430 status
= _cairo_pdf_operators_emit_cluster (pdf_operators
,
1432 clusters
[i
].num_bytes
,
1434 clusters
[i
].num_glyphs
,
1437 if (unlikely (status
))
1440 cur_text
+= clusters
[i
].num_bytes
;
1441 if (!(cluster_flags
& CAIRO_TEXT_CLUSTER_FLAG_BACKWARD
))
1442 cur_glyph
+= clusters
[i
].num_glyphs
;
1445 for (i
= 0; i
< num_glyphs
; i
++) {
1446 status
= _cairo_pdf_operators_emit_cluster (pdf_operators
,
1448 -1, /* no unicode string available */
1453 if (unlikely (status
))
1458 return _cairo_output_stream_get_status (pdf_operators
->stream
);
1461 #endif /* CAIRO_HAS_PDF_OPERATORS */