Subversion Repositories Kolibri OS

Rev

Rev 1897 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1897 serge 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 
38
 *	Carl Worth 
39
 *	Adrian Johnson 
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
_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
{
62
    pdf_operators->stream = stream;
63
    pdf_operators->cairo_to_pdf = *cairo_to_pdf;
64
    pdf_operators->font_subsets = font_subsets;
65
    pdf_operators->use_font_subset = NULL;
66
    pdf_operators->use_font_subset_closure = NULL;
67
    pdf_operators->in_text_object = FALSE;
68
    pdf_operators->num_glyphs = 0;
69
    pdf_operators->has_line_style = FALSE;
70
    pdf_operators->use_actual_text = FALSE;
71
}
72
 
73
cairo_status_t
74
_cairo_pdf_operators_fini (cairo_pdf_operators_t	*pdf_operators)
75
{
76
    return _cairo_pdf_operators_flush (pdf_operators);
77
}
78
 
79
void
80
_cairo_pdf_operators_set_font_subsets_callback (cairo_pdf_operators_t		     *pdf_operators,
81
						cairo_pdf_operators_use_font_subset_t use_font_subset,
82
						void				     *closure)
83
{
84
    pdf_operators->use_font_subset = use_font_subset;
85
    pdf_operators->use_font_subset_closure = closure;
86
}
87
 
88
/* Change the output stream to a different stream.
89
 * _cairo_pdf_operators_flush() should always be called before calling
90
 * this function.
91
 */
92
void
93
_cairo_pdf_operators_set_stream (cairo_pdf_operators_t	 *pdf_operators,
94
				 cairo_output_stream_t   *stream)
95
{
96
    pdf_operators->stream = stream;
97
    pdf_operators->has_line_style = FALSE;
98
}
99
 
100
void
101
_cairo_pdf_operators_set_cairo_to_pdf_matrix (cairo_pdf_operators_t *pdf_operators,
102
					      cairo_matrix_t	    *cairo_to_pdf)
103
{
104
    pdf_operators->cairo_to_pdf = *cairo_to_pdf;
105
    pdf_operators->has_line_style = FALSE;
106
}
107
 
108
cairo_private void
109
_cairo_pdf_operators_enable_actual_text (cairo_pdf_operators_t *pdf_operators,
110
					 cairo_bool_t 	  	enable)
111
{
112
    pdf_operators->use_actual_text = enable;
113
}
114
 
115
/* Finish writing out any pending commands to the stream. This
116
 * function must be called by the surface before emitting anything
117
 * into the PDF stream.
118
 *
119
 * pdf_operators may leave the emitted PDF for some operations
120
 * unfinished in case subsequent operations can be merged. This
121
 * function will finish off any incomplete operation so the stream
122
 * will be in a state where the surface may emit its own PDF
123
 * operations (eg changing patterns).
124
 *
125
 */
126
cairo_status_t
127
_cairo_pdf_operators_flush (cairo_pdf_operators_t	 *pdf_operators)
128
{
129
    cairo_status_t status = CAIRO_STATUS_SUCCESS;
130
 
131
    if (pdf_operators->in_text_object)
132
	status = _cairo_pdf_operators_end_text (pdf_operators);
133
 
134
    return status;
135
}
136
 
137
/* Reset the known graphics state of the PDF consumer. ie no
138
 * assumptions will be made about the state. The next time a
139
 * particular graphics state is required (eg line width) the state
140
 * operator is always emitted and then remembered for subsequent
141
 * operatations.
142
 *
143
 * This should be called when starting a new stream or after emitting
144
 * the 'Q' operator (where pdf-operators functions were called inside
145
 * the q/Q pair).
146
 */
147
void
148
_cairo_pdf_operators_reset (cairo_pdf_operators_t *pdf_operators)
149
{
150
    pdf_operators->has_line_style = FALSE;
151
}
152
 
153
/* A word wrap stream can be used as a filter to do word wrapping on
154
 * top of an existing output stream. The word wrapping is quite
155
 * simple, using isspace to determine characters that separate
156
 * words. Any word that will cause the column count exceed the given
157
 * max_column will have a '\n' character emitted before it.
158
 *
159
 * The stream is careful to maintain integrity for words that cross
160
 * the boundary from one call to write to the next.
161
 *
162
 * Note: This stream does not guarantee that the output will never
163
 * exceed max_column. In particular, if a single word is larger than
164
 * max_column it will not be broken up.
165
 */
3959 Serge 166
 
167
typedef enum _cairo_word_wrap_state {
168
    WRAP_STATE_DELIMITER,
169
    WRAP_STATE_WORD,
170
    WRAP_STATE_STRING,
171
    WRAP_STATE_HEXSTRING
172
} cairo_word_wrap_state_t;
173
 
174
 
1897 serge 175
typedef struct _word_wrap_stream {
176
    cairo_output_stream_t base;
177
    cairo_output_stream_t *output;
178
    int max_column;
179
    int column;
3959 Serge 180
    cairo_word_wrap_state_t state;
181
    cairo_bool_t in_escape;
182
    int		 escape_digits;
1897 serge 183
} word_wrap_stream_t;
184
 
3959 Serge 185
 
186
 
187
/* Emit word bytes up to the next delimiter character */
1897 serge 188
static int
3959 Serge 189
_word_wrap_stream_count_word_up_to (word_wrap_stream_t *stream,
190
				   const unsigned char *data, int length)
1897 serge 191
{
3959 Serge 192
    const unsigned char *s = data;
193
    int count = 0;
1897 serge 194
 
195
    while (length--) {
3959 Serge 196
	if (_cairo_isspace (*s) || *s == '<' || *s == '(') {
197
	    stream->state = WRAP_STATE_DELIMITER;
198
	    break;
1897 serge 199
	}
3959 Serge 200
 
201
	count++;
202
	stream->column++;
203
	s++;
1897 serge 204
    }
205
 
3959 Serge 206
    if (count)
207
	_cairo_output_stream_write (stream->output, data, count);
208
 
209
    return count;
1897 serge 210
}
211
 
212
 
3959 Serge 213
/* Emit hexstring bytes up to either the end of the ASCII hexstring or the number
1897 serge 214
 * of columns remaining.
215
 */
216
static int
3959 Serge 217
_word_wrap_stream_count_hexstring_up_to (word_wrap_stream_t *stream,
218
					 const unsigned char *data, int length)
1897 serge 219
{
3959 Serge 220
    const unsigned char *s = data;
221
    int count = 0;
222
    cairo_bool_t newline = FALSE;
1897 serge 223
 
224
    while (length--) {
3959 Serge 225
	count++;
226
	stream->column++;
227
	if (*s == '>') {
228
	    stream->state = WRAP_STATE_DELIMITER;
229
	    break;
230
	}
1897 serge 231
 
3959 Serge 232
	if (stream->column > stream->max_column) {
233
	    newline = TRUE;
234
	    break;
235
	}
236
	s++;
1897 serge 237
    }
238
 
3959 Serge 239
    if (count)
240
	_cairo_output_stream_write (stream->output, data, count);
241
 
242
    if (newline) {
243
	_cairo_output_stream_printf (stream->output, "\n");
244
	stream->column = 0;
245
    }
246
 
247
    return count;
1897 serge 248
}
249
 
3959 Serge 250
/* Count up to either the end of the string or the number of columns
251
 * remaining.
252
 */
253
static int
254
_word_wrap_stream_count_string_up_to (word_wrap_stream_t *stream,
255
				      const unsigned char *data, int length)
256
{
257
    const unsigned char *s = data;
258
    int count = 0;
259
    cairo_bool_t newline = FALSE;
260
 
261
    while (length--) {
262
	count++;
263
	stream->column++;
264
	if (!stream->in_escape) {
265
	    if (*s == ')') {
266
		stream->state = WRAP_STATE_DELIMITER;
267
		break;
268
	    }
269
	    if (*s == '\\') {
270
		stream->in_escape = TRUE;
271
		stream->escape_digits = 0;
272
	    } else if (stream->column > stream->max_column) {
273
		newline = TRUE;
274
		break;
275
	    }
276
	} else {
277
	    if (!_cairo_isdigit(*s) || ++stream->escape_digits == 3)
278
		stream->in_escape = FALSE;
279
	}
280
	s++;
281
    }
282
 
283
    if (count)
284
	_cairo_output_stream_write (stream->output, data, count);
285
 
286
    if (newline) {
287
	_cairo_output_stream_printf (stream->output, "\\\n");
288
	stream->column = 0;
289
    }
290
 
291
    return count;
292
}
293
 
1897 serge 294
static cairo_status_t
295
_word_wrap_stream_write (cairo_output_stream_t  *base,
296
			 const unsigned char	*data,
297
			 unsigned int		 length)
298
{
299
    word_wrap_stream_t *stream = (word_wrap_stream_t *) base;
3959 Serge 300
    int count;
1897 serge 301
 
302
    while (length) {
3959 Serge 303
	switch (stream->state) {
304
	case WRAP_STATE_WORD:
305
	    count = _word_wrap_stream_count_word_up_to (stream, data, length);
306
	    break;
307
	case WRAP_STATE_HEXSTRING:
308
	    count = _word_wrap_stream_count_hexstring_up_to (stream, data, length);
309
	    break;
310
	case WRAP_STATE_STRING:
311
	    count = _word_wrap_stream_count_string_up_to (stream, data, length);
312
	    break;
313
	case WRAP_STATE_DELIMITER:
314
	    count = 1;
1897 serge 315
	    stream->column++;
3959 Serge 316
	    if (*data == '\n' || stream->column >= stream->max_column) {
1897 serge 317
		_cairo_output_stream_printf (stream->output, "\n");
318
		stream->column = 0;
3959 Serge 319
	    } else if (*data == '<') {
320
		stream->state = WRAP_STATE_HEXSTRING;
321
	    } else if (*data == '(') {
322
		stream->state = WRAP_STATE_STRING;
323
	    } else if (!_cairo_isspace (*data)) {
324
		stream->state = WRAP_STATE_WORD;
1897 serge 325
	    }
3959 Serge 326
	    if (*data != '\n')
327
		_cairo_output_stream_write (stream->output, data, 1);
328
	    break;
329
 
330
	default:
331
	    ASSERT_NOT_REACHED;
332
	    count = length;
333
	    break;
1897 serge 334
	}
3959 Serge 335
	data += count;
336
	length -= count;
1897 serge 337
    }
338
 
339
    return _cairo_output_stream_get_status (stream->output);
340
}
341
 
342
static cairo_status_t
343
_word_wrap_stream_close (cairo_output_stream_t *base)
344
{
345
    word_wrap_stream_t *stream = (word_wrap_stream_t *) base;
346
 
347
    return _cairo_output_stream_get_status (stream->output);
348
}
349
 
350
static cairo_output_stream_t *
351
_word_wrap_stream_create (cairo_output_stream_t *output, int max_column)
352
{
353
    word_wrap_stream_t *stream;
354
 
355
    if (output->status)
356
	return _cairo_output_stream_create_in_error (output->status);
357
 
358
    stream = malloc (sizeof (word_wrap_stream_t));
359
    if (unlikely (stream == NULL)) {
360
	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
361
	return (cairo_output_stream_t *) &_cairo_output_stream_nil;
362
    }
363
 
364
    _cairo_output_stream_init (&stream->base,
365
			       _word_wrap_stream_write,
366
			       NULL,
367
			       _word_wrap_stream_close);
368
    stream->output = output;
369
    stream->max_column = max_column;
370
    stream->column = 0;
3959 Serge 371
    stream->state = WRAP_STATE_DELIMITER;
372
    stream->in_escape = FALSE;
373
    stream->escape_digits = 0;
1897 serge 374
 
375
    return &stream->base;
376
}
377
 
378
typedef struct _pdf_path_info {
379
    cairo_output_stream_t   *output;
380
    cairo_matrix_t	    *path_transform;
381
    cairo_line_cap_t         line_cap;
382
    cairo_point_t            last_move_to_point;
383
    cairo_bool_t             has_sub_path;
384
} pdf_path_info_t;
385
 
386
static cairo_status_t
387
_cairo_pdf_path_move_to (void *closure,
388
			 const cairo_point_t *point)
389
{
390
    pdf_path_info_t *info = closure;
391
    double x = _cairo_fixed_to_double (point->x);
392
    double y = _cairo_fixed_to_double (point->y);
393
 
394
    info->last_move_to_point = *point;
395
    info->has_sub_path = FALSE;
396
    cairo_matrix_transform_point (info->path_transform, &x, &y);
397
    _cairo_output_stream_printf (info->output,
398
				 "%g %g m ", x, y);
399
 
400
    return _cairo_output_stream_get_status (info->output);
401
}
402
 
403
static cairo_status_t
404
_cairo_pdf_path_line_to (void *closure,
405
			 const cairo_point_t *point)
406
{
407
    pdf_path_info_t *info = closure;
408
    double x = _cairo_fixed_to_double (point->x);
409
    double y = _cairo_fixed_to_double (point->y);
410
 
411
    if (info->line_cap != CAIRO_LINE_CAP_ROUND &&
412
	! info->has_sub_path &&
413
	point->x == info->last_move_to_point.x &&
414
	point->y == info->last_move_to_point.y)
415
    {
416
	return CAIRO_STATUS_SUCCESS;
417
    }
418
 
419
    info->has_sub_path = TRUE;
420
    cairo_matrix_transform_point (info->path_transform, &x, &y);
421
    _cairo_output_stream_printf (info->output,
422
				 "%g %g l ", x, y);
423
 
424
    return _cairo_output_stream_get_status (info->output);
425
}
426
 
427
static cairo_status_t
428
_cairo_pdf_path_curve_to (void          *closure,
429
			  const cairo_point_t *b,
430
			  const cairo_point_t *c,
431
			  const cairo_point_t *d)
432
{
433
    pdf_path_info_t *info = closure;
434
    double bx = _cairo_fixed_to_double (b->x);
435
    double by = _cairo_fixed_to_double (b->y);
436
    double cx = _cairo_fixed_to_double (c->x);
437
    double cy = _cairo_fixed_to_double (c->y);
438
    double dx = _cairo_fixed_to_double (d->x);
439
    double dy = _cairo_fixed_to_double (d->y);
440
 
441
    info->has_sub_path = TRUE;
442
    cairo_matrix_transform_point (info->path_transform, &bx, &by);
443
    cairo_matrix_transform_point (info->path_transform, &cx, &cy);
444
    cairo_matrix_transform_point (info->path_transform, &dx, &dy);
445
    _cairo_output_stream_printf (info->output,
446
				 "%g %g %g %g %g %g c ",
447
				 bx, by, cx, cy, dx, dy);
448
    return _cairo_output_stream_get_status (info->output);
449
}
450
 
451
static cairo_status_t
452
_cairo_pdf_path_close_path (void *closure)
453
{
454
    pdf_path_info_t *info = closure;
455
 
456
    if (info->line_cap != CAIRO_LINE_CAP_ROUND &&
457
	! info->has_sub_path)
458
    {
459
	return CAIRO_STATUS_SUCCESS;
460
    }
461
 
462
    _cairo_output_stream_printf (info->output,
463
				 "h\n");
464
 
465
    return _cairo_output_stream_get_status (info->output);
466
}
467
 
468
static cairo_status_t
469
_cairo_pdf_path_rectangle (pdf_path_info_t *info, cairo_box_t *box)
470
{
471
    double x1 = _cairo_fixed_to_double (box->p1.x);
472
    double y1 = _cairo_fixed_to_double (box->p1.y);
473
    double x2 = _cairo_fixed_to_double (box->p2.x);
474
    double y2 = _cairo_fixed_to_double (box->p2.y);
475
 
476
    cairo_matrix_transform_point (info->path_transform, &x1, &y1);
477
    cairo_matrix_transform_point (info->path_transform, &x2, &y2);
478
    _cairo_output_stream_printf (info->output,
479
				 "%g %g %g %g re ",
480
				 x1, y1, x2 - x1, y2 - y1);
481
 
482
    return _cairo_output_stream_get_status (info->output);
483
}
484
 
485
/* The line cap value is needed to workaround the fact that PostScript
486
 * and PDF semantics for stroking degenerate sub-paths do not match
487
 * cairo semantics. (PostScript draws something for any line cap
488
 * value, while cairo draws something only for round caps).
489
 *
490
 * When using this function to emit a path to be filled, rather than
491
 * stroked, simply pass %CAIRO_LINE_CAP_ROUND which will guarantee that
492
 * the stroke workaround will not modify the path being emitted.
493
 */
494
static cairo_status_t
495
_cairo_pdf_operators_emit_path (cairo_pdf_operators_t	*pdf_operators,
3959 Serge 496
				const cairo_path_fixed_t*path,
1897 serge 497
				cairo_matrix_t          *path_transform,
498
				cairo_line_cap_t         line_cap)
499
{
500
    cairo_output_stream_t *word_wrap;
501
    cairo_status_t status, status2;
502
    pdf_path_info_t info;
503
    cairo_box_t box;
504
 
505
    word_wrap = _word_wrap_stream_create (pdf_operators->stream, 72);
506
    status = _cairo_output_stream_get_status (word_wrap);
507
    if (unlikely (status))
508
	return _cairo_output_stream_destroy (word_wrap);
509
 
510
    info.output = word_wrap;
511
    info.path_transform = path_transform;
512
    info.line_cap = line_cap;
513
    if (_cairo_path_fixed_is_rectangle (path, &box)) {
514
	status = _cairo_pdf_path_rectangle (&info, &box);
515
    } else {
516
	status = _cairo_path_fixed_interpret (path,
517
					      _cairo_pdf_path_move_to,
518
					      _cairo_pdf_path_line_to,
519
					      _cairo_pdf_path_curve_to,
520
					      _cairo_pdf_path_close_path,
521
					      &info);
522
    }
523
 
524
    status2 = _cairo_output_stream_destroy (word_wrap);
525
    if (status == CAIRO_STATUS_SUCCESS)
526
	status = status2;
527
 
528
    return status;
529
}
530
 
531
cairo_int_status_t
532
_cairo_pdf_operators_clip (cairo_pdf_operators_t	*pdf_operators,
3959 Serge 533
			   const cairo_path_fixed_t	*path,
1897 serge 534
			   cairo_fill_rule_t		 fill_rule)
535
{
536
    const char *pdf_operator;
537
    cairo_status_t status;
538
 
539
    if (pdf_operators->in_text_object) {
540
	status = _cairo_pdf_operators_end_text (pdf_operators);
541
	if (unlikely (status))
542
	    return status;
543
    }
544
 
545
    if (! path->has_current_point) {
546
	/* construct an empty path */
547
	_cairo_output_stream_printf (pdf_operators->stream, "0 0 m ");
548
    } else {
549
	status = _cairo_pdf_operators_emit_path (pdf_operators,
550
						 path,
551
						 &pdf_operators->cairo_to_pdf,
552
						 CAIRO_LINE_CAP_ROUND);
553
	if (unlikely (status))
554
	    return status;
555
    }
556
 
557
    switch (fill_rule) {
558
    default:
559
	ASSERT_NOT_REACHED;
560
    case CAIRO_FILL_RULE_WINDING:
561
	pdf_operator = "W";
562
	break;
563
    case CAIRO_FILL_RULE_EVEN_ODD:
564
	pdf_operator = "W*";
565
	break;
566
    }
567
 
568
    _cairo_output_stream_printf (pdf_operators->stream,
569
				 "%s n\n",
570
				 pdf_operator);
571
 
572
    return _cairo_output_stream_get_status (pdf_operators->stream);
573
}
574
 
575
static int
576
_cairo_pdf_line_cap (cairo_line_cap_t cap)
577
{
578
    switch (cap) {
579
    case CAIRO_LINE_CAP_BUTT:
580
	return 0;
581
    case CAIRO_LINE_CAP_ROUND:
582
	return 1;
583
    case CAIRO_LINE_CAP_SQUARE:
584
	return 2;
585
    default:
586
	ASSERT_NOT_REACHED;
587
	return 0;
588
    }
589
}
590
 
591
static int
592
_cairo_pdf_line_join (cairo_line_join_t join)
593
{
594
    switch (join) {
595
    case CAIRO_LINE_JOIN_MITER:
596
	return 0;
597
    case CAIRO_LINE_JOIN_ROUND:
598
	return 1;
599
    case CAIRO_LINE_JOIN_BEVEL:
600
	return 2;
601
    default:
602
	ASSERT_NOT_REACHED;
603
	return 0;
604
    }
605
}
606
 
607
cairo_int_status_t
608
_cairo_pdf_operators_emit_stroke_style (cairo_pdf_operators_t		*pdf_operators,
609
					const cairo_stroke_style_t	*style,
610
					double				 scale)
611
{
612
    double *dash = style->dash;
613
    int num_dashes = style->num_dashes;
614
    double dash_offset = style->dash_offset;
615
    double line_width = style->line_width * scale;
616
 
617
    /* PostScript has "special needs" when it comes to zero-length
618
     * dash segments with butt caps. It apparently (at least
619
     * according to ghostscript) draws hairlines for this
620
     * case. That's not what the cairo semantics want, so we first
621
     * touch up the array to eliminate any 0.0 values that will
622
     * result in "on" segments.
623
     */
624
    if (num_dashes && style->line_cap == CAIRO_LINE_CAP_BUTT) {
625
	int i;
626
 
627
	/* If there's an odd number of dash values they will each get
628
	 * interpreted as both on and off. So we first explicitly
629
	 * expand the array to remove the duplicate usage so that we
630
	 * can modify some of the values.
631
	 */
632
	if (num_dashes % 2) {
633
	    dash = _cairo_malloc_abc (num_dashes, 2, sizeof (double));
634
	    if (unlikely (dash == NULL))
635
		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
636
 
637
	    memcpy (dash, style->dash, num_dashes * sizeof (double));
638
	    memcpy (dash + num_dashes, style->dash, num_dashes * sizeof (double));
639
 
640
	    num_dashes *= 2;
641
	}
642
 
643
	for (i = 0; i < num_dashes; i += 2) {
644
	    if (dash[i] == 0.0) {
645
		/* Do not modify the dashes in-place, as we may need to also
646
		 * replay this stroke to an image fallback.
647
		 */
648
		if (dash == style->dash) {
649
		    dash = _cairo_malloc_ab (num_dashes, sizeof (double));
650
		    if (unlikely (dash == NULL))
651
			return _cairo_error (CAIRO_STATUS_NO_MEMORY);
652
		    memcpy (dash, style->dash, num_dashes * sizeof (double));
653
		}
654
 
655
		/* If we're at the front of the list, we first rotate
656
		 * two elements from the end of the list to the front
657
		 * of the list before folding away the 0.0. Or, if
658
		 * there are only two dash elements, then there is
659
		 * nothing at all to draw.
660
		 */
661
		if (i == 0) {
662
		    double last_two[2];
663
 
664
		    if (num_dashes == 2) {
665
			free (dash);
666
			return CAIRO_INT_STATUS_NOTHING_TO_DO;
667
		    }
668
 
669
		    /* The cases of num_dashes == 0, 1, or 3 elements
670
		     * cannot exist, so the rotation of 2 elements
671
		     * will always be safe */
672
		    memcpy (last_two, dash + num_dashes - 2, sizeof (last_two));
673
		    memmove (dash + 2, dash, (num_dashes - 2) * sizeof (double));
674
		    memcpy (dash, last_two, sizeof (last_two));
675
		    dash_offset += dash[0] + dash[1];
676
		    i = 2;
677
		}
678
		dash[i-1] += dash[i+1];
679
		num_dashes -= 2;
680
		memmove (dash + i, dash + i + 2, (num_dashes - i) * sizeof (double));
681
		/* If we might have just rotated, it's possible that
682
		 * we rotated a 0.0 value to the front of the list.
683
		 * Set i to -2 so it will get incremented to 0. */
684
		if (i == 2)
685
		    i = -2;
686
	    }
687
	}
688
    }
689
 
690
    if (!pdf_operators->has_line_style || pdf_operators->line_width != line_width) {
691
	_cairo_output_stream_printf (pdf_operators->stream,
692
				     "%f w\n",
693
				     line_width);
694
	pdf_operators->line_width = line_width;
695
    }
696
 
697
    if (!pdf_operators->has_line_style || pdf_operators->line_cap != style->line_cap) {
698
	_cairo_output_stream_printf (pdf_operators->stream,
699
				     "%d J\n",
700
				     _cairo_pdf_line_cap (style->line_cap));
701
	pdf_operators->line_cap = style->line_cap;
702
    }
703
 
704
    if (!pdf_operators->has_line_style || pdf_operators->line_join != style->line_join) {
705
	_cairo_output_stream_printf (pdf_operators->stream,
706
				     "%d j\n",
707
				     _cairo_pdf_line_join (style->line_join));
708
	pdf_operators->line_join = style->line_join;
709
    }
710
 
711
    if (num_dashes) {
712
	int d;
713
 
714
	_cairo_output_stream_printf (pdf_operators->stream, "[");
715
	for (d = 0; d < num_dashes; d++)
716
	    _cairo_output_stream_printf (pdf_operators->stream, " %f", dash[d] * scale);
717
	_cairo_output_stream_printf (pdf_operators->stream, "] %f d\n",
718
				     dash_offset * scale);
719
	pdf_operators->has_dashes = TRUE;
720
    } else if (!pdf_operators->has_line_style || pdf_operators->has_dashes) {
721
	_cairo_output_stream_printf (pdf_operators->stream, "[] 0.0 d\n");
722
	pdf_operators->has_dashes = FALSE;
723
    }
724
    if (dash != style->dash)
725
        free (dash);
726
 
727
    if (!pdf_operators->has_line_style || pdf_operators->miter_limit != style->miter_limit) {
728
	_cairo_output_stream_printf (pdf_operators->stream,
729
				     "%f M ",
730
				     style->miter_limit < 1.0 ? 1.0 : style->miter_limit);
731
	pdf_operators->miter_limit = style->miter_limit;
732
    }
733
    pdf_operators->has_line_style = TRUE;
734
 
735
    return _cairo_output_stream_get_status (pdf_operators->stream);
736
}
737
 
738
/* Scale the matrix so the largest absolute value of the non
739
 * translation components is 1.0. Return the scale required to restore
740
 * the matrix to the original values.
741
 *
742
 * eg the matrix  [ 100  0  0  50   20   10  ]
743
 *
744
 * is rescaled to [  1   0  0  0.5  0.2  0.1 ]
745
 * and the scale returned is 100
746
 */
747
static void
748
_cairo_matrix_factor_out_scale (cairo_matrix_t *m, double *scale)
749
{
750
    double s;
751
 
752
    s = fabs (m->xx);
753
    if (fabs (m->xy) > s)
754
	s = fabs (m->xy);
755
    if (fabs (m->yx) > s)
756
	s = fabs (m->yx);
757
    if (fabs (m->yy) > s)
758
	s = fabs (m->yy);
759
    *scale = s;
760
    s = 1.0/s;
761
    cairo_matrix_scale (m, s, s);
762
}
763
 
764
static cairo_int_status_t
765
_cairo_pdf_operators_emit_stroke (cairo_pdf_operators_t		*pdf_operators,
3959 Serge 766
				  const cairo_path_fixed_t	*path,
1897 serge 767
				  const cairo_stroke_style_t	*style,
768
				  const cairo_matrix_t		*ctm,
769
				  const cairo_matrix_t		*ctm_inverse,
770
				  const char			*pdf_operator)
771
{
3959 Serge 772
    cairo_int_status_t status;
1897 serge 773
    cairo_matrix_t m, path_transform;
774
    cairo_bool_t has_ctm = TRUE;
775
    double scale = 1.0;
776
 
777
    if (pdf_operators->in_text_object) {
778
	status = _cairo_pdf_operators_end_text (pdf_operators);
779
	if (unlikely (status))
780
	    return status;
781
    }
782
 
783
    /* Optimize away the stroke ctm when it does not affect the
784
     * stroke. There are other ctm cases that could be optimized
785
     * however this is the most common.
786
     */
787
    if (fabs(ctm->xx) == 1.0 && fabs(ctm->yy) == 1.0 &&
788
	fabs(ctm->xy) == 0.0 && fabs(ctm->yx) == 0.0)
789
    {
790
	has_ctm = FALSE;
791
    }
792
 
793
    /* The PDF CTM is transformed to the user space CTM when stroking
794
     * so the corect pen shape will be used. This also requires that
795
     * the path be transformed to user space when emitted. The
796
     * conversion of path coordinates to user space may cause rounding
797
     * errors. For example the device space point (1.234, 3.142) when
798
     * transformed to a user space CTM of [100 0 0 100 0 0] will be
799
     * emitted as (0.012, 0.031).
800
     *
801
     * To avoid the rounding problem we scale the user space CTM
802
     * matrix so that all the non translation components of the matrix
803
     * are <= 1. The line width and and dashes are scaled by the
804
     * inverse of the scale applied to the CTM. This maintains the
805
     * shape of the stroke pen while keeping the user space CTM within
806
     * the range that maximizes the precision of the emitted path.
807
     */
808
    if (has_ctm) {
809
	m = *ctm;
810
	/* Zero out the translation since it does not affect the pen
811
	 * shape however it may cause unnecessary digits to be emitted.
812
	 */
813
	m.x0 = 0.0;
814
	m.y0 = 0.0;
815
	_cairo_matrix_factor_out_scale (&m, &scale);
816
	path_transform = m;
817
	status = cairo_matrix_invert (&path_transform);
818
	if (unlikely (status))
819
	    return status;
820
 
821
	cairo_matrix_multiply (&m, &m, &pdf_operators->cairo_to_pdf);
822
    }
823
 
824
    status = _cairo_pdf_operators_emit_stroke_style (pdf_operators, style, scale);
825
    if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
826
	return CAIRO_STATUS_SUCCESS;
827
    if (unlikely (status))
828
	return status;
829
 
830
    if (has_ctm) {
831
	_cairo_output_stream_printf (pdf_operators->stream,
832
				     "q %f %f %f %f %f %f cm\n",
833
				     m.xx, m.yx, m.xy, m.yy,
834
				     m.x0, m.y0);
835
    } else {
836
	path_transform = pdf_operators->cairo_to_pdf;
837
    }
838
 
839
    status = _cairo_pdf_operators_emit_path (pdf_operators,
840
					     path,
841
					     &path_transform,
842
					     style->line_cap);
843
    if (unlikely (status))
844
	return status;
845
 
846
    _cairo_output_stream_printf (pdf_operators->stream, "%s", pdf_operator);
847
    if (has_ctm)
848
	_cairo_output_stream_printf (pdf_operators->stream, " Q");
849
 
850
    _cairo_output_stream_printf (pdf_operators->stream, "\n");
851
 
852
    return _cairo_output_stream_get_status (pdf_operators->stream);
853
}
854
 
855
cairo_int_status_t
856
_cairo_pdf_operators_stroke (cairo_pdf_operators_t		*pdf_operators,
3959 Serge 857
			     const cairo_path_fixed_t		*path,
1897 serge 858
			     const cairo_stroke_style_t		*style,
859
			     const cairo_matrix_t		*ctm,
860
			     const cairo_matrix_t		*ctm_inverse)
861
{
862
    return _cairo_pdf_operators_emit_stroke (pdf_operators,
863
					     path,
864
					     style,
865
					     ctm,
866
					     ctm_inverse,
867
					     "S");
868
}
869
 
870
cairo_int_status_t
871
_cairo_pdf_operators_fill (cairo_pdf_operators_t	*pdf_operators,
3959 Serge 872
			   const cairo_path_fixed_t	*path,
1897 serge 873
			   cairo_fill_rule_t		fill_rule)
874
{
875
    const char *pdf_operator;
876
    cairo_status_t status;
877
 
878
    if (pdf_operators->in_text_object) {
879
	status = _cairo_pdf_operators_end_text (pdf_operators);
880
	if (unlikely (status))
881
	    return status;
882
    }
883
 
884
    status = _cairo_pdf_operators_emit_path (pdf_operators,
885
					     path,
886
					     &pdf_operators->cairo_to_pdf,
887
					     CAIRO_LINE_CAP_ROUND);
888
    if (unlikely (status))
889
	return status;
890
 
891
    switch (fill_rule) {
892
    default:
893
	ASSERT_NOT_REACHED;
894
    case CAIRO_FILL_RULE_WINDING:
895
	pdf_operator = "f";
896
	break;
897
    case CAIRO_FILL_RULE_EVEN_ODD:
898
	pdf_operator = "f*";
899
	break;
900
    }
901
 
902
    _cairo_output_stream_printf (pdf_operators->stream,
903
				 "%s\n",
904
				 pdf_operator);
905
 
906
    return _cairo_output_stream_get_status (pdf_operators->stream);
907
}
908
 
909
cairo_int_status_t
910
_cairo_pdf_operators_fill_stroke (cairo_pdf_operators_t		*pdf_operators,
3959 Serge 911
				  const cairo_path_fixed_t	*path,
1897 serge 912
				  cairo_fill_rule_t		 fill_rule,
913
				  const cairo_stroke_style_t	*style,
914
				  const cairo_matrix_t		*ctm,
915
				  const cairo_matrix_t		*ctm_inverse)
916
{
917
    const char *operator;
918
 
919
    switch (fill_rule) {
920
    default:
921
	ASSERT_NOT_REACHED;
922
    case CAIRO_FILL_RULE_WINDING:
923
	operator = "B";
924
	break;
925
    case CAIRO_FILL_RULE_EVEN_ODD:
926
	operator = "B*";
927
	break;
928
    }
929
 
930
    return _cairo_pdf_operators_emit_stroke (pdf_operators,
931
					     path,
932
					     style,
933
					     ctm,
934
					     ctm_inverse,
935
					     operator);
936
}
937
 
3959 Serge 938
static void
939
_cairo_pdf_operators_emit_glyph_index (cairo_pdf_operators_t *pdf_operators,
940
				       cairo_output_stream_t *stream,
941
				       unsigned int 	      glyph)
942
{
943
    if (pdf_operators->is_latin) {
944
	if (glyph == '(' || glyph == ')' || glyph == '\\')
945
	    _cairo_output_stream_printf (stream, "\\%c", glyph);
946
	else if (glyph >= 0x20 && glyph <= 0x7e)
947
	    _cairo_output_stream_printf (stream, "%c", glyph);
948
	else
949
	    _cairo_output_stream_printf (stream, "\\%03o", glyph);
950
    } else {
951
	_cairo_output_stream_printf (stream,
952
				     "%0*x",
953
				     pdf_operators->hex_width,
954
				     glyph);
955
    }
956
}
957
 
1897 serge 958
#define GLYPH_POSITION_TOLERANCE 0.001
959
 
960
/* Emit the string of glyphs using the 'Tj' operator. This requires
961
 * that the glyphs are positioned at their natural glyph advances. */
962
static cairo_status_t
963
_cairo_pdf_operators_emit_glyph_string (cairo_pdf_operators_t   *pdf_operators,
964
					cairo_output_stream_t  	*stream)
965
{
966
    int i;
967
 
3959 Serge 968
    _cairo_output_stream_printf (stream, "%s", pdf_operators->is_latin ? "(" : "<");
1897 serge 969
    for (i = 0; i < pdf_operators->num_glyphs; i++) {
3959 Serge 970
	_cairo_pdf_operators_emit_glyph_index (pdf_operators,
971
					       stream,
972
					       pdf_operators->glyphs[i].glyph_index);
1897 serge 973
	pdf_operators->cur_x += pdf_operators->glyphs[i].x_advance;
974
    }
3959 Serge 975
    _cairo_output_stream_printf (stream, "%sTj\n", pdf_operators->is_latin ? ")" : ">");
1897 serge 976
 
977
    return _cairo_output_stream_get_status (stream);
978
}
979
 
980
/* Emit the string of glyphs using the 'TJ' operator.
981
 *
982
 * The TJ operator takes an array of strings of glyphs. Each string of
983
 * glyphs is displayed using the glyph advances of each glyph to
984
 * position the glyphs. A relative adjustment to the glyph advance may
985
 * be specified by including the adjustment between two strings. The
986
 * adjustment is in units of text space * -1000.
987
 */
988
static cairo_status_t
989
_cairo_pdf_operators_emit_glyph_string_with_positioning (
990
    cairo_pdf_operators_t   *pdf_operators,
991
    cairo_output_stream_t   *stream)
992
{
993
    int i;
994
 
3959 Serge 995
    _cairo_output_stream_printf (stream, "[%s", pdf_operators->is_latin ? "(" : "<");
1897 serge 996
    for (i = 0; i < pdf_operators->num_glyphs; i++) {
997
	if (pdf_operators->glyphs[i].x_position != pdf_operators->cur_x)
998
	{
999
	    double delta = pdf_operators->glyphs[i].x_position - pdf_operators->cur_x;
1000
	    int rounded_delta;
1001
 
1002
	    delta = -1000.0*delta;
1003
	    /* As the delta is in 1/1000 of a unit of text space,
1004
	     * rounding to an integer should still provide sufficient
1005
	     * precision. We round the delta before adding to Tm_x so
1006
	     * that we keep track of the accumulated rounding error in
1007
	     * the PDF interpreter and compensate for it when
1008
	     * calculating subsequent deltas.
1009
	     */
1010
	    rounded_delta = _cairo_lround (delta);
3959 Serge 1011
	    if (abs(rounded_delta) < 3)
1012
		rounded_delta = 0;
1897 serge 1013
	    if (rounded_delta != 0) {
3959 Serge 1014
		if (pdf_operators->is_latin) {
1015
		    _cairo_output_stream_printf (stream,
1016
						 ")%d(",
1017
						 rounded_delta);
1018
		} else {
1019
		    _cairo_output_stream_printf (stream,
1020
						 ">%d<",
1021
						 rounded_delta);
1022
		}
1897 serge 1023
	    }
1024
 
1025
	    /* Convert the rounded delta back to text
1026
	     * space before adding to the current text
1027
	     * position. */
1028
	    delta = rounded_delta/-1000.0;
1029
	    pdf_operators->cur_x += delta;
1030
	}
1031
 
3959 Serge 1032
	_cairo_pdf_operators_emit_glyph_index (pdf_operators,
1033
					       stream,
1034
					       pdf_operators->glyphs[i].glyph_index);
1897 serge 1035
	pdf_operators->cur_x += pdf_operators->glyphs[i].x_advance;
1036
    }
3959 Serge 1037
    _cairo_output_stream_printf (stream, "%s]TJ\n", pdf_operators->is_latin ? ")" : ">");
1897 serge 1038
 
1039
    return _cairo_output_stream_get_status (stream);
1040
}
1041
 
1042
static cairo_status_t
1043
_cairo_pdf_operators_flush_glyphs (cairo_pdf_operators_t    *pdf_operators)
1044
{
1045
    cairo_output_stream_t *word_wrap_stream;
1046
    cairo_status_t status, status2;
1047
    int i;
1048
    double x;
1049
 
1050
    if (pdf_operators->num_glyphs == 0)
1051
	return CAIRO_STATUS_SUCCESS;
1052
 
1053
    word_wrap_stream = _word_wrap_stream_create (pdf_operators->stream, 72);
1054
    status = _cairo_output_stream_get_status (word_wrap_stream);
1055
    if (unlikely (status))
1056
	return _cairo_output_stream_destroy (word_wrap_stream);
1057
 
1058
    /* Check if glyph advance used to position every glyph */
1059
    x = pdf_operators->cur_x;
1060
    for (i = 0; i < pdf_operators->num_glyphs; i++) {
1061
	if (fabs(pdf_operators->glyphs[i].x_position - x) > GLYPH_POSITION_TOLERANCE)
1062
	    break;
1063
	x += pdf_operators->glyphs[i].x_advance;
1064
    }
1065
    if (i == pdf_operators->num_glyphs) {
1066
	status = _cairo_pdf_operators_emit_glyph_string (pdf_operators,
1067
							 word_wrap_stream);
1068
    } else {
1069
	status = _cairo_pdf_operators_emit_glyph_string_with_positioning (
1070
	    pdf_operators, word_wrap_stream);
1071
    }
1072
 
1073
    pdf_operators->num_glyphs = 0;
1074
    pdf_operators->glyph_buf_x_pos = pdf_operators->cur_x;
1075
    status2 = _cairo_output_stream_destroy (word_wrap_stream);
1076
    if (status == CAIRO_STATUS_SUCCESS)
1077
	status = status2;
1078
 
1079
    return status;
1080
}
1081
 
1082
static cairo_status_t
1083
_cairo_pdf_operators_add_glyph (cairo_pdf_operators_t             *pdf_operators,
1084
				cairo_scaled_font_subsets_glyph_t *glyph,
1085
				double 			           x_position)
1086
{
1087
    double x, y;
1088
 
1089
    x = glyph->x_advance;
1090
    y = glyph->y_advance;
1091
    if (glyph->is_scaled)
1092
	cairo_matrix_transform_distance (&pdf_operators->font_matrix_inverse, &x, &y);
1093
 
1094
    pdf_operators->glyphs[pdf_operators->num_glyphs].x_position = x_position;
1095
    pdf_operators->glyphs[pdf_operators->num_glyphs].glyph_index = glyph->subset_glyph_index;
1096
    pdf_operators->glyphs[pdf_operators->num_glyphs].x_advance = x;
1097
    pdf_operators->glyph_buf_x_pos += x;
1098
    pdf_operators->num_glyphs++;
1099
    if (pdf_operators->num_glyphs == PDF_GLYPH_BUFFER_SIZE)
1100
	return _cairo_pdf_operators_flush_glyphs (pdf_operators);
1101
 
1102
    return CAIRO_STATUS_SUCCESS;
1103
}
1104
 
1105
/* Use 'Tm' operator to set the PDF text matrix. */
1106
static cairo_status_t
1107
_cairo_pdf_operators_set_text_matrix (cairo_pdf_operators_t  *pdf_operators,
1108
				      cairo_matrix_t         *matrix)
1109
{
1110
    cairo_matrix_t inverse;
1111
    cairo_status_t status;
1112
 
1113
    /* We require the matrix to be invertable. */
1114
    inverse = *matrix;
1115
    status = cairo_matrix_invert (&inverse);
1116
    if (unlikely (status))
1117
	return status;
1118
 
1119
    pdf_operators->text_matrix = *matrix;
1120
    pdf_operators->cur_x = 0;
1121
    pdf_operators->cur_y = 0;
1122
    pdf_operators->glyph_buf_x_pos = 0;
1123
    _cairo_output_stream_printf (pdf_operators->stream,
1124
				 "%f %f %f %f %f %f Tm\n",
1125
				 pdf_operators->text_matrix.xx,
1126
				 pdf_operators->text_matrix.yx,
1127
				 pdf_operators->text_matrix.xy,
1128
				 pdf_operators->text_matrix.yy,
1129
				 pdf_operators->text_matrix.x0,
1130
				 pdf_operators->text_matrix.y0);
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
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
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;
3959 Serge 1212
    pdf_operators->is_latin = subset_glyph->is_latin;
1897 serge 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
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
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
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
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 
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
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
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 becauses 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
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
    cur_glyph = glyphs;
1420
    /* XXX
1421
     * If no glyphs, we should put *something* here for the text to be selectable. */
1422
    for (i = 0; i < num_glyphs; i++) {
1423
	status = _cairo_scaled_font_subsets_map_glyph (pdf_operators->font_subsets,
1424
						       scaled_font,
1425
						       cur_glyph->index,
1426
						       NULL, -1,
1427
						       &subset_glyph);
1428
	if (unlikely (status))
1429
	    return status;
1430
 
1431
	status = _cairo_pdf_operators_emit_glyph (pdf_operators,
1432
						  cur_glyph,
1433
						  &subset_glyph);
1434
	if (unlikely (status))
1435
	    return status;
1436
 
1437
	if ((cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD))
1438
	    cur_glyph--;
1439
	else
1440
	    cur_glyph++;
1441
    }
1442
 
1443
    if (pdf_operators->use_actual_text) {
1444
	status = _cairo_pdf_operators_flush_glyphs (pdf_operators);
1445
	if (unlikely (status))
1446
	    return status;
1447
 
1448
	status = _cairo_pdf_operators_end_actualtext (pdf_operators);
1449
    }
1450
 
1451
    return status;
1452
}
1453
 
1454
cairo_int_status_t
1455
_cairo_pdf_operators_show_text_glyphs (cairo_pdf_operators_t	  *pdf_operators,
1456
				       const char                 *utf8,
1457
				       int                         utf8_len,
1458
				       cairo_glyph_t              *glyphs,
1459
				       int                         num_glyphs,
1460
				       const cairo_text_cluster_t *clusters,
1461
				       int                         num_clusters,
1462
				       cairo_text_cluster_flags_t  cluster_flags,
1463
				       cairo_scaled_font_t	  *scaled_font)
1464
{
1465
    cairo_status_t status;
1466
    int i;
1467
    cairo_matrix_t text_matrix, invert_y_axis;
1468
    double x, y;
1469
    const char *cur_text;
1470
    cairo_glyph_t *cur_glyph;
1471
 
1472
    pdf_operators->font_matrix_inverse = scaled_font->font_matrix;
1473
    status = cairo_matrix_invert (&pdf_operators->font_matrix_inverse);
1474
    if (status == CAIRO_STATUS_INVALID_MATRIX)
1475
	return CAIRO_STATUS_SUCCESS;
1476
    assert (status == CAIRO_STATUS_SUCCESS);
1477
 
1478
    pdf_operators->is_new_text_object = FALSE;
1479
    if (pdf_operators->in_text_object == FALSE) {
1480
	status = _cairo_pdf_operators_begin_text (pdf_operators);
1481
	if (unlikely (status))
1482
	    return status;
1483
 
1484
	/* Force Tm and Tf to be emitted when starting a new text
1485
	 * object.*/
1486
	pdf_operators->is_new_text_object = TRUE;
1487
    }
1488
 
1489
    cairo_matrix_init_scale (&invert_y_axis, 1, -1);
1490
    text_matrix = scaled_font->scale;
1491
 
1492
    /* Invert y axis in font space  */
1493
    cairo_matrix_multiply (&text_matrix, &text_matrix, &invert_y_axis);
1494
 
1495
    /* Invert y axis in device space  */
1496
    cairo_matrix_multiply (&text_matrix, &invert_y_axis, &text_matrix);
1497
 
1498
    if (pdf_operators->is_new_text_object ||
1499
	! _cairo_matrix_scale_equal (&pdf_operators->text_matrix, &text_matrix))
1500
    {
1501
	status = _cairo_pdf_operators_flush_glyphs (pdf_operators);
1502
	if (unlikely (status))
1503
	    return status;
1504
 
1505
	x = glyphs[0].x;
1506
	y = glyphs[0].y;
1507
	cairo_matrix_transform_point (&pdf_operators->cairo_to_pdf, &x, &y);
1508
	text_matrix.x0 = x;
1509
	text_matrix.y0 = y;
1510
	status = _cairo_pdf_operators_set_text_matrix (pdf_operators, &text_matrix);
1511
	if (status == CAIRO_STATUS_INVALID_MATRIX)
1512
	    return CAIRO_STATUS_SUCCESS;
1513
	if (unlikely (status))
1514
	    return status;
1515
    }
1516
 
1517
    if (num_clusters > 0) {
1518
	cur_text = utf8;
1519
	if ((cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD))
1520
	    cur_glyph = glyphs + num_glyphs;
1521
	else
1522
	    cur_glyph = glyphs;
1523
	for (i = 0; i < num_clusters; i++) {
1524
	    if ((cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD))
1525
		cur_glyph -= clusters[i].num_glyphs;
1526
	    status = _cairo_pdf_operators_emit_cluster (pdf_operators,
1527
							cur_text,
1528
							clusters[i].num_bytes,
1529
							cur_glyph,
1530
							clusters[i].num_glyphs,
1531
							cluster_flags,
1532
							scaled_font);
1533
	    if (unlikely (status))
1534
		return status;
1535
 
1536
	    cur_text += clusters[i].num_bytes;
1537
	    if (!(cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD))
1538
		cur_glyph += clusters[i].num_glyphs;
1539
	}
1540
    } else {
1541
	for (i = 0; i < num_glyphs; i++) {
1542
	    status = _cairo_pdf_operators_emit_cluster (pdf_operators,
1543
							NULL,
1544
							-1, /* no unicode string available */
1545
							&glyphs[i],
1546
							1,
1547
							FALSE,
1548
							scaled_font);
1549
	    if (unlikely (status))
1550
		return status;
1551
	}
1552
    }
1553
 
1554
    return _cairo_output_stream_get_status (pdf_operators->stream);
1555
}
1556
 
1557
#endif /* CAIRO_HAS_PDF_OPERATORS */