beta-0.89.2
[luatex.git] / source / libs / cairo / cairo-src / src / cairo-pdf-operators.c
blobdcee25f0c23957730529a736d5b0c24129518201
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
34 * California.
36 * Contributor(s):
37 * Kristian Høgsberg <krh@redhat.com>
38 * Carl Worth <cworth@cworth.org>
39 * Adrian Johnson <ajohnson@redneon.com>
42 #include "cairoint.h"
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"
52 static cairo_status_t
53 _cairo_pdf_operators_end_text (cairo_pdf_operators_t *pdf_operators);
56 void
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,
61 cairo_bool_t ps)
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;
75 cairo_status_t
76 _cairo_pdf_operators_fini (cairo_pdf_operators_t *pdf_operators)
78 return _cairo_pdf_operators_flush (pdf_operators);
81 void
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,
84 void *closure)
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
92 * this function.
94 void
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;
102 void
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;
110 cairo_private void
111 _cairo_pdf_operators_enable_actual_text (cairo_pdf_operators_t *pdf_operators,
112 cairo_bool_t enable)
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).
128 cairo_status_t
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);
136 return status;
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
143 * operatations.
145 * This should be called when starting a new stream or after emitting
146 * the 'Q' operator (where pdf-operators functions were called inside
147 * the q/Q pair).
149 void
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,
171 WRAP_STATE_WORD,
172 WRAP_STATE_STRING,
173 WRAP_STATE_HEXSTRING
174 } cairo_word_wrap_state_t;
177 typedef struct _word_wrap_stream {
178 cairo_output_stream_t base;
179 cairo_output_stream_t *output;
180 int max_column;
181 cairo_bool_t ps_output;
182 int column;
183 cairo_word_wrap_state_t state;
184 cairo_bool_t in_escape;
185 int escape_digits;
186 } word_wrap_stream_t;
190 /* Emit word bytes up to the next delimiter character */
191 static int
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;
196 int count = 0;
198 while (length--) {
199 if (_cairo_isspace (*s) || *s == '<' || *s == '(') {
200 stream->state = WRAP_STATE_DELIMITER;
201 break;
204 count++;
205 stream->column++;
206 s++;
209 if (count)
210 _cairo_output_stream_write (stream->output, data, count);
212 return count;
216 /* Emit hexstring bytes up to either the end of the ASCII hexstring or the number
217 * of columns remaining.
219 static int
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;
224 int count = 0;
225 cairo_bool_t newline = FALSE;
227 while (length--) {
228 count++;
229 stream->column++;
230 if (*s == '>') {
231 stream->state = WRAP_STATE_DELIMITER;
232 break;
235 if (stream->column > stream->max_column) {
236 newline = TRUE;
237 break;
239 s++;
242 if (count)
243 _cairo_output_stream_write (stream->output, data, count);
245 if (newline) {
246 _cairo_output_stream_printf (stream->output, "\n");
247 stream->column = 0;
250 return count;
253 /* Count up to either the end of the string or the number of columns
254 * remaining.
256 static int
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;
261 int count = 0;
262 cairo_bool_t newline = FALSE;
264 while (length--) {
265 count++;
266 stream->column++;
267 if (!stream->in_escape) {
268 if (*s == ')') {
269 stream->state = WRAP_STATE_DELIMITER;
270 break;
272 if (*s == '\\') {
273 stream->in_escape = TRUE;
274 stream->escape_digits = 0;
275 } else if (stream->ps_output && stream->column > stream->max_column) {
276 newline = TRUE;
277 break;
279 } else {
280 if (!_cairo_isdigit(*s) || ++stream->escape_digits == 3)
281 stream->in_escape = FALSE;
283 s++;
286 if (count)
287 _cairo_output_stream_write (stream->output, data, count);
289 if (newline) {
290 _cairo_output_stream_printf (stream->output, "\\\n");
291 stream->column = 0;
294 return count;
297 static cairo_status_t
298 _word_wrap_stream_write (cairo_output_stream_t *base,
299 const unsigned char *data,
300 unsigned int length)
302 word_wrap_stream_t *stream = (word_wrap_stream_t *) base;
303 int count;
305 while (length) {
306 switch (stream->state) {
307 case WRAP_STATE_WORD:
308 count = _word_wrap_stream_count_word_up_to (stream, data, length);
309 break;
310 case WRAP_STATE_HEXSTRING:
311 count = _word_wrap_stream_count_hexstring_up_to (stream, data, length);
312 break;
313 case WRAP_STATE_STRING:
314 count = _word_wrap_stream_count_string_up_to (stream, data, length);
315 break;
316 case WRAP_STATE_DELIMITER:
317 count = 1;
318 stream->column++;
319 if (*data == '\n' || stream->column >= stream->max_column) {
320 _cairo_output_stream_printf (stream->output, "\n");
321 stream->column = 0;
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;
329 if (*data != '\n')
330 _cairo_output_stream_write (stream->output, data, 1);
331 break;
333 default:
334 ASSERT_NOT_REACHED;
335 count = length;
336 break;
338 data += count;
339 length -= count;
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;
358 if (output->status)
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,
369 NULL,
370 _word_wrap_stream_close);
371 stream->output = output;
372 stream->max_column = max_column;
373 stream->ps_output = ps;
374 stream->column = 0;
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;
388 } pdf_path_info_t;
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,
402 "%g %g m ", x, y);
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,
426 "%g %g l ", x, y);
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,
467 "h\n");
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,
483 "%g %g %g %g re ",
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;
507 cairo_box_t box;
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);
521 } else {
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,
527 &info);
530 status2 = _cairo_output_stream_destroy (word_wrap);
531 if (status == CAIRO_STATUS_SUCCESS)
532 status = status2;
534 return status;
537 cairo_int_status_t
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))
548 return status;
551 if (! path->has_current_point) {
552 /* construct an empty path */
553 _cairo_output_stream_printf (pdf_operators->stream, "0 0 m ");
554 } else {
555 status = _cairo_pdf_operators_emit_path (pdf_operators,
556 path,
557 &pdf_operators->cairo_to_pdf,
558 CAIRO_LINE_CAP_ROUND);
559 if (unlikely (status))
560 return status;
563 switch (fill_rule) {
564 default:
565 ASSERT_NOT_REACHED;
566 case CAIRO_FILL_RULE_WINDING:
567 pdf_operator = "W";
568 break;
569 case CAIRO_FILL_RULE_EVEN_ODD:
570 pdf_operator = "W*";
571 break;
574 _cairo_output_stream_printf (pdf_operators->stream,
575 "%s n\n",
576 pdf_operator);
578 return _cairo_output_stream_get_status (pdf_operators->stream);
581 static int
582 _cairo_pdf_line_cap (cairo_line_cap_t cap)
584 switch (cap) {
585 case CAIRO_LINE_CAP_BUTT:
586 return 0;
587 case CAIRO_LINE_CAP_ROUND:
588 return 1;
589 case CAIRO_LINE_CAP_SQUARE:
590 return 2;
591 default:
592 ASSERT_NOT_REACHED;
593 return 0;
597 static int
598 _cairo_pdf_line_join (cairo_line_join_t join)
600 switch (join) {
601 case CAIRO_LINE_JOIN_MITER:
602 return 0;
603 case CAIRO_LINE_JOIN_ROUND:
604 return 1;
605 case CAIRO_LINE_JOIN_BEVEL:
606 return 2;
607 default:
608 ASSERT_NOT_REACHED;
609 return 0;
613 cairo_int_status_t
614 _cairo_pdf_operators_emit_stroke_style (cairo_pdf_operators_t *pdf_operators,
615 const cairo_stroke_style_t *style,
616 double scale)
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) {
631 int i;
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));
646 num_dashes *= 2;
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.
667 if (i == 0) {
668 double last_two[2];
670 if (num_dashes == 2) {
671 free (dash);
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];
682 i = 2;
684 dash[i-1] += dash[i+1];
685 num_dashes -= 2;
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. */
690 if (i == 2)
691 i = -2;
696 if (!pdf_operators->has_line_style || pdf_operators->line_width != line_width) {
697 _cairo_output_stream_printf (pdf_operators->stream,
698 "%f w\n",
699 line_width);
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,
705 "%d J\n",
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,
712 "%d j\n",
713 _cairo_pdf_line_join (style->line_join));
714 pdf_operators->line_join = style->line_join;
717 if (num_dashes) {
718 int d;
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)
731 free (dash);
733 if (!pdf_operators->has_line_style || pdf_operators->miter_limit != style->miter_limit) {
734 _cairo_output_stream_printf (pdf_operators->stream,
735 "%f M ",
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
753 static void
754 _cairo_matrix_factor_out_scale (cairo_matrix_t *m, double *scale)
756 double s;
758 s = fabs (m->xx);
759 if (fabs (m->xy) > s)
760 s = fabs (m->xy);
761 if (fabs (m->yx) > s)
762 s = fabs (m->yx);
763 if (fabs (m->yy) > s)
764 s = fabs (m->yy);
765 *scale = s;
766 s = 1.0/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;
781 double scale = 1.0;
783 if (pdf_operators->in_text_object) {
784 status = _cairo_pdf_operators_end_text (pdf_operators);
785 if (unlikely (status))
786 return 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)
796 has_ctm = FALSE;
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.
814 if (has_ctm) {
815 m = *ctm;
816 /* Zero out the translation since it does not affect the pen
817 * shape however it may cause unnecessary digits to be emitted.
819 m.x0 = 0.0;
820 m.y0 = 0.0;
821 _cairo_matrix_factor_out_scale (&m, &scale);
822 path_transform = m;
823 status = cairo_matrix_invert (&path_transform);
824 if (unlikely (status))
825 return 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))
834 return status;
836 if (has_ctm) {
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");
840 } else {
841 path_transform = pdf_operators->cairo_to_pdf;
844 status = _cairo_pdf_operators_emit_path (pdf_operators,
845 path,
846 &path_transform,
847 style->line_cap);
848 if (unlikely (status))
849 return status;
851 _cairo_output_stream_printf (pdf_operators->stream, "%s", pdf_operator);
852 if (has_ctm)
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);
860 cairo_int_status_t
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,
868 path,
869 style,
870 ctm,
871 ctm_inverse,
872 "S");
875 cairo_int_status_t
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))
886 return status;
889 status = _cairo_pdf_operators_emit_path (pdf_operators,
890 path,
891 &pdf_operators->cairo_to_pdf,
892 CAIRO_LINE_CAP_ROUND);
893 if (unlikely (status))
894 return status;
896 switch (fill_rule) {
897 default:
898 ASSERT_NOT_REACHED;
899 case CAIRO_FILL_RULE_WINDING:
900 pdf_operator = "f";
901 break;
902 case CAIRO_FILL_RULE_EVEN_ODD:
903 pdf_operator = "f*";
904 break;
907 _cairo_output_stream_printf (pdf_operators->stream,
908 "%s\n",
909 pdf_operator);
911 return _cairo_output_stream_get_status (pdf_operators->stream);
914 cairo_int_status_t
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;
924 switch (fill_rule) {
925 default:
926 ASSERT_NOT_REACHED;
927 case CAIRO_FILL_RULE_WINDING:
928 operator = "B";
929 break;
930 case CAIRO_FILL_RULE_EVEN_ODD:
931 operator = "B*";
932 break;
935 return _cairo_pdf_operators_emit_stroke (pdf_operators,
936 path,
937 style,
938 ctm,
939 ctm_inverse,
940 operator);
943 static void
944 _cairo_pdf_operators_emit_glyph_index (cairo_pdf_operators_t *pdf_operators,
945 cairo_output_stream_t *stream,
946 unsigned int glyph)
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);
953 else
954 _cairo_output_stream_printf (stream, "\\%03o", glyph);
955 } else {
956 _cairo_output_stream_printf (stream,
957 "%0*x",
958 pdf_operators->hex_width,
959 glyph);
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)
971 int i;
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,
976 stream,
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)
998 int i;
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;
1005 int rounded_delta;
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)
1017 rounded_delta = 0;
1018 if (rounded_delta != 0) {
1019 if (pdf_operators->is_latin) {
1020 _cairo_output_stream_printf (stream,
1021 ")%d(",
1022 rounded_delta);
1023 } else {
1024 _cairo_output_stream_printf (stream,
1025 ">%d<",
1026 rounded_delta);
1030 /* Convert the rounded delta back to text
1031 * space before adding to the current text
1032 * position. */
1033 delta = rounded_delta/-1000.0;
1034 pdf_operators->cur_x += delta;
1037 _cairo_pdf_operators_emit_glyph_index (pdf_operators,
1038 stream,
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;
1052 int i;
1053 double x;
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)
1067 break;
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,
1072 word_wrap_stream);
1073 } else {
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)
1082 status = status2;
1084 return status;
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,
1090 double x_position)
1092 double x, y;
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. */
1119 inverse = *matrix;
1120 status = cairo_matrix_invert (&inverse);
1121 if (unlikely (status))
1122 return 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,
1148 double x,
1149 double y)
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)
1168 translate.x0 = 0.0;
1169 if (fabs(translate.y0) < TEXT_MATRIX_TOLERANCE)
1170 translate.y0 = 0.0;
1171 _cairo_output_stream_printf (pdf_operators->stream,
1172 "%f %f Td\n",
1173 translate.x0,
1174 translate.y0);
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,
1199 "/f-%d-%d 1 Tf\n",
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))
1207 return 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;
1215 else
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))
1240 return 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. */
1251 static cairo_bool_t
1252 _cairo_matrix_scale_equal (cairo_matrix_t *a, cairo_matrix_t *b)
1254 return (a->xx == b->xx &&
1255 a->xy == b->xy &&
1256 a->yx == b->yx &&
1257 a->yy == b->yy);
1260 static cairo_status_t
1261 _cairo_pdf_operators_begin_actualtext (cairo_pdf_operators_t *pdf_operators,
1262 const char *utf8,
1263 int utf8_len)
1265 uint16_t *utf16;
1266 int utf16_len;
1267 cairo_status_t status;
1268 int i;
1270 _cairo_output_stream_printf (pdf_operators->stream, "/Span << /ActualText <feff");
1271 if (utf8_len) {
1272 status = _cairo_utf8_to_utf16 (utf8, utf8_len, &utf16, &utf16_len);
1273 if (unlikely (status))
1274 return status;
1276 for (i = 0; i < utf16_len; i++) {
1277 _cairo_output_stream_printf (pdf_operators->stream,
1278 "%04x", (int) (utf16[i]));
1280 free (utf16);
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)
1300 double x, y;
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))
1309 return status;
1311 status = _cairo_pdf_operators_set_font_subset (pdf_operators, subset_glyph);
1312 if (unlikely (status))
1313 return status;
1315 pdf_operators->is_new_text_object = FALSE;
1318 x = glyph->x;
1319 y = glyph->y;
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))
1338 return status;
1340 x = glyph->x;
1341 y = glyph->y;
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))
1345 return status;
1347 x = 0.0;
1348 y = 0.0;
1351 status = _cairo_pdf_operators_add_glyph (pdf_operators,
1352 subset_glyph,
1354 return status;
1357 /* A utf8_len of -1 indicates no unicode text. A utf8_len = 0 is an
1358 * empty string.
1360 static cairo_int_status_t
1361 _cairo_pdf_operators_emit_cluster (cairo_pdf_operators_t *pdf_operators,
1362 const char *utf8,
1363 int utf8_len,
1364 cairo_glyph_t *glyphs,
1365 int num_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;
1372 int i;
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,
1387 scaled_font,
1388 glyphs->index,
1389 utf8,
1390 utf8_len,
1391 &subset_glyph);
1392 if (unlikely (status))
1393 return status;
1395 if (subset_glyph.utf8_is_mapped || utf8_len < 0) {
1396 status = _cairo_pdf_operators_emit_glyph (pdf_operators,
1397 glyphs,
1398 &subset_glyph);
1399 if (unlikely (status))
1400 return 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))
1411 return status;
1413 status = _cairo_pdf_operators_begin_actualtext (pdf_operators, utf8, utf8_len);
1414 if (unlikely (status))
1415 return status;
1418 if (cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD)
1419 cur_glyph = glyphs + num_glyphs - 1;
1420 else
1421 cur_glyph = glyphs;
1423 /* XXX
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,
1427 scaled_font,
1428 cur_glyph->index,
1429 NULL, -1,
1430 &subset_glyph);
1431 if (unlikely (status))
1432 return status;
1434 status = _cairo_pdf_operators_emit_glyph (pdf_operators,
1435 cur_glyph,
1436 &subset_glyph);
1437 if (unlikely (status))
1438 return status;
1440 if ((cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD))
1441 cur_glyph--;
1442 else
1443 cur_glyph++;
1446 if (pdf_operators->use_actual_text) {
1447 status = _cairo_pdf_operators_flush_glyphs (pdf_operators);
1448 if (unlikely (status))
1449 return status;
1451 status = _cairo_pdf_operators_end_actualtext (pdf_operators);
1454 return status;
1457 cairo_int_status_t
1458 _cairo_pdf_operators_show_text_glyphs (cairo_pdf_operators_t *pdf_operators,
1459 const char *utf8,
1460 int utf8_len,
1461 cairo_glyph_t *glyphs,
1462 int num_glyphs,
1463 const cairo_text_cluster_t *clusters,
1464 int num_clusters,
1465 cairo_text_cluster_flags_t cluster_flags,
1466 cairo_scaled_font_t *scaled_font)
1468 cairo_status_t status;
1469 int i;
1470 cairo_matrix_t text_matrix, invert_y_axis;
1471 double x, y;
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))
1485 return status;
1487 /* Force Tm and Tf to be emitted when starting a new text
1488 * object.*/
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))
1506 return status;
1508 x = glyphs[0].x;
1509 y = glyphs[0].y;
1510 cairo_matrix_transform_point (&pdf_operators->cairo_to_pdf, &x, &y);
1511 text_matrix.x0 = x;
1512 text_matrix.y0 = 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))
1517 return status;
1520 if (num_clusters > 0) {
1521 cur_text = utf8;
1522 if ((cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD))
1523 cur_glyph = glyphs + num_glyphs;
1524 else
1525 cur_glyph = 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,
1530 cur_text,
1531 clusters[i].num_bytes,
1532 cur_glyph,
1533 clusters[i].num_glyphs,
1534 cluster_flags,
1535 scaled_font);
1536 if (unlikely (status))
1537 return status;
1539 cur_text += clusters[i].num_bytes;
1540 if (!(cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD))
1541 cur_glyph += clusters[i].num_glyphs;
1543 } else {
1544 for (i = 0; i < num_glyphs; i++) {
1545 status = _cairo_pdf_operators_emit_cluster (pdf_operators,
1546 NULL,
1547 -1, /* no unicode string available */
1548 &glyphs[i],
1550 FALSE,
1551 scaled_font);
1552 if (unlikely (status))
1553 return status;
1557 return _cairo_output_stream_get_status (pdf_operators->stream);
1560 #endif /* CAIRO_HAS_PDF_OPERATORS */