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
57
10
_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
10
    pdf_operators->stream = stream;
64
10
    pdf_operators->cairo_to_pdf = *cairo_to_pdf;
65
10
    pdf_operators->font_subsets = font_subsets;
66
10
    pdf_operators->ps_output = ps;
67
10
    pdf_operators->use_font_subset = NULL;
68
10
    pdf_operators->use_font_subset_closure = NULL;
69
10
    pdf_operators->in_text_object = FALSE;
70
10
    pdf_operators->num_glyphs = 0;
71
10
    pdf_operators->has_line_style = FALSE;
72
10
    pdf_operators->use_actual_text = FALSE;
73
10
}
74

            
75
cairo_status_t
76
5
_cairo_pdf_operators_fini (cairo_pdf_operators_t	*pdf_operators)
77
{
78
5
    return _cairo_pdf_operators_flush (pdf_operators);
79
}
80

            
81
void
82
5
_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
5
    pdf_operators->use_font_subset = use_font_subset;
87
5
    pdf_operators->use_font_subset_closure = closure;
88
5
}
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
95
104
_cairo_pdf_operators_set_stream (cairo_pdf_operators_t	 *pdf_operators,
96
				 cairo_output_stream_t   *stream)
97
{
98
104
    pdf_operators->stream = stream;
99
104
    pdf_operators->has_line_style = FALSE;
100
104
}
101

            
102
void
103
16
_cairo_pdf_operators_set_cairo_to_pdf_matrix (cairo_pdf_operators_t *pdf_operators,
104
					      cairo_matrix_t	    *cairo_to_pdf)
105
{
106
16
    pdf_operators->cairo_to_pdf = *cairo_to_pdf;
107
16
    pdf_operators->has_line_style = FALSE;
108
16
}
109

            
110
cairo_private void
111
5
_cairo_pdf_operators_enable_actual_text (cairo_pdf_operators_t *pdf_operators,
112
					 cairo_bool_t 	  	enable)
113
{
114
5
    pdf_operators->use_actual_text = enable;
115
5
}
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
129
352
_cairo_pdf_operators_flush (cairo_pdf_operators_t	 *pdf_operators)
130
{
131
352
    cairo_status_t status = CAIRO_STATUS_SUCCESS;
132

            
133
352
    if (pdf_operators->in_text_object)
134
	status = _cairo_pdf_operators_end_text (pdf_operators);
135

            
136
352
    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
150
174
_cairo_pdf_operators_reset (cairo_pdf_operators_t *pdf_operators)
151
{
152
174
    pdf_operators->has_line_style = FALSE;
153
174
}
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
192
1347
_word_wrap_stream_count_word_up_to (word_wrap_stream_t *stream,
193
				   const unsigned char *data, int length)
194
{
195
1347
    const unsigned char *s = data;
196
1347
    int count = 0;
197

            
198
3516
    while (length--) {
199
3516
	if (_cairo_isspace (*s) || *s == '<' || *s == '(') {
200
1347
	    stream->state = WRAP_STATE_DELIMITER;
201
1347
	    break;
202
	}
203

            
204
2169
	count++;
205
2169
	stream->column++;
206
2169
	s++;
207
    }
208

            
209
1347
    if (count)
210
821
	_cairo_output_stream_write (stream->output, data, count);
211

            
212
1347
    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
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
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
298
972
_word_wrap_stream_write (cairo_output_stream_t  *base,
299
			 const unsigned char	*data,
300
			 unsigned int		 length)
301
{
302
972
    word_wrap_stream_t *stream = (word_wrap_stream_t *) base;
303
    int count;
304

            
305
5013
    while (length) {
306
4041
	switch (stream->state) {
307
1347
	case WRAP_STATE_WORD:
308
1347
	    count = _word_wrap_stream_count_word_up_to (stream, data, length);
309
1347
	    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
2694
	case WRAP_STATE_DELIMITER:
317
2694
	    count = 1;
318
2694
	    stream->column++;
319
2694
	    if (*data == '\n' || stream->column >= stream->max_column) {
320
64
		_cairo_output_stream_printf (stream->output, "\n");
321
64
		stream->column = 0;
322
	    }
323
2694
	    if (*data == '<') {
324
		stream->state = WRAP_STATE_HEXSTRING;
325
2694
	    } else if (*data == '(') {
326
		stream->state = WRAP_STATE_STRING;
327
2694
	    } else if (!_cairo_isspace (*data)) {
328
1347
		stream->state = WRAP_STATE_WORD;
329
	    }
330
2694
	    if (*data != '\n')
331
2630
		_cairo_output_stream_write (stream->output, data, 1);
332
2694
	    break;
333

            
334
	default:
335
	    ASSERT_NOT_REACHED;
336
	    count = length;
337
	    break;
338
	}
339
4041
	data += count;
340
4041
	length -= count;
341
    }
342

            
343
972
    return _cairo_output_stream_get_status (stream->output);
344
}
345

            
346
static cairo_status_t
347
119
_word_wrap_stream_close (cairo_output_stream_t *base)
348
{
349
119
    word_wrap_stream_t *stream = (word_wrap_stream_t *) base;
350

            
351
119
    return _cairo_output_stream_get_status (stream->output);
352
}
353

            
354
static cairo_output_stream_t *
355
119
_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
119
    if (output->status)
360
	return _cairo_output_stream_create_in_error (output->status);
361

            
362
119
    stream = _cairo_calloc (sizeof (word_wrap_stream_t));
363
119
    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
119
    _cairo_output_stream_init (&stream->base,
369
			       _word_wrap_stream_write,
370
			       NULL,
371
			       _word_wrap_stream_close);
372
119
    stream->output = output;
373
119
    stream->max_column = max_column;
374
119
    stream->ps_output = ps;
375
119
    stream->column = 0;
376
119
    stream->state = WRAP_STATE_DELIMITER;
377
119
    stream->in_escape = FALSE;
378
119
    stream->escape_digits = 0;
379

            
380
119
    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
392
104
_cairo_pdf_path_move_to (void *closure,
393
			 const cairo_point_t *point)
394
{
395
104
    pdf_path_info_t *info = closure;
396
104
    double x = _cairo_fixed_to_double (point->x);
397
104
    double y = _cairo_fixed_to_double (point->y);
398

            
399
104
    info->last_move_to_point = *point;
400
104
    info->has_sub_path = FALSE;
401
104
    cairo_matrix_transform_point (info->path_transform, &x, &y);
402
104
    _cairo_output_stream_printf (info->output,
403
				 "%g %g m ", x, y);
404

            
405
104
    return _cairo_output_stream_get_status (info->output);
406
}
407

            
408
static cairo_status_t
409
192
_cairo_pdf_path_line_to (void *closure,
410
			 const cairo_point_t *point)
411
{
412
192
    pdf_path_info_t *info = closure;
413
192
    double x = _cairo_fixed_to_double (point->x);
414
192
    double y = _cairo_fixed_to_double (point->y);
415

            
416
192
    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
192
    info->has_sub_path = TRUE;
425
192
    cairo_matrix_transform_point (info->path_transform, &x, &y);
426
192
    _cairo_output_stream_printf (info->output,
427
				 "%g %g l ", x, y);
428

            
429
192
    return _cairo_output_stream_get_status (info->output);
430
}
431

            
432
static cairo_status_t
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
457
64
_cairo_pdf_path_close_path (void *closure)
458
{
459
64
    pdf_path_info_t *info = closure;
460

            
461
64
    if (info->line_cap != CAIRO_LINE_CAP_ROUND &&
462
	! info->has_sub_path)
463
    {
464
	return CAIRO_STATUS_SUCCESS;
465
    }
466

            
467
64
    _cairo_output_stream_printf (info->output,
468
				 "h\n");
469

            
470
64
    return _cairo_output_stream_get_status (info->output);
471
}
472

            
473
static cairo_status_t
474
79
_cairo_pdf_path_rectangle (pdf_path_info_t *info, cairo_box_t *box)
475
{
476
79
    double x1 = _cairo_fixed_to_double (box->p1.x);
477
79
    double y1 = _cairo_fixed_to_double (box->p1.y);
478
79
    double x2 = _cairo_fixed_to_double (box->p2.x);
479
79
    double y2 = _cairo_fixed_to_double (box->p2.y);
480

            
481
79
    cairo_matrix_transform_point (info->path_transform, &x1, &y1);
482
79
    cairo_matrix_transform_point (info->path_transform, &x2, &y2);
483
79
    _cairo_output_stream_printf (info->output,
484
				 "%g %g %g %g re ",
485
				 x1, y1, x2 - x1, y2 - y1);
486

            
487
79
    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
500
119
_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
119
    word_wrap = _word_wrap_stream_create (pdf_operators->stream, pdf_operators->ps_output, 72);
511
119
    status = _cairo_output_stream_get_status (word_wrap);
512
119
    if (unlikely (status))
513
	return _cairo_output_stream_destroy (word_wrap);
514

            
515
119
    info.output = word_wrap;
516
119
    info.path_transform = path_transform;
517
119
    info.line_cap = line_cap;
518
119
    if (_cairo_path_fixed_is_rectangle (path, &box) &&
519
79
	((path_transform->xx == 0 && path_transform->yy == 0) ||
520
79
	 (path_transform->xy == 0 && path_transform->yx == 0))) {
521
79
	status = _cairo_pdf_path_rectangle (&info, &box);
522
    } else {
523
40
	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
119
    status2 = _cairo_output_stream_destroy (word_wrap);
532
119
    if (status == CAIRO_STATUS_SUCCESS)
533
119
	status = status2;
534

            
535
119
    return status;
536
}
537

            
538
cairo_int_status_t
539
67
_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
67
    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
67
    if (! path->has_current_point) {
553
	/* construct an empty path */
554
	_cairo_output_stream_printf (pdf_operators->stream, "0 0 m ");
555
    } else {
556
67
	status = _cairo_pdf_operators_emit_path (pdf_operators,
557
						 path,
558
						 &pdf_operators->cairo_to_pdf,
559
						 CAIRO_LINE_CAP_ROUND);
560
67
	if (unlikely (status))
561
	    return status;
562
    }
563

            
564
67
    switch (fill_rule) {
565
    default:
566
	ASSERT_NOT_REACHED;
567
    case CAIRO_FILL_RULE_WINDING:
568
67
	pdf_operator = "W";
569
67
	break;
570
    case CAIRO_FILL_RULE_EVEN_ODD:
571
	pdf_operator = "W*";
572
	break;
573
    }
574

            
575
67
    _cairo_output_stream_printf (pdf_operators->stream,
576
				 "%s n\n",
577
				 pdf_operator);
578

            
579
67
    return _cairo_output_stream_get_status (pdf_operators->stream);
580
}
581

            
582
static int
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
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
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
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
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
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
877
52
_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
52
    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
52
    status = _cairo_pdf_operators_emit_path (pdf_operators,
891
					     path,
892
					     &pdf_operators->cairo_to_pdf,
893
					     CAIRO_LINE_CAP_ROUND);
894
52
    if (unlikely (status))
895
	return status;
896

            
897
52
    switch (fill_rule) {
898
    default:
899
	ASSERT_NOT_REACHED;
900
    case CAIRO_FILL_RULE_WINDING:
901
52
	pdf_operator = "f";
902
52
	break;
903
    case CAIRO_FILL_RULE_EVEN_ODD:
904
	pdf_operator = "f*";
905
	break;
906
    }
907

            
908
52
    _cairo_output_stream_printf (pdf_operators->stream,
909
				 "%s\n",
910
				 pdf_operator);
911

            
912
52
    return _cairo_output_stream_get_status (pdf_operators->stream);
913
}
914

            
915
cairo_int_status_t
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
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
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
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;
    _cairo_output_stream_printf (stream, "[%s", pdf_operators->is_latin ? "(" : "<");
    for (i = 0; i < pdf_operators->num_glyphs; i++) {
	if (pdf_operators->glyphs[i].x_position != pdf_operators->cur_x)
	{
	    double delta = pdf_operators->glyphs[i].x_position - pdf_operators->cur_x;
	    int rounded_delta;
	    delta = -1000.0*delta;
	    /* As the delta is in 1/1000 of a unit of text space,
	     * rounding to an integer should still provide sufficient
	     * precision. We round the delta before adding to Tm_x so
	     * that we keep track of the accumulated rounding error in
	     * the PDF interpreter and compensate for it when
	     * calculating subsequent deltas.
	     */
	    rounded_delta = _cairo_lround (delta);
	    if (abs(rounded_delta) < 3)
		rounded_delta = 0;
	    if (rounded_delta != 0) {
		if (pdf_operators->is_latin) {
		    _cairo_output_stream_printf (stream,
						 ")%d(",
						 rounded_delta);
		} else {
		    _cairo_output_stream_printf (stream,
						 ">%d<",
						 rounded_delta);
		}
	    }
	    /* Convert the rounded delta back to text
	     * space before adding to the current text
	     * position. */
	    delta = rounded_delta/-1000.0;
	    pdf_operators->cur_x += delta;
	}
	_cairo_pdf_operators_emit_glyph_index (pdf_operators,
					       stream,
					       pdf_operators->glyphs[i].glyph_index);
	pdf_operators->cur_x += pdf_operators->glyphs[i].x_advance;
    }
    _cairo_output_stream_printf (stream, "%s]TJ\n", pdf_operators->is_latin ? ")" : ">");
    return _cairo_output_stream_get_status (stream);
}
static cairo_status_t
_cairo_pdf_operators_flush_glyphs (cairo_pdf_operators_t    *pdf_operators)
{
    cairo_output_stream_t *word_wrap_stream;
    cairo_status_t status, status2;
    int i;
    double x;
    if (pdf_operators->num_glyphs == 0)
	return CAIRO_STATUS_SUCCESS;
    word_wrap_stream = _word_wrap_stream_create (pdf_operators->stream, pdf_operators->ps_output, 72);
    status = _cairo_output_stream_get_status (word_wrap_stream);
    if (unlikely (status))
	return _cairo_output_stream_destroy (word_wrap_stream);
    /* Check if glyph advance used to position every glyph */
    x = pdf_operators->cur_x;
    for (i = 0; i < pdf_operators->num_glyphs; i++) {
	if (fabs(pdf_operators->glyphs[i].x_position - x) > GLYPH_POSITION_TOLERANCE)
	    break;
	x += pdf_operators->glyphs[i].x_advance;
    }
    if (i == pdf_operators->num_glyphs) {
	status = _cairo_pdf_operators_emit_glyph_string (pdf_operators,
							 word_wrap_stream);
    } else {
	status = _cairo_pdf_operators_emit_glyph_string_with_positioning (
	    pdf_operators, word_wrap_stream);
    }
    pdf_operators->num_glyphs = 0;
    pdf_operators->glyph_buf_x_pos = pdf_operators->cur_x;
    status2 = _cairo_output_stream_destroy (word_wrap_stream);
    if (status == CAIRO_STATUS_SUCCESS)
	status = status2;
    return status;
}
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)
{
    double x, y;
    x = glyph->x_advance;
    y = glyph->y_advance;
    if (glyph->is_scaled)
	cairo_matrix_transform_distance (&pdf_operators->font_matrix_inverse, &x, &y);
    pdf_operators->glyphs[pdf_operators->num_glyphs].x_position = x_position;
    pdf_operators->glyphs[pdf_operators->num_glyphs].glyph_index = glyph->subset_glyph_index;
    pdf_operators->glyphs[pdf_operators->num_glyphs].x_advance = x;
    pdf_operators->glyph_buf_x_pos += x;
    pdf_operators->num_glyphs++;
    if (pdf_operators->num_glyphs == PDF_GLYPH_BUFFER_SIZE)
	return _cairo_pdf_operators_flush_glyphs (pdf_operators);
    return CAIRO_STATUS_SUCCESS;
}
/* Use 'Tm' operator to set the PDF text matrix. */
static cairo_status_t
_cairo_pdf_operators_set_text_matrix (cairo_pdf_operators_t  *pdf_operators,
				      cairo_matrix_t         *matrix)
{
    cairo_matrix_t inverse;
    cairo_status_t status;
    /* We require the matrix to be invertable. */
    inverse = *matrix;
    status = cairo_matrix_invert (&inverse);
    if (unlikely (status))
	return status;
    pdf_operators->text_matrix = *matrix;
    pdf_operators->cur_x = 0;
    pdf_operators->cur_y = 0;
    pdf_operators->glyph_buf_x_pos = 0;
    _cairo_output_stream_print_matrix (pdf_operators->stream, &pdf_operators->text_matrix);
    _cairo_output_stream_printf (pdf_operators->stream, " Tm\n");
    pdf_operators->cairo_to_pdftext = *matrix;
    status = cairo_matrix_invert (&pdf_operators->cairo_to_pdftext);
    assert (status == CAIRO_STATUS_SUCCESS);
    cairo_matrix_multiply (&pdf_operators->cairo_to_pdftext,
			   &pdf_operators->cairo_to_pdf,
			   &pdf_operators->cairo_to_pdftext);
    return _cairo_output_stream_get_status (pdf_operators->stream);
}
#define TEXT_MATRIX_TOLERANCE 1e-6
/* Set the translation components of the PDF text matrix to x, y. The
 * 'Td' operator is used to transform the text matrix.
 */
static cairo_status_t
_cairo_pdf_operators_set_text_position (cairo_pdf_operators_t  *pdf_operators,
					double 			x,
					double 			y)
{
    cairo_matrix_t translate, inverse;
    cairo_status_t status;
    /* The Td operator transforms the text_matrix with:
     *
     *   text_matrix' = T x text_matrix
     *
     * where T is a translation matrix with the translation components
     * set to the Td operands tx and ty.
     */
    inverse = pdf_operators->text_matrix;
    status = cairo_matrix_invert (&inverse);
    assert (status == CAIRO_STATUS_SUCCESS);
    pdf_operators->text_matrix.x0 = x;
    pdf_operators->text_matrix.y0 = y;
    cairo_matrix_multiply (&translate, &pdf_operators->text_matrix, &inverse);
    if (fabs(translate.x0) < TEXT_MATRIX_TOLERANCE)
	translate.x0 = 0.0;
    if (fabs(translate.y0) < TEXT_MATRIX_TOLERANCE)
	translate.y0 = 0.0;
    _cairo_output_stream_printf (pdf_operators->stream,
				 "%f %f Td\n",
				 translate.x0,
				 translate.y0);
    pdf_operators->cur_x = 0;
    pdf_operators->cur_y = 0;
    pdf_operators->glyph_buf_x_pos = 0;
    pdf_operators->cairo_to_pdftext = pdf_operators->text_matrix;
    status = cairo_matrix_invert (&pdf_operators->cairo_to_pdftext);
    assert (status == CAIRO_STATUS_SUCCESS);
    cairo_matrix_multiply (&pdf_operators->cairo_to_pdftext,
			   &pdf_operators->cairo_to_pdf,
			   &pdf_operators->cairo_to_pdftext);
    return _cairo_output_stream_get_status (pdf_operators->stream);
}
/* Select the font using the 'Tf' operator. The font size is set to 1
 * as we use the 'Tm' operator to set the font scale.
 */
static cairo_status_t
_cairo_pdf_operators_set_font_subset (cairo_pdf_operators_t             *pdf_operators,
				      cairo_scaled_font_subsets_glyph_t *subset_glyph)
{
    cairo_status_t status;
    _cairo_output_stream_printf (pdf_operators->stream,
				 "/f-%d-%d 1 Tf\n",
				 subset_glyph->font_id,
				 subset_glyph->subset_id);
    if (pdf_operators->use_font_subset) {
	status = pdf_operators->use_font_subset (subset_glyph->font_id,
						 subset_glyph->subset_id,
						 pdf_operators->use_font_subset_closure);
	if (unlikely (status))
	    return status;
    }
    pdf_operators->font_id = subset_glyph->font_id;
    pdf_operators->subset_id = subset_glyph->subset_id;
    pdf_operators->is_latin = subset_glyph->is_latin;
    if (subset_glyph->is_composite)
	pdf_operators->hex_width = 4;
    else
	pdf_operators->hex_width = 2;
    return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_pdf_operators_begin_text (cairo_pdf_operators_t    *pdf_operators)
{
    _cairo_output_stream_printf (pdf_operators->stream, "BT\n");
    pdf_operators->in_text_object = TRUE;
    pdf_operators->num_glyphs = 0;
    pdf_operators->glyph_buf_x_pos = 0;
    return _cairo_output_stream_get_status (pdf_operators->stream);
}
static cairo_status_t
_cairo_pdf_operators_end_text (cairo_pdf_operators_t    *pdf_operators)
{
    cairo_status_t status;
    status = _cairo_pdf_operators_flush_glyphs (pdf_operators);
    if (unlikely (status))
	return status;
    _cairo_output_stream_printf (pdf_operators->stream, "ET\n");
    pdf_operators->in_text_object = FALSE;
    return _cairo_output_stream_get_status (pdf_operators->stream);
}
/* Compare the scale components of two matrices. The translation
 * components are ignored. */
static cairo_bool_t
_cairo_matrix_scale_equal (cairo_matrix_t *a, cairo_matrix_t *b)
{
    return (a->xx == b->xx &&
	    a->xy == b->xy &&
	    a->yx == b->yx &&
	    a->yy == b->yy);
}
static cairo_status_t
_cairo_pdf_operators_begin_actualtext (cairo_pdf_operators_t *pdf_operators,
				       const char 	     *utf8,
				       int		      utf8_len)
{
    uint16_t *utf16;
    int utf16_len;
    cairo_status_t status;
    int i;
    _cairo_output_stream_printf (pdf_operators->stream, "/Span << /ActualText <feff");
    if (utf8_len) {
	status = _cairo_utf8_to_utf16 (utf8, utf8_len, &utf16, &utf16_len);
	if (unlikely (status))
	    return status;
	for (i = 0; i < utf16_len; i++) {
	    _cairo_output_stream_printf (pdf_operators->stream,
					 "%04x", (int) (utf16[i]));
	}
	free (utf16);
    }
    _cairo_output_stream_printf (pdf_operators->stream, "> >> BDC\n");
    return _cairo_output_stream_get_status (pdf_operators->stream);
}
static cairo_status_t
_cairo_pdf_operators_end_actualtext (cairo_pdf_operators_t    *pdf_operators)
{
    _cairo_output_stream_printf (pdf_operators->stream, "EMC\n");
    return _cairo_output_stream_get_status (pdf_operators->stream);
}
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)
{
    double x, y;
    cairo_status_t status;
    if (pdf_operators->is_new_text_object ||
	pdf_operators->font_id != subset_glyph->font_id ||
	pdf_operators->subset_id != subset_glyph->subset_id)
    {
	status = _cairo_pdf_operators_flush_glyphs (pdf_operators);
	if (unlikely (status))
	    return status;
	status = _cairo_pdf_operators_set_font_subset (pdf_operators, subset_glyph);
	if (unlikely (status))
	    return status;
	pdf_operators->is_new_text_object = FALSE;
    }
    x = glyph->x;
    y = glyph->y;
    cairo_matrix_transform_point (&pdf_operators->cairo_to_pdftext, &x, &y);
    /* The TJ operator for displaying text strings can only set
     * the horizontal position of the glyphs. If the y position
     * (in text space) changes, use the Td operator to change the
     * current position to the next glyph. We also use the Td
     * operator to move the current position if the horizontal
     * position changes by more than 10 (in text space
     * units). This is because the horizontal glyph positioning
     * in the TJ operator is intended for kerning and there may be
     * PDF consumers that do not handle very large position
     * adjustments in TJ.
     */
    if (fabs(x - pdf_operators->glyph_buf_x_pos) > 10 ||
	fabs(y - pdf_operators->cur_y) > GLYPH_POSITION_TOLERANCE)
    {
	status = _cairo_pdf_operators_flush_glyphs (pdf_operators);
	if (unlikely (status))
	    return status;
	x = glyph->x;
	y = glyph->y;
	cairo_matrix_transform_point (&pdf_operators->cairo_to_pdf, &x, &y);
	status = _cairo_pdf_operators_set_text_position (pdf_operators, x, y);
	if (unlikely (status))
	    return status;
	x = 0.0;
	y = 0.0;
    }
    status = _cairo_pdf_operators_add_glyph (pdf_operators,
					     subset_glyph,
					     x);
    return status;
}
/* A utf8_len of -1 indicates no unicode text. A utf8_len = 0 is an
 * empty string.
 */
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)
{
    cairo_scaled_font_subsets_glyph_t subset_glyph;
    cairo_glyph_t *cur_glyph;
    cairo_status_t status = CAIRO_STATUS_SUCCESS;
    int i;
    /* If the cluster maps 1 glyph to 1 or more unicode characters, we
     * first try _map_glyph() with the unicode string to see if it can
     * use toUnicode to map our glyph to the unicode. This will fail
     * if the glyph is already mapped to a different unicode string.
     *
     * We also go through this path if no unicode mapping was
     * supplied (utf8_len < 0).
     *
     * Mapping a glyph to a zero length unicode string requires the
     * use of ActualText.
     */
    if (num_glyphs == 1 && utf8_len != 0) {
	status = _cairo_scaled_font_subsets_map_glyph (pdf_operators->font_subsets,
						       scaled_font,
						       glyphs->index,
						       utf8,
						       utf8_len,
						       &subset_glyph);
	if (unlikely (status))
	    return status;
	if (subset_glyph.utf8_is_mapped || utf8_len < 0) {
	    status = _cairo_pdf_operators_emit_glyph (pdf_operators,
						      glyphs,
						      &subset_glyph);
	    if (unlikely (status))
		return status;
	    return CAIRO_STATUS_SUCCESS;
	}
    }
    if (pdf_operators->use_actual_text) {
	/* Fallback to using ActualText to map zero or more glyphs to a
	 * unicode string. */
	status = _cairo_pdf_operators_flush_glyphs (pdf_operators);
	if (unlikely (status))
	    return status;
	status = _cairo_pdf_operators_begin_actualtext (pdf_operators, utf8, utf8_len);
	if (unlikely (status))
	    return status;
    }
    if (cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD)
	cur_glyph = glyphs + num_glyphs - 1;
    else
	cur_glyph = glyphs;
    /* XXX
     * If no glyphs, we should put *something* here for the text to be selectable. */
    for (i = 0; i < num_glyphs; i++) {
	status = _cairo_scaled_font_subsets_map_glyph (pdf_operators->font_subsets,
						       scaled_font,
						       cur_glyph->index,
						       NULL, -1,
						       &subset_glyph);
	if (unlikely (status))
	    return status;
	status = _cairo_pdf_operators_emit_glyph (pdf_operators,
						  cur_glyph,
						  &subset_glyph);
	if (unlikely (status))
	    return status;
	if ((cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD))
	    cur_glyph--;
	else
	    cur_glyph++;
    }
    if (pdf_operators->use_actual_text) {
	status = _cairo_pdf_operators_flush_glyphs (pdf_operators);
	if (unlikely (status))
	    return status;
	status = _cairo_pdf_operators_end_actualtext (pdf_operators);
    }
    return status;
}
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)
{
    cairo_status_t status;
    int i;
    cairo_matrix_t text_matrix, invert_y_axis;
    double x, y;
    const char *cur_text;
    cairo_glyph_t *cur_glyph;
    pdf_operators->font_matrix_inverse = scaled_font->font_matrix;
    status = cairo_matrix_invert (&pdf_operators->font_matrix_inverse);
    if (status == CAIRO_STATUS_INVALID_MATRIX)
	return CAIRO_STATUS_SUCCESS;
    assert (status == CAIRO_STATUS_SUCCESS);
    pdf_operators->is_new_text_object = FALSE;
    if (pdf_operators->in_text_object == FALSE) {
	status = _cairo_pdf_operators_begin_text (pdf_operators);
	if (unlikely (status))
	    return status;
	/* Force Tm and Tf to be emitted when starting a new text
	 * object.*/
	pdf_operators->is_new_text_object = TRUE;
    }
    cairo_matrix_init_scale (&invert_y_axis, 1, -1);
    text_matrix = scaled_font->scale;
    /* Invert y axis in device space  */
    cairo_matrix_multiply (&text_matrix, &invert_y_axis, &text_matrix);
    if (pdf_operators->is_new_text_object ||
	! _cairo_matrix_scale_equal (&pdf_operators->text_matrix, &text_matrix))
    {
	status = _cairo_pdf_operators_flush_glyphs (pdf_operators);
	if (unlikely (status))
	    return status;
	x = glyphs[0].x;
	y = glyphs[0].y;
	cairo_matrix_transform_point (&pdf_operators->cairo_to_pdf, &x, &y);
	text_matrix.x0 = x;
	text_matrix.y0 = y;
	status = _cairo_pdf_operators_set_text_matrix (pdf_operators, &text_matrix);
	if (status == CAIRO_STATUS_INVALID_MATRIX)
	    return CAIRO_STATUS_SUCCESS;
	if (unlikely (status))
	    return status;
    }
    if (num_clusters > 0) {
	cur_text = utf8;
	if ((cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD))
	    cur_glyph = glyphs + num_glyphs;
	else
	    cur_glyph = glyphs;
	for (i = 0; i < num_clusters; i++) {
	    if ((cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD))
		cur_glyph -= clusters[i].num_glyphs;
	    status = _cairo_pdf_operators_emit_cluster (pdf_operators,
							cur_text,
							clusters[i].num_bytes,
							cur_glyph,
							clusters[i].num_glyphs,
							cluster_flags,
							scaled_font);
	    if (unlikely (status))
		return status;
	    cur_text += clusters[i].num_bytes;
	    if (!(cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD))
		cur_glyph += clusters[i].num_glyphs;
	}
    } else {
	for (i = 0; i < num_glyphs; i++) {
	    status = _cairo_pdf_operators_emit_cluster (pdf_operators,
							NULL,
							-1, /* no unicode string available */
							&glyphs[i],
							1,
							FALSE,
							scaled_font);
	    if (unlikely (status))
		return status;
	}
    }
    return _cairo_output_stream_get_status (pdf_operators->stream);
}
cairo_int_status_t
_cairo_pdf_operators_tag_begin (cairo_pdf_operators_t *pdf_operators,
				const char            *tag_name,
				int                    mcid)
{
    cairo_status_t status;
    if (pdf_operators->in_text_object) {
	status = _cairo_pdf_operators_end_text (pdf_operators);
	if (unlikely (status))
	    return status;
    }
    if (mcid >= 0) {
	_cairo_output_stream_printf (pdf_operators->stream,
				     "/%s << /MCID %d >> BDC\n",
				     tag_name,
				     mcid);
    } else {
	_cairo_output_stream_printf (pdf_operators->stream,
				     "/%s BMC\n",
				     tag_name);
    }
    return _cairo_output_stream_get_status (pdf_operators->stream);
}
cairo_int_status_t
_cairo_pdf_operators_tag_end (cairo_pdf_operators_t *pdf_operators)
{
    cairo_status_t status;
    if (pdf_operators->in_text_object) {
	status = _cairo_pdf_operators_end_text (pdf_operators);
	if (unlikely (status))
	    return status;
    }
    _cairo_output_stream_printf (pdf_operators->stream, "EMC\n");
    return _cairo_output_stream_get_status (pdf_operators->stream);
}
#endif /* CAIRO_HAS_PDF_OPERATORS */