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
3  *
4  * Copyright © 2004 Red Hat, Inc
5  * Copyright © 2006 Red Hat, Inc
6  * Copyright © 2007, 2008 Adrian Johnson
7  *
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.
15  *
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
21  *
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/
26  *
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.
30  *
31  * The Original Code is the cairo graphics library.
32  *
33  * The Initial Developer of the Original Code is University of Southern
34  * California.
35  *
36  * Contributor(s):
37  *	Kristian Høgsberg <krh@redhat.com>
38  *	Carl Worth <cworth@cworth.org>
39  *	Adrian Johnson <ajohnson@redneon.com>
40  */
41 
42 #include "cairoint.h"
43 
44 #if CAIRO_HAS_PDF_OPERATORS
45 
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"
51 
52 static cairo_status_t
53 _cairo_pdf_operators_end_text (cairo_pdf_operators_t    *pdf_operators);
54 
55 
56 void
_cairo_pdf_operators_init(cairo_pdf_operators_t * pdf_operators,cairo_output_stream_t * stream,cairo_matrix_t * cairo_to_pdf,cairo_scaled_font_subsets_t * font_subsets,cairo_bool_t ps)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)
62 {
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;
73 }
74 
75 cairo_status_t
_cairo_pdf_operators_fini(cairo_pdf_operators_t * pdf_operators)76 _cairo_pdf_operators_fini (cairo_pdf_operators_t	*pdf_operators)
77 {
78     return _cairo_pdf_operators_flush (pdf_operators);
79 }
80 
81 void
_cairo_pdf_operators_set_font_subsets_callback(cairo_pdf_operators_t * pdf_operators,cairo_pdf_operators_use_font_subset_t use_font_subset,void * closure)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)
85 {
86     pdf_operators->use_font_subset = use_font_subset;
87     pdf_operators->use_font_subset_closure = closure;
88 }
89 
90 /* Change the output stream to a different stream.
91  * _cairo_pdf_operators_flush() should always be called before calling
92  * this function.
93  */
94 void
_cairo_pdf_operators_set_stream(cairo_pdf_operators_t * pdf_operators,cairo_output_stream_t * stream)95 _cairo_pdf_operators_set_stream (cairo_pdf_operators_t	 *pdf_operators,
96 				 cairo_output_stream_t   *stream)
97 {
98     pdf_operators->stream = stream;
99     pdf_operators->has_line_style = FALSE;
100 }
101 
102 void
_cairo_pdf_operators_set_cairo_to_pdf_matrix(cairo_pdf_operators_t * pdf_operators,cairo_matrix_t * cairo_to_pdf)103 _cairo_pdf_operators_set_cairo_to_pdf_matrix (cairo_pdf_operators_t *pdf_operators,
104 					      cairo_matrix_t	    *cairo_to_pdf)
105 {
106     pdf_operators->cairo_to_pdf = *cairo_to_pdf;
107     pdf_operators->has_line_style = FALSE;
108 }
109 
110 cairo_private void
_cairo_pdf_operators_enable_actual_text(cairo_pdf_operators_t * pdf_operators,cairo_bool_t enable)111 _cairo_pdf_operators_enable_actual_text (cairo_pdf_operators_t *pdf_operators,
112 					 cairo_bool_t 	  	enable)
113 {
114     pdf_operators->use_actual_text = enable;
115 }
116 
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.
120  *
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).
126  *
127  */
128 cairo_status_t
_cairo_pdf_operators_flush(cairo_pdf_operators_t * pdf_operators)129 _cairo_pdf_operators_flush (cairo_pdf_operators_t	 *pdf_operators)
130 {
131     cairo_status_t status = CAIRO_STATUS_SUCCESS;
132 
133     if (pdf_operators->in_text_object)
134 	status = _cairo_pdf_operators_end_text (pdf_operators);
135 
136     return status;
137 }
138 
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  * operations.
144  *
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).
148  */
149 void
_cairo_pdf_operators_reset(cairo_pdf_operators_t * pdf_operators)150 _cairo_pdf_operators_reset (cairo_pdf_operators_t *pdf_operators)
151 {
152     pdf_operators->has_line_style = FALSE;
153 }
154 
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.
160  *
161  * The stream is careful to maintain integrity for words that cross
162  * the boundary from one call to write to the next.
163  *
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.
167  */
168 
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;
175 
176 
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;
187 
188 
189 
190 /* Emit word bytes up to the next delimiter character */
191 static int
_word_wrap_stream_count_word_up_to(word_wrap_stream_t * stream,const unsigned char * data,int length)192 _word_wrap_stream_count_word_up_to (word_wrap_stream_t *stream,
193 				   const unsigned char *data, int length)
194 {
195     const unsigned char *s = data;
196     int count = 0;
197 
198     while (length--) {
199 	if (_cairo_isspace (*s) || *s == '<' || *s == '(') {
200 	    stream->state = WRAP_STATE_DELIMITER;
201 	    break;
202 	}
203 
204 	count++;
205 	stream->column++;
206 	s++;
207     }
208 
209     if (count)
210 	_cairo_output_stream_write (stream->output, data, count);
211 
212     return count;
213 }
214 
215 
216 /* Emit hexstring bytes up to either the end of the ASCII hexstring or the number
217  * of columns remaining.
218  */
219 static int
_word_wrap_stream_count_hexstring_up_to(word_wrap_stream_t * stream,const unsigned char * data,int length)220 _word_wrap_stream_count_hexstring_up_to (word_wrap_stream_t *stream,
221 					 const unsigned char *data, int length)
222 {
223     const unsigned char *s = data;
224     int count = 0;
225     cairo_bool_t newline = FALSE;
226 
227     while (length--) {
228 	count++;
229 	stream->column++;
230 	if (*s == '>') {
231 	    stream->state = WRAP_STATE_DELIMITER;
232 	    break;
233 	}
234 
235 	if (stream->column > stream->max_column) {
236 	    newline = TRUE;
237 	    break;
238 	}
239 	s++;
240     }
241 
242     if (count)
243 	_cairo_output_stream_write (stream->output, data, count);
244 
245     if (newline) {
246 	_cairo_output_stream_printf (stream->output, "\n");
247 	stream->column = 0;
248     }
249 
250     return count;
251 }
252 
253 /* Count up to either the end of the string or the number of columns
254  * remaining.
255  */
256 static int
_word_wrap_stream_count_string_up_to(word_wrap_stream_t * stream,const unsigned char * data,int length)257 _word_wrap_stream_count_string_up_to (word_wrap_stream_t *stream,
258 				      const unsigned char *data, int length)
259 {
260     const unsigned char *s = data;
261     int count = 0;
262     cairo_bool_t newline = FALSE;
263 
264     while (length--) {
265 	count++;
266 	stream->column++;
267 	if (!stream->in_escape) {
268 	    if (*s == ')') {
269 		stream->state = WRAP_STATE_DELIMITER;
270 		break;
271 	    }
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;
278 	    }
279 	} else {
280 	    if (!_cairo_isdigit(*s) || ++stream->escape_digits == 3)
281 		stream->in_escape = FALSE;
282 	}
283 	s++;
284     }
285 
286     if (count)
287 	_cairo_output_stream_write (stream->output, data, count);
288 
289     if (newline) {
290 	_cairo_output_stream_printf (stream->output, "\\\n");
291 	stream->column = 0;
292     }
293 
294     return count;
295 }
296 
297 static cairo_status_t
_word_wrap_stream_write(cairo_output_stream_t * base,const unsigned char * data,unsigned int length)298 _word_wrap_stream_write (cairo_output_stream_t  *base,
299 			 const unsigned char	*data,
300 			 unsigned int		 length)
301 {
302     word_wrap_stream_t *stream = (word_wrap_stream_t *) base;
303     int count;
304 
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 	    }
323 	    if (*data == '<') {
324 		stream->state = WRAP_STATE_HEXSTRING;
325 	    } else if (*data == '(') {
326 		stream->state = WRAP_STATE_STRING;
327 	    } else if (!_cairo_isspace (*data)) {
328 		stream->state = WRAP_STATE_WORD;
329 	    }
330 	    if (*data != '\n')
331 		_cairo_output_stream_write (stream->output, data, 1);
332 	    break;
333 
334 	default:
335 	    ASSERT_NOT_REACHED;
336 	    count = length;
337 	    break;
338 	}
339 	data += count;
340 	length -= count;
341     }
342 
343     return _cairo_output_stream_get_status (stream->output);
344 }
345 
346 static cairo_status_t
_word_wrap_stream_close(cairo_output_stream_t * base)347 _word_wrap_stream_close (cairo_output_stream_t *base)
348 {
349     word_wrap_stream_t *stream = (word_wrap_stream_t *) base;
350 
351     return _cairo_output_stream_get_status (stream->output);
352 }
353 
354 static cairo_output_stream_t *
_word_wrap_stream_create(cairo_output_stream_t * output,cairo_bool_t ps,int max_column)355 _word_wrap_stream_create (cairo_output_stream_t *output, cairo_bool_t ps, int max_column)
356 {
357     word_wrap_stream_t *stream;
358 
359     if (output->status)
360 	return _cairo_output_stream_create_in_error (output->status);
361 
362     stream = _cairo_malloc (sizeof (word_wrap_stream_t));
363     if (unlikely (stream == NULL)) {
364 	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
365 	return (cairo_output_stream_t *) &_cairo_output_stream_nil;
366     }
367 
368     _cairo_output_stream_init (&stream->base,
369 			       _word_wrap_stream_write,
370 			       NULL,
371 			       _word_wrap_stream_close);
372     stream->output = output;
373     stream->max_column = max_column;
374     stream->ps_output = ps;
375     stream->column = 0;
376     stream->state = WRAP_STATE_DELIMITER;
377     stream->in_escape = FALSE;
378     stream->escape_digits = 0;
379 
380     return &stream->base;
381 }
382 
383 typedef struct _pdf_path_info {
384     cairo_output_stream_t   *output;
385     cairo_matrix_t	    *path_transform;
386     cairo_line_cap_t         line_cap;
387     cairo_point_t            last_move_to_point;
388     cairo_bool_t             has_sub_path;
389 } pdf_path_info_t;
390 
391 static cairo_status_t
_cairo_pdf_path_move_to(void * closure,const cairo_point_t * point)392 _cairo_pdf_path_move_to (void *closure,
393 			 const cairo_point_t *point)
394 {
395     pdf_path_info_t *info = closure;
396     double x = _cairo_fixed_to_double (point->x);
397     double y = _cairo_fixed_to_double (point->y);
398 
399     info->last_move_to_point = *point;
400     info->has_sub_path = FALSE;
401     cairo_matrix_transform_point (info->path_transform, &x, &y);
402     _cairo_output_stream_printf (info->output,
403 				 "%g %g m ", x, y);
404 
405     return _cairo_output_stream_get_status (info->output);
406 }
407 
408 static cairo_status_t
_cairo_pdf_path_line_to(void * closure,const cairo_point_t * point)409 _cairo_pdf_path_line_to (void *closure,
410 			 const cairo_point_t *point)
411 {
412     pdf_path_info_t *info = closure;
413     double x = _cairo_fixed_to_double (point->x);
414     double y = _cairo_fixed_to_double (point->y);
415 
416     if (info->line_cap != CAIRO_LINE_CAP_ROUND &&
417 	! info->has_sub_path &&
418 	point->x == info->last_move_to_point.x &&
419 	point->y == info->last_move_to_point.y)
420     {
421 	return CAIRO_STATUS_SUCCESS;
422     }
423 
424     info->has_sub_path = TRUE;
425     cairo_matrix_transform_point (info->path_transform, &x, &y);
426     _cairo_output_stream_printf (info->output,
427 				 "%g %g l ", x, y);
428 
429     return _cairo_output_stream_get_status (info->output);
430 }
431 
432 static cairo_status_t
_cairo_pdf_path_curve_to(void * closure,const cairo_point_t * b,const cairo_point_t * c,const cairo_point_t * d)433 _cairo_pdf_path_curve_to (void          *closure,
434 			  const cairo_point_t *b,
435 			  const cairo_point_t *c,
436 			  const cairo_point_t *d)
437 {
438     pdf_path_info_t *info = closure;
439     double bx = _cairo_fixed_to_double (b->x);
440     double by = _cairo_fixed_to_double (b->y);
441     double cx = _cairo_fixed_to_double (c->x);
442     double cy = _cairo_fixed_to_double (c->y);
443     double dx = _cairo_fixed_to_double (d->x);
444     double dy = _cairo_fixed_to_double (d->y);
445 
446     info->has_sub_path = TRUE;
447     cairo_matrix_transform_point (info->path_transform, &bx, &by);
448     cairo_matrix_transform_point (info->path_transform, &cx, &cy);
449     cairo_matrix_transform_point (info->path_transform, &dx, &dy);
450     _cairo_output_stream_printf (info->output,
451 				 "%g %g %g %g %g %g c ",
452 				 bx, by, cx, cy, dx, dy);
453     return _cairo_output_stream_get_status (info->output);
454 }
455 
456 static cairo_status_t
_cairo_pdf_path_close_path(void * closure)457 _cairo_pdf_path_close_path (void *closure)
458 {
459     pdf_path_info_t *info = closure;
460 
461     if (info->line_cap != CAIRO_LINE_CAP_ROUND &&
462 	! info->has_sub_path)
463     {
464 	return CAIRO_STATUS_SUCCESS;
465     }
466 
467     _cairo_output_stream_printf (info->output,
468 				 "h\n");
469 
470     return _cairo_output_stream_get_status (info->output);
471 }
472 
473 static cairo_status_t
_cairo_pdf_path_rectangle(pdf_path_info_t * info,cairo_box_t * box)474 _cairo_pdf_path_rectangle (pdf_path_info_t *info, cairo_box_t *box)
475 {
476     double x1 = _cairo_fixed_to_double (box->p1.x);
477     double y1 = _cairo_fixed_to_double (box->p1.y);
478     double x2 = _cairo_fixed_to_double (box->p2.x);
479     double y2 = _cairo_fixed_to_double (box->p2.y);
480 
481     cairo_matrix_transform_point (info->path_transform, &x1, &y1);
482     cairo_matrix_transform_point (info->path_transform, &x2, &y2);
483     _cairo_output_stream_printf (info->output,
484 				 "%g %g %g %g re ",
485 				 x1, y1, x2 - x1, y2 - y1);
486 
487     return _cairo_output_stream_get_status (info->output);
488 }
489 
490 /* The line cap value is needed to workaround the fact that PostScript
491  * and PDF semantics for stroking degenerate sub-paths do not match
492  * cairo semantics. (PostScript draws something for any line cap
493  * value, while cairo draws something only for round caps).
494  *
495  * When using this function to emit a path to be filled, rather than
496  * stroked, simply pass %CAIRO_LINE_CAP_ROUND which will guarantee that
497  * the stroke workaround will not modify the path being emitted.
498  */
499 static cairo_status_t
_cairo_pdf_operators_emit_path(cairo_pdf_operators_t * pdf_operators,const cairo_path_fixed_t * path,cairo_matrix_t * path_transform,cairo_line_cap_t line_cap)500 _cairo_pdf_operators_emit_path (cairo_pdf_operators_t	*pdf_operators,
501 				const cairo_path_fixed_t*path,
502 				cairo_matrix_t          *path_transform,
503 				cairo_line_cap_t         line_cap)
504 {
505     cairo_output_stream_t *word_wrap;
506     cairo_status_t status, status2;
507     pdf_path_info_t info;
508     cairo_box_t box;
509 
510     word_wrap = _word_wrap_stream_create (pdf_operators->stream, pdf_operators->ps_output, 72);
511     status = _cairo_output_stream_get_status (word_wrap);
512     if (unlikely (status))
513 	return _cairo_output_stream_destroy (word_wrap);
514 
515     info.output = word_wrap;
516     info.path_transform = path_transform;
517     info.line_cap = line_cap;
518     if (_cairo_path_fixed_is_rectangle (path, &box) &&
519 	((path_transform->xx == 0 && path_transform->yy == 0) ||
520 	 (path_transform->xy == 0 && path_transform->yx == 0))) {
521 	status = _cairo_pdf_path_rectangle (&info, &box);
522     } else {
523 	status = _cairo_path_fixed_interpret (path,
524 					      _cairo_pdf_path_move_to,
525 					      _cairo_pdf_path_line_to,
526 					      _cairo_pdf_path_curve_to,
527 					      _cairo_pdf_path_close_path,
528 					      &info);
529     }
530 
531     status2 = _cairo_output_stream_destroy (word_wrap);
532     if (status == CAIRO_STATUS_SUCCESS)
533 	status = status2;
534 
535     return status;
536 }
537 
538 cairo_int_status_t
_cairo_pdf_operators_clip(cairo_pdf_operators_t * pdf_operators,const cairo_path_fixed_t * path,cairo_fill_rule_t fill_rule)539 _cairo_pdf_operators_clip (cairo_pdf_operators_t	*pdf_operators,
540 			   const cairo_path_fixed_t	*path,
541 			   cairo_fill_rule_t		 fill_rule)
542 {
543     const char *pdf_operator;
544     cairo_status_t status;
545 
546     if (pdf_operators->in_text_object) {
547 	status = _cairo_pdf_operators_end_text (pdf_operators);
548 	if (unlikely (status))
549 	    return status;
550     }
551 
552     if (! path->has_current_point) {
553 	/* construct an empty path */
554 	_cairo_output_stream_printf (pdf_operators->stream, "0 0 m ");
555     } else {
556 	status = _cairo_pdf_operators_emit_path (pdf_operators,
557 						 path,
558 						 &pdf_operators->cairo_to_pdf,
559 						 CAIRO_LINE_CAP_ROUND);
560 	if (unlikely (status))
561 	    return status;
562     }
563 
564     switch (fill_rule) {
565     default:
566 	ASSERT_NOT_REACHED;
567     case CAIRO_FILL_RULE_WINDING:
568 	pdf_operator = "W";
569 	break;
570     case CAIRO_FILL_RULE_EVEN_ODD:
571 	pdf_operator = "W*";
572 	break;
573     }
574 
575     _cairo_output_stream_printf (pdf_operators->stream,
576 				 "%s n\n",
577 				 pdf_operator);
578 
579     return _cairo_output_stream_get_status (pdf_operators->stream);
580 }
581 
582 static int
_cairo_pdf_line_cap(cairo_line_cap_t cap)583 _cairo_pdf_line_cap (cairo_line_cap_t cap)
584 {
585     switch (cap) {
586     case CAIRO_LINE_CAP_BUTT:
587 	return 0;
588     case CAIRO_LINE_CAP_ROUND:
589 	return 1;
590     case CAIRO_LINE_CAP_SQUARE:
591 	return 2;
592     default:
593 	ASSERT_NOT_REACHED;
594 	return 0;
595     }
596 }
597 
598 static int
_cairo_pdf_line_join(cairo_line_join_t join)599 _cairo_pdf_line_join (cairo_line_join_t join)
600 {
601     switch (join) {
602     case CAIRO_LINE_JOIN_MITER:
603 	return 0;
604     case CAIRO_LINE_JOIN_ROUND:
605 	return 1;
606     case CAIRO_LINE_JOIN_BEVEL:
607 	return 2;
608     default:
609 	ASSERT_NOT_REACHED;
610 	return 0;
611     }
612 }
613 
614 cairo_int_status_t
_cairo_pdf_operators_emit_stroke_style(cairo_pdf_operators_t * pdf_operators,const cairo_stroke_style_t * style,double scale)615 _cairo_pdf_operators_emit_stroke_style (cairo_pdf_operators_t		*pdf_operators,
616 					const cairo_stroke_style_t	*style,
617 					double				 scale)
618 {
619     double *dash = style->dash;
620     int num_dashes = style->num_dashes;
621     double dash_offset = style->dash_offset;
622     double line_width = style->line_width * scale;
623 
624     /* PostScript has "special needs" when it comes to zero-length
625      * dash segments with butt caps. It apparently (at least
626      * according to ghostscript) draws hairlines for this
627      * case. That's not what the cairo semantics want, so we first
628      * touch up the array to eliminate any 0.0 values that will
629      * result in "on" segments.
630      */
631     if (num_dashes && style->line_cap == CAIRO_LINE_CAP_BUTT) {
632 	int i;
633 
634 	/* If there's an odd number of dash values they will each get
635 	 * interpreted as both on and off. So we first explicitly
636 	 * expand the array to remove the duplicate usage so that we
637 	 * can modify some of the values.
638 	 */
639 	if (num_dashes % 2) {
640 	    dash = _cairo_malloc_abc (num_dashes, 2, sizeof (double));
641 	    if (unlikely (dash == NULL))
642 		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
643 
644 	    memcpy (dash, style->dash, num_dashes * sizeof (double));
645 	    memcpy (dash + num_dashes, style->dash, num_dashes * sizeof (double));
646 
647 	    num_dashes *= 2;
648 	}
649 
650 	for (i = 0; i < num_dashes; i += 2) {
651 	    if (dash[i] == 0.0) {
652 		/* Do not modify the dashes in-place, as we may need to also
653 		 * replay this stroke to an image fallback.
654 		 */
655 		if (dash == style->dash) {
656 		    dash = _cairo_malloc_ab (num_dashes, sizeof (double));
657 		    if (unlikely (dash == NULL))
658 			return _cairo_error (CAIRO_STATUS_NO_MEMORY);
659 		    memcpy (dash, style->dash, num_dashes * sizeof (double));
660 		}
661 
662 		/* If we're at the front of the list, we first rotate
663 		 * two elements from the end of the list to the front
664 		 * of the list before folding away the 0.0. Or, if
665 		 * there are only two dash elements, then there is
666 		 * nothing at all to draw.
667 		 */
668 		if (i == 0) {
669 		    double last_two[2];
670 
671 		    if (num_dashes == 2) {
672 			free (dash);
673 			return CAIRO_INT_STATUS_NOTHING_TO_DO;
674 		    }
675 
676 		    /* The cases of num_dashes == 0, 1, or 3 elements
677 		     * cannot exist, so the rotation of 2 elements
678 		     * will always be safe */
679 		    memcpy (last_two, dash + num_dashes - 2, sizeof (last_two));
680 		    memmove (dash + 2, dash, (num_dashes - 2) * sizeof (double));
681 		    memcpy (dash, last_two, sizeof (last_two));
682 		    dash_offset += dash[0] + dash[1];
683 		    i = 2;
684 		}
685 		dash[i-1] += dash[i+1];
686 		num_dashes -= 2;
687 		memmove (dash + i, dash + i + 2, (num_dashes - i) * sizeof (double));
688 		/* If we might have just rotated, it's possible that
689 		 * we rotated a 0.0 value to the front of the list.
690 		 * Set i to -2 so it will get incremented to 0. */
691 		if (i == 2)
692 		    i = -2;
693 	    }
694 	}
695     }
696 
697     if (!pdf_operators->has_line_style || pdf_operators->line_width != line_width) {
698 	_cairo_output_stream_printf (pdf_operators->stream,
699 				     "%f w\n",
700 				     line_width);
701 	pdf_operators->line_width = line_width;
702     }
703 
704     if (!pdf_operators->has_line_style || pdf_operators->line_cap != style->line_cap) {
705 	_cairo_output_stream_printf (pdf_operators->stream,
706 				     "%d J\n",
707 				     _cairo_pdf_line_cap (style->line_cap));
708 	pdf_operators->line_cap = style->line_cap;
709     }
710 
711     if (!pdf_operators->has_line_style || pdf_operators->line_join != style->line_join) {
712 	_cairo_output_stream_printf (pdf_operators->stream,
713 				     "%d j\n",
714 				     _cairo_pdf_line_join (style->line_join));
715 	pdf_operators->line_join = style->line_join;
716     }
717 
718     if (num_dashes) {
719 	int d;
720 
721 	_cairo_output_stream_printf (pdf_operators->stream, "[");
722 	for (d = 0; d < num_dashes; d++)
723 	    _cairo_output_stream_printf (pdf_operators->stream, " %f", dash[d] * scale);
724 	_cairo_output_stream_printf (pdf_operators->stream, "] %f d\n",
725 				     dash_offset * scale);
726 	pdf_operators->has_dashes = TRUE;
727     } else if (!pdf_operators->has_line_style || pdf_operators->has_dashes) {
728 	_cairo_output_stream_printf (pdf_operators->stream, "[] 0.0 d\n");
729 	pdf_operators->has_dashes = FALSE;
730     }
731     if (dash != style->dash)
732         free (dash);
733 
734     if (!pdf_operators->has_line_style || pdf_operators->miter_limit != style->miter_limit) {
735 	_cairo_output_stream_printf (pdf_operators->stream,
736 				     "%f M ",
737 				     style->miter_limit < 1.0 ? 1.0 : style->miter_limit);
738 	pdf_operators->miter_limit = style->miter_limit;
739     }
740     pdf_operators->has_line_style = TRUE;
741 
742     return _cairo_output_stream_get_status (pdf_operators->stream);
743 }
744 
745 /* Scale the matrix so the largest absolute value of the non
746  * translation components is 1.0. Return the scale required to restore
747  * the matrix to the original values.
748  *
749  * eg the matrix  [ 100  0  0  50   20   10  ]
750  *
751  * is rescaled to [  1   0  0  0.5  0.2  0.1 ]
752  * and the scale returned is 100
753  */
754 static void
_cairo_matrix_factor_out_scale(cairo_matrix_t * m,double * scale)755 _cairo_matrix_factor_out_scale (cairo_matrix_t *m, double *scale)
756 {
757     double s;
758 
759     s = fabs (m->xx);
760     if (fabs (m->xy) > s)
761 	s = fabs (m->xy);
762     if (fabs (m->yx) > s)
763 	s = fabs (m->yx);
764     if (fabs (m->yy) > s)
765 	s = fabs (m->yy);
766     *scale = s;
767     s = 1.0/s;
768     cairo_matrix_scale (m, s, s);
769 }
770 
771 static cairo_int_status_t
_cairo_pdf_operators_emit_stroke(cairo_pdf_operators_t * pdf_operators,const cairo_path_fixed_t * path,const cairo_stroke_style_t * style,const cairo_matrix_t * ctm,const cairo_matrix_t * ctm_inverse,const char * pdf_operator)772 _cairo_pdf_operators_emit_stroke (cairo_pdf_operators_t		*pdf_operators,
773 				  const cairo_path_fixed_t	*path,
774 				  const cairo_stroke_style_t	*style,
775 				  const cairo_matrix_t		*ctm,
776 				  const cairo_matrix_t		*ctm_inverse,
777 				  const char			*pdf_operator)
778 {
779     cairo_int_status_t status;
780     cairo_matrix_t m, path_transform;
781     cairo_bool_t has_ctm = TRUE;
782     double scale = 1.0;
783 
784     if (pdf_operators->in_text_object) {
785 	status = _cairo_pdf_operators_end_text (pdf_operators);
786 	if (unlikely (status))
787 	    return status;
788     }
789 
790     /* Optimize away the stroke ctm when it does not affect the
791      * stroke. There are other ctm cases that could be optimized
792      * however this is the most common.
793      */
794     if (fabs(ctm->xx) == 1.0 && fabs(ctm->yy) == 1.0 &&
795 	fabs(ctm->xy) == 0.0 && fabs(ctm->yx) == 0.0)
796     {
797 	has_ctm = FALSE;
798     }
799 
800     /* The PDF CTM is transformed to the user space CTM when stroking
801      * so the correct pen shape will be used. This also requires that
802      * the path be transformed to user space when emitted. The
803      * conversion of path coordinates to user space may cause rounding
804      * errors. For example the device space point (1.234, 3.142) when
805      * transformed to a user space CTM of [100 0 0 100 0 0] will be
806      * emitted as (0.012, 0.031).
807      *
808      * To avoid the rounding problem we scale the user space CTM
809      * matrix so that all the non translation components of the matrix
810      * are <= 1. The line width and and dashes are scaled by the
811      * inverse of the scale applied to the CTM. This maintains the
812      * shape of the stroke pen while keeping the user space CTM within
813      * the range that maximizes the precision of the emitted path.
814      */
815     if (has_ctm) {
816 	m = *ctm;
817 	/* Zero out the translation since it does not affect the pen
818 	 * shape however it may cause unnecessary digits to be emitted.
819 	 */
820 	m.x0 = 0.0;
821 	m.y0 = 0.0;
822 	_cairo_matrix_factor_out_scale (&m, &scale);
823 	path_transform = m;
824 	status = cairo_matrix_invert (&path_transform);
825 	if (unlikely (status))
826 	    return status;
827 
828 	cairo_matrix_multiply (&m, &m, &pdf_operators->cairo_to_pdf);
829     }
830 
831     status = _cairo_pdf_operators_emit_stroke_style (pdf_operators, style, scale);
832     if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
833 	return CAIRO_STATUS_SUCCESS;
834     if (unlikely (status))
835 	return status;
836 
837     if (has_ctm) {
838 	_cairo_output_stream_printf (pdf_operators->stream, "q ");
839 	_cairo_output_stream_print_matrix (pdf_operators->stream, &m);
840 	_cairo_output_stream_printf (pdf_operators->stream, " cm\n");
841     } else {
842 	path_transform = pdf_operators->cairo_to_pdf;
843     }
844 
845     status = _cairo_pdf_operators_emit_path (pdf_operators,
846 					     path,
847 					     &path_transform,
848 					     style->line_cap);
849     if (unlikely (status))
850 	return status;
851 
852     _cairo_output_stream_printf (pdf_operators->stream, "%s", pdf_operator);
853     if (has_ctm)
854 	_cairo_output_stream_printf (pdf_operators->stream, " Q");
855 
856     _cairo_output_stream_printf (pdf_operators->stream, "\n");
857 
858     return _cairo_output_stream_get_status (pdf_operators->stream);
859 }
860 
861 cairo_int_status_t
_cairo_pdf_operators_stroke(cairo_pdf_operators_t * pdf_operators,const cairo_path_fixed_t * path,const cairo_stroke_style_t * style,const cairo_matrix_t * ctm,const cairo_matrix_t * ctm_inverse)862 _cairo_pdf_operators_stroke (cairo_pdf_operators_t		*pdf_operators,
863 			     const cairo_path_fixed_t		*path,
864 			     const cairo_stroke_style_t		*style,
865 			     const cairo_matrix_t		*ctm,
866 			     const cairo_matrix_t		*ctm_inverse)
867 {
868     return _cairo_pdf_operators_emit_stroke (pdf_operators,
869 					     path,
870 					     style,
871 					     ctm,
872 					     ctm_inverse,
873 					     "S");
874 }
875 
876 cairo_int_status_t
_cairo_pdf_operators_fill(cairo_pdf_operators_t * pdf_operators,const cairo_path_fixed_t * path,cairo_fill_rule_t fill_rule)877 _cairo_pdf_operators_fill (cairo_pdf_operators_t	*pdf_operators,
878 			   const cairo_path_fixed_t	*path,
879 			   cairo_fill_rule_t		fill_rule)
880 {
881     const char *pdf_operator;
882     cairo_status_t status;
883 
884     if (pdf_operators->in_text_object) {
885 	status = _cairo_pdf_operators_end_text (pdf_operators);
886 	if (unlikely (status))
887 	    return status;
888     }
889 
890     status = _cairo_pdf_operators_emit_path (pdf_operators,
891 					     path,
892 					     &pdf_operators->cairo_to_pdf,
893 					     CAIRO_LINE_CAP_ROUND);
894     if (unlikely (status))
895 	return status;
896 
897     switch (fill_rule) {
898     default:
899 	ASSERT_NOT_REACHED;
900     case CAIRO_FILL_RULE_WINDING:
901 	pdf_operator = "f";
902 	break;
903     case CAIRO_FILL_RULE_EVEN_ODD:
904 	pdf_operator = "f*";
905 	break;
906     }
907 
908     _cairo_output_stream_printf (pdf_operators->stream,
909 				 "%s\n",
910 				 pdf_operator);
911 
912     return _cairo_output_stream_get_status (pdf_operators->stream);
913 }
914 
915 cairo_int_status_t
_cairo_pdf_operators_fill_stroke(cairo_pdf_operators_t * pdf_operators,const cairo_path_fixed_t * path,cairo_fill_rule_t fill_rule,const cairo_stroke_style_t * style,const cairo_matrix_t * ctm,const cairo_matrix_t * ctm_inverse)916 _cairo_pdf_operators_fill_stroke (cairo_pdf_operators_t		*pdf_operators,
917 				  const cairo_path_fixed_t	*path,
918 				  cairo_fill_rule_t		 fill_rule,
919 				  const cairo_stroke_style_t	*style,
920 				  const cairo_matrix_t		*ctm,
921 				  const cairo_matrix_t		*ctm_inverse)
922 {
923     const char *operator;
924 
925     switch (fill_rule) {
926     default:
927 	ASSERT_NOT_REACHED;
928     case CAIRO_FILL_RULE_WINDING:
929 	operator = "B";
930 	break;
931     case CAIRO_FILL_RULE_EVEN_ODD:
932 	operator = "B*";
933 	break;
934     }
935 
936     return _cairo_pdf_operators_emit_stroke (pdf_operators,
937 					     path,
938 					     style,
939 					     ctm,
940 					     ctm_inverse,
941 					     operator);
942 }
943 
944 static void
_cairo_pdf_operators_emit_glyph_index(cairo_pdf_operators_t * pdf_operators,cairo_output_stream_t * stream,unsigned int glyph)945 _cairo_pdf_operators_emit_glyph_index (cairo_pdf_operators_t *pdf_operators,
946 				       cairo_output_stream_t *stream,
947 				       unsigned int 	      glyph)
948 {
949     if (pdf_operators->is_latin) {
950 	if (glyph == '(' || glyph == ')' || glyph == '\\')
951 	    _cairo_output_stream_printf (stream, "\\%c", glyph);
952 	else if (glyph >= 0x20 && glyph <= 0x7e)
953 	    _cairo_output_stream_printf (stream, "%c", glyph);
954 	else
955 	    _cairo_output_stream_printf (stream, "\\%03o", glyph);
956     } else {
957 	_cairo_output_stream_printf (stream,
958 				     "%0*x",
959 				     pdf_operators->hex_width,
960 				     glyph);
961     }
962 }
963 
964 #define GLYPH_POSITION_TOLERANCE 0.001
965 
966 /* Emit the string of glyphs using the 'Tj' operator. This requires
967  * that the glyphs are positioned at their natural glyph advances. */
968 static cairo_status_t
_cairo_pdf_operators_emit_glyph_string(cairo_pdf_operators_t * pdf_operators,cairo_output_stream_t * stream)969 _cairo_pdf_operators_emit_glyph_string (cairo_pdf_operators_t   *pdf_operators,
970 					cairo_output_stream_t  	*stream)
971 {
972     int i;
973 
974     _cairo_output_stream_printf (stream, "%s", pdf_operators->is_latin ? "(" : "<");
975     for (i = 0; i < pdf_operators->num_glyphs; i++) {
976 	_cairo_pdf_operators_emit_glyph_index (pdf_operators,
977 					       stream,
978 					       pdf_operators->glyphs[i].glyph_index);
979 	pdf_operators->cur_x += pdf_operators->glyphs[i].x_advance;
980     }
981     _cairo_output_stream_printf (stream, "%sTj\n", pdf_operators->is_latin ? ")" : ">");
982 
983     return _cairo_output_stream_get_status (stream);
984 }
985 
986 /* Emit the string of glyphs using the 'TJ' operator.
987  *
988  * The TJ operator takes an array of strings of glyphs. Each string of
989  * glyphs is displayed using the glyph advances of each glyph to
990  * position the glyphs. A relative adjustment to the glyph advance may
991  * be specified by including the adjustment between two strings. The
992  * adjustment is in units of text space * -1000.
993  */
994 static cairo_status_t
_cairo_pdf_operators_emit_glyph_string_with_positioning(cairo_pdf_operators_t * pdf_operators,cairo_output_stream_t * stream)995 _cairo_pdf_operators_emit_glyph_string_with_positioning (
996     cairo_pdf_operators_t   *pdf_operators,
997     cairo_output_stream_t   *stream)
998 {
999     int i;
1000 
1001     _cairo_output_stream_printf (stream, "[%s", pdf_operators->is_latin ? "(" : "<");
1002     for (i = 0; i < pdf_operators->num_glyphs; i++) {
1003 	if (pdf_operators->glyphs[i].x_position != pdf_operators->cur_x)
1004 	{
1005 	    double delta = pdf_operators->glyphs[i].x_position - pdf_operators->cur_x;
1006 	    int rounded_delta;
1007 
1008 	    delta = -1000.0*delta;
1009 	    /* As the delta is in 1/1000 of a unit of text space,
1010 	     * rounding to an integer should still provide sufficient
1011 	     * precision. We round the delta before adding to Tm_x so
1012 	     * that we keep track of the accumulated rounding error in
1013 	     * the PDF interpreter and compensate for it when
1014 	     * calculating subsequent deltas.
1015 	     */
1016 	    rounded_delta = _cairo_lround (delta);
1017 	    if (abs(rounded_delta) < 3)
1018 		rounded_delta = 0;
1019 	    if (rounded_delta != 0) {
1020 		if (pdf_operators->is_latin) {
1021 		    _cairo_output_stream_printf (stream,
1022 						 ")%d(",
1023 						 rounded_delta);
1024 		} else {
1025 		    _cairo_output_stream_printf (stream,
1026 						 ">%d<",
1027 						 rounded_delta);
1028 		}
1029 	    }
1030 
1031 	    /* Convert the rounded delta back to text
1032 	     * space before adding to the current text
1033 	     * position. */
1034 	    delta = rounded_delta/-1000.0;
1035 	    pdf_operators->cur_x += delta;
1036 	}
1037 
1038 	_cairo_pdf_operators_emit_glyph_index (pdf_operators,
1039 					       stream,
1040 					       pdf_operators->glyphs[i].glyph_index);
1041 	pdf_operators->cur_x += pdf_operators->glyphs[i].x_advance;
1042     }
1043     _cairo_output_stream_printf (stream, "%s]TJ\n", pdf_operators->is_latin ? ")" : ">");
1044 
1045     return _cairo_output_stream_get_status (stream);
1046 }
1047 
1048 static cairo_status_t
_cairo_pdf_operators_flush_glyphs(cairo_pdf_operators_t * pdf_operators)1049 _cairo_pdf_operators_flush_glyphs (cairo_pdf_operators_t    *pdf_operators)
1050 {
1051     cairo_output_stream_t *word_wrap_stream;
1052     cairo_status_t status, status2;
1053     int i;
1054     double x;
1055 
1056     if (pdf_operators->num_glyphs == 0)
1057 	return CAIRO_STATUS_SUCCESS;
1058 
1059     word_wrap_stream = _word_wrap_stream_create (pdf_operators->stream, pdf_operators->ps_output, 72);
1060     status = _cairo_output_stream_get_status (word_wrap_stream);
1061     if (unlikely (status))
1062 	return _cairo_output_stream_destroy (word_wrap_stream);
1063 
1064     /* Check if glyph advance used to position every glyph */
1065     x = pdf_operators->cur_x;
1066     for (i = 0; i < pdf_operators->num_glyphs; i++) {
1067 	if (fabs(pdf_operators->glyphs[i].x_position - x) > GLYPH_POSITION_TOLERANCE)
1068 	    break;
1069 	x += pdf_operators->glyphs[i].x_advance;
1070     }
1071     if (i == pdf_operators->num_glyphs) {
1072 	status = _cairo_pdf_operators_emit_glyph_string (pdf_operators,
1073 							 word_wrap_stream);
1074     } else {
1075 	status = _cairo_pdf_operators_emit_glyph_string_with_positioning (
1076 	    pdf_operators, word_wrap_stream);
1077     }
1078 
1079     pdf_operators->num_glyphs = 0;
1080     pdf_operators->glyph_buf_x_pos = pdf_operators->cur_x;
1081     status2 = _cairo_output_stream_destroy (word_wrap_stream);
1082     if (status == CAIRO_STATUS_SUCCESS)
1083 	status = status2;
1084 
1085     return status;
1086 }
1087 
1088 static cairo_status_t
_cairo_pdf_operators_add_glyph(cairo_pdf_operators_t * pdf_operators,cairo_scaled_font_subsets_glyph_t * glyph,double x_position)1089 _cairo_pdf_operators_add_glyph (cairo_pdf_operators_t             *pdf_operators,
1090 				cairo_scaled_font_subsets_glyph_t *glyph,
1091 				double 			           x_position)
1092 {
1093     double x, y;
1094 
1095     x = glyph->x_advance;
1096     y = glyph->y_advance;
1097     if (glyph->is_scaled)
1098 	cairo_matrix_transform_distance (&pdf_operators->font_matrix_inverse, &x, &y);
1099 
1100     pdf_operators->glyphs[pdf_operators->num_glyphs].x_position = x_position;
1101     pdf_operators->glyphs[pdf_operators->num_glyphs].glyph_index = glyph->subset_glyph_index;
1102     pdf_operators->glyphs[pdf_operators->num_glyphs].x_advance = x;
1103     pdf_operators->glyph_buf_x_pos += x;
1104     pdf_operators->num_glyphs++;
1105     if (pdf_operators->num_glyphs == PDF_GLYPH_BUFFER_SIZE)
1106 	return _cairo_pdf_operators_flush_glyphs (pdf_operators);
1107 
1108     return CAIRO_STATUS_SUCCESS;
1109 }
1110 
1111 /* Use 'Tm' operator to set the PDF text matrix. */
1112 static cairo_status_t
_cairo_pdf_operators_set_text_matrix(cairo_pdf_operators_t * pdf_operators,cairo_matrix_t * matrix)1113 _cairo_pdf_operators_set_text_matrix (cairo_pdf_operators_t  *pdf_operators,
1114 				      cairo_matrix_t         *matrix)
1115 {
1116     cairo_matrix_t inverse;
1117     cairo_status_t status;
1118 
1119     /* We require the matrix to be invertable. */
1120     inverse = *matrix;
1121     status = cairo_matrix_invert (&inverse);
1122     if (unlikely (status))
1123 	return status;
1124 
1125     pdf_operators->text_matrix = *matrix;
1126     pdf_operators->cur_x = 0;
1127     pdf_operators->cur_y = 0;
1128     pdf_operators->glyph_buf_x_pos = 0;
1129     _cairo_output_stream_print_matrix (pdf_operators->stream, &pdf_operators->text_matrix);
1130     _cairo_output_stream_printf (pdf_operators->stream, " Tm\n");
1131 
1132     pdf_operators->cairo_to_pdftext = *matrix;
1133     status = cairo_matrix_invert (&pdf_operators->cairo_to_pdftext);
1134     assert (status == CAIRO_STATUS_SUCCESS);
1135     cairo_matrix_multiply (&pdf_operators->cairo_to_pdftext,
1136 			   &pdf_operators->cairo_to_pdf,
1137 			   &pdf_operators->cairo_to_pdftext);
1138 
1139     return _cairo_output_stream_get_status (pdf_operators->stream);
1140 }
1141 
1142 #define TEXT_MATRIX_TOLERANCE 1e-6
1143 
1144 /* Set the translation components of the PDF text matrix to x, y. The
1145  * 'Td' operator is used to transform the text matrix.
1146  */
1147 static cairo_status_t
_cairo_pdf_operators_set_text_position(cairo_pdf_operators_t * pdf_operators,double x,double y)1148 _cairo_pdf_operators_set_text_position (cairo_pdf_operators_t  *pdf_operators,
1149 					double 			x,
1150 					double 			y)
1151 {
1152     cairo_matrix_t translate, inverse;
1153     cairo_status_t status;
1154 
1155     /* The Td operator transforms the text_matrix with:
1156      *
1157      *   text_matrix' = T x text_matrix
1158      *
1159      * where T is a translation matrix with the translation components
1160      * set to the Td operands tx and ty.
1161      */
1162     inverse = pdf_operators->text_matrix;
1163     status = cairo_matrix_invert (&inverse);
1164     assert (status == CAIRO_STATUS_SUCCESS);
1165     pdf_operators->text_matrix.x0 = x;
1166     pdf_operators->text_matrix.y0 = y;
1167     cairo_matrix_multiply (&translate, &pdf_operators->text_matrix, &inverse);
1168     if (fabs(translate.x0) < TEXT_MATRIX_TOLERANCE)
1169 	translate.x0 = 0.0;
1170     if (fabs(translate.y0) < TEXT_MATRIX_TOLERANCE)
1171 	translate.y0 = 0.0;
1172     _cairo_output_stream_printf (pdf_operators->stream,
1173 				 "%f %f Td\n",
1174 				 translate.x0,
1175 				 translate.y0);
1176     pdf_operators->cur_x = 0;
1177     pdf_operators->cur_y = 0;
1178     pdf_operators->glyph_buf_x_pos = 0;
1179 
1180     pdf_operators->cairo_to_pdftext = pdf_operators->text_matrix;
1181     status = cairo_matrix_invert (&pdf_operators->cairo_to_pdftext);
1182     assert (status == CAIRO_STATUS_SUCCESS);
1183     cairo_matrix_multiply (&pdf_operators->cairo_to_pdftext,
1184 			   &pdf_operators->cairo_to_pdf,
1185 			   &pdf_operators->cairo_to_pdftext);
1186 
1187     return _cairo_output_stream_get_status (pdf_operators->stream);
1188 }
1189 
1190 /* Select the font using the 'Tf' operator. The font size is set to 1
1191  * as we use the 'Tm' operator to set the font scale.
1192  */
1193 static cairo_status_t
_cairo_pdf_operators_set_font_subset(cairo_pdf_operators_t * pdf_operators,cairo_scaled_font_subsets_glyph_t * subset_glyph)1194 _cairo_pdf_operators_set_font_subset (cairo_pdf_operators_t             *pdf_operators,
1195 				      cairo_scaled_font_subsets_glyph_t *subset_glyph)
1196 {
1197     cairo_status_t status;
1198 
1199     _cairo_output_stream_printf (pdf_operators->stream,
1200 				 "/f-%d-%d 1 Tf\n",
1201 				 subset_glyph->font_id,
1202 				 subset_glyph->subset_id);
1203     if (pdf_operators->use_font_subset) {
1204 	status = pdf_operators->use_font_subset (subset_glyph->font_id,
1205 						 subset_glyph->subset_id,
1206 						 pdf_operators->use_font_subset_closure);
1207 	if (unlikely (status))
1208 	    return status;
1209     }
1210     pdf_operators->font_id = subset_glyph->font_id;
1211     pdf_operators->subset_id = subset_glyph->subset_id;
1212     pdf_operators->is_latin = subset_glyph->is_latin;
1213 
1214     if (subset_glyph->is_composite)
1215 	pdf_operators->hex_width = 4;
1216     else
1217 	pdf_operators->hex_width = 2;
1218 
1219     return CAIRO_STATUS_SUCCESS;
1220 }
1221 
1222 static cairo_status_t
_cairo_pdf_operators_begin_text(cairo_pdf_operators_t * pdf_operators)1223 _cairo_pdf_operators_begin_text (cairo_pdf_operators_t    *pdf_operators)
1224 {
1225     _cairo_output_stream_printf (pdf_operators->stream, "BT\n");
1226 
1227     pdf_operators->in_text_object = TRUE;
1228     pdf_operators->num_glyphs = 0;
1229     pdf_operators->glyph_buf_x_pos = 0;
1230 
1231     return _cairo_output_stream_get_status (pdf_operators->stream);
1232 }
1233 
1234 static cairo_status_t
_cairo_pdf_operators_end_text(cairo_pdf_operators_t * pdf_operators)1235 _cairo_pdf_operators_end_text (cairo_pdf_operators_t    *pdf_operators)
1236 {
1237     cairo_status_t status;
1238 
1239     status = _cairo_pdf_operators_flush_glyphs (pdf_operators);
1240     if (unlikely (status))
1241 	return status;
1242 
1243     _cairo_output_stream_printf (pdf_operators->stream, "ET\n");
1244 
1245     pdf_operators->in_text_object = FALSE;
1246 
1247     return _cairo_output_stream_get_status (pdf_operators->stream);
1248 }
1249 
1250 /* Compare the scale components of two matrices. The translation
1251  * components are ignored. */
1252 static cairo_bool_t
_cairo_matrix_scale_equal(cairo_matrix_t * a,cairo_matrix_t * b)1253 _cairo_matrix_scale_equal (cairo_matrix_t *a, cairo_matrix_t *b)
1254 {
1255     return (a->xx == b->xx &&
1256 	    a->xy == b->xy &&
1257 	    a->yx == b->yx &&
1258 	    a->yy == b->yy);
1259 }
1260 
1261 static cairo_status_t
_cairo_pdf_operators_begin_actualtext(cairo_pdf_operators_t * pdf_operators,const char * utf8,int utf8_len)1262 _cairo_pdf_operators_begin_actualtext (cairo_pdf_operators_t *pdf_operators,
1263 				       const char 	     *utf8,
1264 				       int		      utf8_len)
1265 {
1266     uint16_t *utf16;
1267     int utf16_len;
1268     cairo_status_t status;
1269     int i;
1270 
1271     _cairo_output_stream_printf (pdf_operators->stream, "/Span << /ActualText <feff");
1272     if (utf8_len) {
1273 	status = _cairo_utf8_to_utf16 (utf8, utf8_len, &utf16, &utf16_len);
1274 	if (unlikely (status))
1275 	    return status;
1276 
1277 	for (i = 0; i < utf16_len; i++) {
1278 	    _cairo_output_stream_printf (pdf_operators->stream,
1279 					 "%04x", (int) (utf16[i]));
1280 	}
1281 	free (utf16);
1282     }
1283     _cairo_output_stream_printf (pdf_operators->stream, "> >> BDC\n");
1284 
1285     return _cairo_output_stream_get_status (pdf_operators->stream);
1286 }
1287 
1288 static cairo_status_t
_cairo_pdf_operators_end_actualtext(cairo_pdf_operators_t * pdf_operators)1289 _cairo_pdf_operators_end_actualtext (cairo_pdf_operators_t    *pdf_operators)
1290 {
1291     _cairo_output_stream_printf (pdf_operators->stream, "EMC\n");
1292 
1293     return _cairo_output_stream_get_status (pdf_operators->stream);
1294 }
1295 
1296 static cairo_status_t
_cairo_pdf_operators_emit_glyph(cairo_pdf_operators_t * pdf_operators,cairo_glyph_t * glyph,cairo_scaled_font_subsets_glyph_t * subset_glyph)1297 _cairo_pdf_operators_emit_glyph (cairo_pdf_operators_t             *pdf_operators,
1298 				 cairo_glyph_t              	   *glyph,
1299 				 cairo_scaled_font_subsets_glyph_t *subset_glyph)
1300 {
1301     double x, y;
1302     cairo_status_t status;
1303 
1304     if (pdf_operators->is_new_text_object ||
1305 	pdf_operators->font_id != subset_glyph->font_id ||
1306 	pdf_operators->subset_id != subset_glyph->subset_id)
1307     {
1308 	status = _cairo_pdf_operators_flush_glyphs (pdf_operators);
1309 	if (unlikely (status))
1310 	    return status;
1311 
1312 	status = _cairo_pdf_operators_set_font_subset (pdf_operators, subset_glyph);
1313 	if (unlikely (status))
1314 	    return status;
1315 
1316 	pdf_operators->is_new_text_object = FALSE;
1317     }
1318 
1319     x = glyph->x;
1320     y = glyph->y;
1321     cairo_matrix_transform_point (&pdf_operators->cairo_to_pdftext, &x, &y);
1322 
1323     /* The TJ operator for displaying text strings can only set
1324      * the horizontal position of the glyphs. If the y position
1325      * (in text space) changes, use the Td operator to change the
1326      * current position to the next glyph. We also use the Td
1327      * operator to move the current position if the horizontal
1328      * position changes by more than 10 (in text space
1329      * units). This is because the horizontal glyph positioning
1330      * in the TJ operator is intended for kerning and there may be
1331      * PDF consumers that do not handle very large position
1332      * adjustments in TJ.
1333      */
1334     if (fabs(x - pdf_operators->glyph_buf_x_pos) > 10 ||
1335 	fabs(y - pdf_operators->cur_y) > GLYPH_POSITION_TOLERANCE)
1336     {
1337 	status = _cairo_pdf_operators_flush_glyphs (pdf_operators);
1338 	if (unlikely (status))
1339 	    return status;
1340 
1341 	x = glyph->x;
1342 	y = glyph->y;
1343 	cairo_matrix_transform_point (&pdf_operators->cairo_to_pdf, &x, &y);
1344 	status = _cairo_pdf_operators_set_text_position (pdf_operators, x, y);
1345 	if (unlikely (status))
1346 	    return status;
1347 
1348 	x = 0.0;
1349 	y = 0.0;
1350     }
1351 
1352     status = _cairo_pdf_operators_add_glyph (pdf_operators,
1353 					     subset_glyph,
1354 					     x);
1355     return status;
1356 }
1357 
1358 /* A utf8_len of -1 indicates no unicode text. A utf8_len = 0 is an
1359  * empty string.
1360  */
1361 static cairo_int_status_t
_cairo_pdf_operators_emit_cluster(cairo_pdf_operators_t * pdf_operators,const char * utf8,int utf8_len,cairo_glyph_t * glyphs,int num_glyphs,cairo_text_cluster_flags_t cluster_flags,cairo_scaled_font_t * scaled_font)1362 _cairo_pdf_operators_emit_cluster (cairo_pdf_operators_t      *pdf_operators,
1363 				   const char                 *utf8,
1364 				   int                         utf8_len,
1365 				   cairo_glyph_t              *glyphs,
1366 				   int                         num_glyphs,
1367 				   cairo_text_cluster_flags_t  cluster_flags,
1368 				   cairo_scaled_font_t	      *scaled_font)
1369 {
1370     cairo_scaled_font_subsets_glyph_t subset_glyph;
1371     cairo_glyph_t *cur_glyph;
1372     cairo_status_t status = CAIRO_STATUS_SUCCESS;
1373     int i;
1374 
1375     /* If the cluster maps 1 glyph to 1 or more unicode characters, we
1376      * first try _map_glyph() with the unicode string to see if it can
1377      * use toUnicode to map our glyph to the unicode. This will fail
1378      * if the glyph is already mapped to a different unicode string.
1379      *
1380      * We also go through this path if no unicode mapping was
1381      * supplied (utf8_len < 0).
1382      *
1383      * Mapping a glyph to a zero length unicode string requires the
1384      * use of ActualText.
1385      */
1386     if (num_glyphs == 1 && utf8_len != 0) {
1387 	status = _cairo_scaled_font_subsets_map_glyph (pdf_operators->font_subsets,
1388 						       scaled_font,
1389 						       glyphs->index,
1390 						       utf8,
1391 						       utf8_len,
1392 						       &subset_glyph);
1393 	if (unlikely (status))
1394 	    return status;
1395 
1396 	if (subset_glyph.utf8_is_mapped || utf8_len < 0) {
1397 	    status = _cairo_pdf_operators_emit_glyph (pdf_operators,
1398 						      glyphs,
1399 						      &subset_glyph);
1400 	    if (unlikely (status))
1401 		return status;
1402 
1403 	    return CAIRO_STATUS_SUCCESS;
1404 	}
1405     }
1406 
1407     if (pdf_operators->use_actual_text) {
1408 	/* Fallback to using ActualText to map zero or more glyphs to a
1409 	 * unicode string. */
1410 	status = _cairo_pdf_operators_flush_glyphs (pdf_operators);
1411 	if (unlikely (status))
1412 	    return status;
1413 
1414 	status = _cairo_pdf_operators_begin_actualtext (pdf_operators, utf8, utf8_len);
1415 	if (unlikely (status))
1416 	    return status;
1417     }
1418 
1419     if (cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD)
1420 	cur_glyph = glyphs + num_glyphs - 1;
1421     else
1422 	cur_glyph = glyphs;
1423 
1424     /* XXX
1425      * If no glyphs, we should put *something* here for the text to be selectable. */
1426     for (i = 0; i < num_glyphs; i++) {
1427 	status = _cairo_scaled_font_subsets_map_glyph (pdf_operators->font_subsets,
1428 						       scaled_font,
1429 						       cur_glyph->index,
1430 						       NULL, -1,
1431 						       &subset_glyph);
1432 	if (unlikely (status))
1433 	    return status;
1434 
1435 	status = _cairo_pdf_operators_emit_glyph (pdf_operators,
1436 						  cur_glyph,
1437 						  &subset_glyph);
1438 	if (unlikely (status))
1439 	    return status;
1440 
1441 	if ((cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD))
1442 	    cur_glyph--;
1443 	else
1444 	    cur_glyph++;
1445     }
1446 
1447     if (pdf_operators->use_actual_text) {
1448 	status = _cairo_pdf_operators_flush_glyphs (pdf_operators);
1449 	if (unlikely (status))
1450 	    return status;
1451 
1452 	status = _cairo_pdf_operators_end_actualtext (pdf_operators);
1453     }
1454 
1455     return status;
1456 }
1457 
1458 cairo_int_status_t
_cairo_pdf_operators_show_text_glyphs(cairo_pdf_operators_t * pdf_operators,const char * utf8,int utf8_len,cairo_glyph_t * glyphs,int num_glyphs,const cairo_text_cluster_t * clusters,int num_clusters,cairo_text_cluster_flags_t cluster_flags,cairo_scaled_font_t * scaled_font)1459 _cairo_pdf_operators_show_text_glyphs (cairo_pdf_operators_t	  *pdf_operators,
1460 				       const char                 *utf8,
1461 				       int                         utf8_len,
1462 				       cairo_glyph_t              *glyphs,
1463 				       int                         num_glyphs,
1464 				       const cairo_text_cluster_t *clusters,
1465 				       int                         num_clusters,
1466 				       cairo_text_cluster_flags_t  cluster_flags,
1467 				       cairo_scaled_font_t	  *scaled_font)
1468 {
1469     cairo_status_t status;
1470     int i;
1471     cairo_matrix_t text_matrix, invert_y_axis;
1472     double x, y;
1473     const char *cur_text;
1474     cairo_glyph_t *cur_glyph;
1475 
1476     pdf_operators->font_matrix_inverse = scaled_font->font_matrix;
1477     status = cairo_matrix_invert (&pdf_operators->font_matrix_inverse);
1478     if (status == CAIRO_STATUS_INVALID_MATRIX)
1479 	return CAIRO_STATUS_SUCCESS;
1480     assert (status == CAIRO_STATUS_SUCCESS);
1481 
1482     pdf_operators->is_new_text_object = FALSE;
1483     if (pdf_operators->in_text_object == FALSE) {
1484 	status = _cairo_pdf_operators_begin_text (pdf_operators);
1485 	if (unlikely (status))
1486 	    return status;
1487 
1488 	/* Force Tm and Tf to be emitted when starting a new text
1489 	 * object.*/
1490 	pdf_operators->is_new_text_object = TRUE;
1491     }
1492 
1493     cairo_matrix_init_scale (&invert_y_axis, 1, -1);
1494     text_matrix = scaled_font->scale;
1495 
1496     /* Invert y axis in device space  */
1497     cairo_matrix_multiply (&text_matrix, &invert_y_axis, &text_matrix);
1498 
1499     if (pdf_operators->is_new_text_object ||
1500 	! _cairo_matrix_scale_equal (&pdf_operators->text_matrix, &text_matrix))
1501     {
1502 	status = _cairo_pdf_operators_flush_glyphs (pdf_operators);
1503 	if (unlikely (status))
1504 	    return status;
1505 
1506 	x = glyphs[0].x;
1507 	y = glyphs[0].y;
1508 	cairo_matrix_transform_point (&pdf_operators->cairo_to_pdf, &x, &y);
1509 	text_matrix.x0 = x;
1510 	text_matrix.y0 = y;
1511 	status = _cairo_pdf_operators_set_text_matrix (pdf_operators, &text_matrix);
1512 	if (status == CAIRO_STATUS_INVALID_MATRIX)
1513 	    return CAIRO_STATUS_SUCCESS;
1514 	if (unlikely (status))
1515 	    return status;
1516     }
1517 
1518     if (num_clusters > 0) {
1519 	cur_text = utf8;
1520 	if ((cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD))
1521 	    cur_glyph = glyphs + num_glyphs;
1522 	else
1523 	    cur_glyph = glyphs;
1524 	for (i = 0; i < num_clusters; i++) {
1525 	    if ((cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD))
1526 		cur_glyph -= clusters[i].num_glyphs;
1527 	    status = _cairo_pdf_operators_emit_cluster (pdf_operators,
1528 							cur_text,
1529 							clusters[i].num_bytes,
1530 							cur_glyph,
1531 							clusters[i].num_glyphs,
1532 							cluster_flags,
1533 							scaled_font);
1534 	    if (unlikely (status))
1535 		return status;
1536 
1537 	    cur_text += clusters[i].num_bytes;
1538 	    if (!(cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD))
1539 		cur_glyph += clusters[i].num_glyphs;
1540 	}
1541     } else {
1542 	for (i = 0; i < num_glyphs; i++) {
1543 	    status = _cairo_pdf_operators_emit_cluster (pdf_operators,
1544 							NULL,
1545 							-1, /* no unicode string available */
1546 							&glyphs[i],
1547 							1,
1548 							FALSE,
1549 							scaled_font);
1550 	    if (unlikely (status))
1551 		return status;
1552 	}
1553     }
1554 
1555     return _cairo_output_stream_get_status (pdf_operators->stream);
1556 }
1557 
1558 cairo_int_status_t
_cairo_pdf_operators_tag_begin(cairo_pdf_operators_t * pdf_operators,const char * tag_name,int mcid)1559 _cairo_pdf_operators_tag_begin (cairo_pdf_operators_t *pdf_operators,
1560 				const char            *tag_name,
1561 				int                    mcid)
1562 {
1563     cairo_status_t status;
1564 
1565     if (pdf_operators->in_text_object) {
1566 	status = _cairo_pdf_operators_end_text (pdf_operators);
1567 	if (unlikely (status))
1568 	    return status;
1569     }
1570 
1571     _cairo_output_stream_printf (pdf_operators->stream,
1572 				 "/%s << /MCID %d >> BDC\n",
1573 				 tag_name,
1574 				 mcid);
1575 
1576     return _cairo_output_stream_get_status (pdf_operators->stream);
1577 }
1578 
1579 cairo_int_status_t
_cairo_pdf_operators_tag_end(cairo_pdf_operators_t * pdf_operators)1580 _cairo_pdf_operators_tag_end (cairo_pdf_operators_t *pdf_operators)
1581 {
1582     cairo_status_t status;
1583 
1584     if (pdf_operators->in_text_object) {
1585 	status = _cairo_pdf_operators_end_text (pdf_operators);
1586 	if (unlikely (status))
1587 	    return status;
1588     }
1589 
1590     _cairo_output_stream_printf (pdf_operators->stream, "EMC\n");
1591 
1592     return _cairo_output_stream_get_status (pdf_operators->stream);
1593 }
1594 
1595 #endif /* CAIRO_HAS_PDF_OPERATORS */
1596