1 /* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
2 /* cairo - a vector graphics library with display and print output
4 * Copyright © 2008 Adrian Johnson
6 * This library is free software; you can redistribute it and/or
7 * modify it either under the terms of the GNU Lesser General Public
8 * License version 2.1 as published by the Free Software Foundation
9 * (the "LGPL") or, at your option, under the terms of the Mozilla
10 * Public License Version 1.1 (the "MPL"). If you do not alter this
11 * notice, a recipient may use your version of this file under either
12 * the MPL or the LGPL.
14 * You should have received a copy of the LGPL along with this library
15 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
17 * You should have received a copy of the MPL along with this library
18 * in the file COPYING-MPL-1.1
20 * The contents of this file are subject to the Mozilla Public License
21 * Version 1.1 (the "License"); you may not use this file except in
22 * compliance with the License. You may obtain a copy of the License at
23 * http://www.mozilla.org/MPL/
25 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
26 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
27 * the specific language governing rights and limitations.
29 * The Original Code is the cairo graphics library.
31 * The Initial Developer of the Original Code is Adrian Johnson.
34 * Adrian Johnson <ajohnson@redneon.com>
39 #if CAIRO_HAS_FONT_SUBSET
41 #include "cairo-type3-glyph-surface-private.h"
42 #include "cairo-output-stream-private.h"
43 #include "cairo-recording-surface-private.h"
44 #include "cairo-analysis-surface-private.h"
45 #include "cairo-default-context-private.h"
46 #include "cairo-error-private.h"
47 #include "cairo-image-surface-private.h"
48 #include "cairo-surface-clipper-private.h"
50 static const cairo_surface_backend_t cairo_type3_glyph_surface_backend
;
53 _cairo_type3_glyph_surface_clipper_intersect_clip_path (cairo_surface_clipper_t
*clipper
,
54 cairo_path_fixed_t
*path
,
55 cairo_fill_rule_t fill_rule
,
57 cairo_antialias_t antialias
)
59 cairo_type3_glyph_surface_t
*surface
= cairo_container_of (clipper
,
60 cairo_type3_glyph_surface_t
,
64 _cairo_output_stream_printf (surface
->stream
, "Q q\n");
65 return CAIRO_STATUS_SUCCESS
;
68 return _cairo_pdf_operators_clip (&surface
->pdf_operators
,
74 _cairo_type3_glyph_surface_create (cairo_scaled_font_t
*scaled_font
,
75 cairo_output_stream_t
*stream
,
76 cairo_type3_glyph_surface_emit_image_t emit_image
,
77 cairo_scaled_font_subsets_t
*font_subsets
,
80 cairo_type3_glyph_surface_t
*surface
;
81 cairo_matrix_t invert_y_axis
;
83 if (unlikely (stream
!= NULL
&& stream
->status
))
84 return _cairo_surface_create_in_error (stream
->status
);
86 surface
= malloc (sizeof (cairo_type3_glyph_surface_t
));
87 if (unlikely (surface
== NULL
))
88 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY
));
90 _cairo_surface_init (&surface
->base
,
91 &cairo_type3_glyph_surface_backend
,
93 CAIRO_CONTENT_COLOR_ALPHA
);
95 surface
->scaled_font
= scaled_font
;
96 surface
->stream
= stream
;
97 surface
->emit_image
= emit_image
;
99 /* Setup the transform from the user-font device space to Type 3
100 * font space. The Type 3 font space is defined by the FontMatrix
101 * entry in the Type 3 dictionary. In the PDF backend this is an
102 * identity matrix. */
103 surface
->cairo_to_pdf
= scaled_font
->scale_inverse
;
104 cairo_matrix_init_scale (&invert_y_axis
, 1, -1);
105 cairo_matrix_multiply (&surface
->cairo_to_pdf
, &surface
->cairo_to_pdf
, &invert_y_axis
);
107 _cairo_pdf_operators_init (&surface
->pdf_operators
,
109 &surface
->cairo_to_pdf
,
113 _cairo_surface_clipper_init (&surface
->clipper
,
114 _cairo_type3_glyph_surface_clipper_intersect_clip_path
);
116 return &surface
->base
;
119 static cairo_status_t
120 _cairo_type3_glyph_surface_emit_image (cairo_type3_glyph_surface_t
*surface
,
121 cairo_image_surface_t
*image
,
122 cairo_matrix_t
*image_matrix
)
124 cairo_status_t status
;
126 /* The only image type supported by Type 3 fonts are 1-bit masks */
127 image
= _cairo_image_surface_coerce_to_format (image
, CAIRO_FORMAT_A1
);
128 status
= image
->base
.status
;
129 if (unlikely (status
))
132 _cairo_output_stream_printf (surface
->stream
,
133 "q %f %f %f %f %f %f cm\n",
141 status
= surface
->emit_image (image
, surface
->stream
);
142 cairo_surface_destroy (&image
->base
);
144 _cairo_output_stream_printf (surface
->stream
,
150 static cairo_status_t
151 _cairo_type3_glyph_surface_emit_image_pattern (cairo_type3_glyph_surface_t
*surface
,
152 cairo_image_surface_t
*image
,
153 const cairo_matrix_t
*pattern_matrix
)
155 cairo_matrix_t mat
, upside_down
;
156 cairo_status_t status
;
158 if (image
->width
== 0 || image
->height
== 0)
159 return CAIRO_STATUS_SUCCESS
;
161 mat
= *pattern_matrix
;
163 /* Get the pattern space to user space matrix */
164 status
= cairo_matrix_invert (&mat
);
166 /* cairo_pattern_set_matrix ensures the matrix is invertible */
167 assert (status
== CAIRO_STATUS_SUCCESS
);
169 /* Make this a pattern space to Type 3 font space matrix */
170 cairo_matrix_multiply (&mat
, &mat
, &surface
->cairo_to_pdf
);
172 /* PDF images are in a 1 unit by 1 unit image space. Turn the 1 by
173 * 1 image upside down to convert to flip the Y-axis going from
174 * cairo to PDF. Then scale the image up to the required size. */
175 cairo_matrix_scale (&mat
, image
->width
, image
->height
);
176 cairo_matrix_init (&upside_down
, 1, 0, 0, -1, 0, 1);
177 cairo_matrix_multiply (&mat
, &upside_down
, &mat
);
179 return _cairo_type3_glyph_surface_emit_image (surface
, image
, &mat
);
182 static cairo_status_t
183 _cairo_type3_glyph_surface_finish (void *abstract_surface
)
185 cairo_type3_glyph_surface_t
*surface
= abstract_surface
;
187 return _cairo_pdf_operators_fini (&surface
->pdf_operators
);
190 static cairo_int_status_t
191 _cairo_type3_glyph_surface_paint (void *abstract_surface
,
193 const cairo_pattern_t
*source
,
194 const cairo_clip_t
*clip
)
196 cairo_type3_glyph_surface_t
*surface
= abstract_surface
;
197 const cairo_surface_pattern_t
*pattern
;
198 cairo_image_surface_t
*image
;
200 cairo_status_t status
;
202 if (source
->type
!= CAIRO_PATTERN_TYPE_SURFACE
)
203 return CAIRO_INT_STATUS_IMAGE_FALLBACK
;
205 status
= _cairo_surface_clipper_set_clip (&surface
->clipper
, clip
);
206 if (unlikely (status
))
209 pattern
= (const cairo_surface_pattern_t
*) source
;
210 status
= _cairo_surface_acquire_source_image (pattern
->surface
,
211 &image
, &image_extra
);
212 if (unlikely (status
))
215 status
= _cairo_type3_glyph_surface_emit_image_pattern (surface
,
217 &pattern
->base
.matrix
);
220 _cairo_surface_release_source_image (pattern
->surface
, image
, image_extra
);
225 static cairo_int_status_t
226 _cairo_type3_glyph_surface_mask (void *abstract_surface
,
228 const cairo_pattern_t
*source
,
229 const cairo_pattern_t
*mask
,
230 const cairo_clip_t
*clip
)
232 return _cairo_type3_glyph_surface_paint (abstract_surface
,
237 static cairo_int_status_t
238 _cairo_type3_glyph_surface_stroke (void *abstract_surface
,
240 const cairo_pattern_t
*source
,
241 const cairo_path_fixed_t
*path
,
242 const cairo_stroke_style_t
*style
,
243 const cairo_matrix_t
*ctm
,
244 const cairo_matrix_t
*ctm_inverse
,
246 cairo_antialias_t antialias
,
247 const cairo_clip_t
*clip
)
249 cairo_type3_glyph_surface_t
*surface
= abstract_surface
;
250 cairo_int_status_t status
;
252 status
= _cairo_surface_clipper_set_clip (&surface
->clipper
, clip
);
253 if (unlikely (status
))
256 return _cairo_pdf_operators_stroke (&surface
->pdf_operators
,
263 static cairo_int_status_t
264 _cairo_type3_glyph_surface_fill (void *abstract_surface
,
266 const cairo_pattern_t
*source
,
267 const cairo_path_fixed_t
*path
,
268 cairo_fill_rule_t fill_rule
,
270 cairo_antialias_t antialias
,
271 const cairo_clip_t
*clip
)
273 cairo_type3_glyph_surface_t
*surface
= abstract_surface
;
274 cairo_int_status_t status
;
276 status
= _cairo_surface_clipper_set_clip (&surface
->clipper
, clip
);
277 if (unlikely (status
))
280 return _cairo_pdf_operators_fill (&surface
->pdf_operators
,
285 static cairo_int_status_t
286 _cairo_type3_glyph_surface_show_glyphs (void *abstract_surface
,
288 const cairo_pattern_t
*source
,
289 cairo_glyph_t
*glyphs
,
291 cairo_scaled_font_t
*scaled_font
,
292 const cairo_clip_t
*clip
)
294 cairo_type3_glyph_surface_t
*surface
= abstract_surface
;
295 cairo_int_status_t status
;
296 cairo_scaled_font_t
*font
;
297 cairo_matrix_t new_ctm
, invert_y_axis
;
299 status
= _cairo_surface_clipper_set_clip (&surface
->clipper
, clip
);
300 if (unlikely (status
))
303 cairo_matrix_init_scale (&invert_y_axis
, 1, -1);
304 cairo_matrix_multiply (&new_ctm
, &invert_y_axis
, &scaled_font
->ctm
);
305 cairo_matrix_multiply (&new_ctm
, &surface
->cairo_to_pdf
, &new_ctm
);
306 font
= cairo_scaled_font_create (scaled_font
->font_face
,
307 &scaled_font
->font_matrix
,
309 &scaled_font
->options
);
310 if (unlikely (font
->status
))
313 status
= _cairo_pdf_operators_show_text_glyphs (&surface
->pdf_operators
,
320 cairo_scaled_font_destroy (font
);
325 static const cairo_surface_backend_t cairo_type3_glyph_surface_backend
= {
326 CAIRO_INTERNAL_SURFACE_TYPE_TYPE3_GLYPH
,
327 _cairo_type3_glyph_surface_finish
,
329 _cairo_default_context_create
, /* XXX usable through a context? */
331 NULL
, /* create similar */
332 NULL
, /* create similar image */
333 NULL
, /* map to image */
334 NULL
, /* unmap image */
337 NULL
, /* acquire_source_image */
338 NULL
, /* release_source_image */
341 NULL
, /* copy page */
342 NULL
, /* show page */
344 NULL
, /* _cairo_type3_glyph_surface_get_extents */
345 NULL
, /* _cairo_type3_glyph_surface_get_font_options */
348 NULL
, /* mark_dirty_rectangle */
350 _cairo_type3_glyph_surface_paint
,
351 _cairo_type3_glyph_surface_mask
,
352 _cairo_type3_glyph_surface_stroke
,
353 _cairo_type3_glyph_surface_fill
,
354 NULL
, /* fill-stroke */
355 _cairo_type3_glyph_surface_show_glyphs
,
359 _cairo_type3_glyph_surface_set_stream (cairo_type3_glyph_surface_t
*surface
,
360 cairo_output_stream_t
*stream
)
362 surface
->stream
= stream
;
363 _cairo_pdf_operators_set_stream (&surface
->pdf_operators
, stream
);
366 static cairo_status_t
367 _cairo_type3_glyph_surface_emit_fallback_image (cairo_type3_glyph_surface_t
*surface
,
368 unsigned long glyph_index
)
370 cairo_scaled_glyph_t
*scaled_glyph
;
371 cairo_status_t status
;
372 cairo_image_surface_t
*image
;
376 status
= _cairo_scaled_glyph_lookup (surface
->scaled_font
,
378 CAIRO_SCALED_GLYPH_INFO_METRICS
|
379 CAIRO_SCALED_GLYPH_INFO_SURFACE
,
381 if (unlikely (status
))
384 image
= scaled_glyph
->surface
;
385 if (image
->width
== 0 || image
->height
== 0)
386 return CAIRO_STATUS_SUCCESS
;
388 x
= _cairo_fixed_to_double (scaled_glyph
->bbox
.p1
.x
);
389 y
= _cairo_fixed_to_double (scaled_glyph
->bbox
.p2
.y
);
390 mat
.xx
= image
->width
;
393 mat
.yy
= image
->height
;
396 cairo_matrix_multiply (&mat
, &mat
, &surface
->scaled_font
->scale_inverse
);
399 return _cairo_type3_glyph_surface_emit_image (surface
, image
, &mat
);
403 _cairo_type3_glyph_surface_set_font_subsets_callback (void *abstract_surface
,
404 cairo_pdf_operators_use_font_subset_t use_font_subset
,
407 cairo_type3_glyph_surface_t
*surface
= abstract_surface
;
409 if (unlikely (surface
->base
.status
))
412 _cairo_pdf_operators_set_font_subsets_callback (&surface
->pdf_operators
,
418 _cairo_type3_glyph_surface_analyze_glyph (void *abstract_surface
,
419 unsigned long glyph_index
)
421 cairo_type3_glyph_surface_t
*surface
= abstract_surface
;
422 cairo_scaled_glyph_t
*scaled_glyph
;
423 cairo_int_status_t status
, status2
;
424 cairo_output_stream_t
*null_stream
;
426 if (unlikely (surface
->base
.status
))
427 return surface
->base
.status
;
429 null_stream
= _cairo_null_stream_create ();
430 if (unlikely (null_stream
->status
))
431 return null_stream
->status
;
433 _cairo_type3_glyph_surface_set_stream (surface
, null_stream
);
435 _cairo_scaled_font_freeze_cache (surface
->scaled_font
);
436 status
= _cairo_scaled_glyph_lookup (surface
->scaled_font
,
438 CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE
,
441 if (_cairo_int_status_is_error (status
))
444 if (status
== CAIRO_INT_STATUS_UNSUPPORTED
) {
445 status
= CAIRO_INT_STATUS_SUCCESS
;
449 status
= _cairo_recording_surface_replay (scaled_glyph
->recording_surface
,
451 if (unlikely (status
))
454 status
= _cairo_pdf_operators_flush (&surface
->pdf_operators
);
455 if (status
== CAIRO_INT_STATUS_IMAGE_FALLBACK
)
456 status
= CAIRO_INT_STATUS_SUCCESS
;
459 _cairo_scaled_font_thaw_cache (surface
->scaled_font
);
461 status2
= _cairo_output_stream_destroy (null_stream
);
462 if (status
== CAIRO_INT_STATUS_SUCCESS
)
469 _cairo_type3_glyph_surface_emit_glyph (void *abstract_surface
,
470 cairo_output_stream_t
*stream
,
471 unsigned long glyph_index
,
475 cairo_type3_glyph_surface_t
*surface
= abstract_surface
;
476 cairo_scaled_glyph_t
*scaled_glyph
;
477 cairo_int_status_t status
, status2
;
478 double x_advance
, y_advance
;
479 cairo_matrix_t font_matrix_inverse
;
481 if (unlikely (surface
->base
.status
))
482 return surface
->base
.status
;
484 _cairo_type3_glyph_surface_set_stream (surface
, stream
);
486 _cairo_scaled_font_freeze_cache (surface
->scaled_font
);
487 status
= _cairo_scaled_glyph_lookup (surface
->scaled_font
,
489 CAIRO_SCALED_GLYPH_INFO_METRICS
|
490 CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE
,
492 if (status
== CAIRO_INT_STATUS_UNSUPPORTED
) {
493 status
= _cairo_scaled_glyph_lookup (surface
->scaled_font
,
495 CAIRO_SCALED_GLYPH_INFO_METRICS
,
497 if (status
== CAIRO_INT_STATUS_SUCCESS
)
498 status
= CAIRO_INT_STATUS_IMAGE_FALLBACK
;
500 if (_cairo_int_status_is_error (status
)) {
501 _cairo_scaled_font_thaw_cache (surface
->scaled_font
);
505 x_advance
= scaled_glyph
->metrics
.x_advance
;
506 y_advance
= scaled_glyph
->metrics
.y_advance
;
507 font_matrix_inverse
= surface
->scaled_font
->font_matrix
;
508 status2
= cairo_matrix_invert (&font_matrix_inverse
);
510 /* The invertability of font_matrix is tested in
511 * pdf_operators_show_glyphs before any glyphs are mapped to the
513 assert (status2
== CAIRO_INT_STATUS_SUCCESS
);
515 cairo_matrix_transform_distance (&font_matrix_inverse
, &x_advance
, &y_advance
);
518 *bbox
= scaled_glyph
->bbox
;
519 _cairo_matrix_transform_bounding_box_fixed (&surface
->scaled_font
->scale_inverse
,
522 _cairo_output_stream_printf (surface
->stream
,
523 "%f 0 %f %f %f %f d1\n",
525 _cairo_fixed_to_double (bbox
->p1
.x
),
526 - _cairo_fixed_to_double (bbox
->p2
.y
),
527 _cairo_fixed_to_double (bbox
->p2
.x
),
528 - _cairo_fixed_to_double (bbox
->p1
.y
));
530 if (status
== CAIRO_INT_STATUS_SUCCESS
) {
531 cairo_output_stream_t
*mem_stream
;
533 mem_stream
= _cairo_memory_stream_create ();
534 status
= mem_stream
->status
;
535 if (unlikely (status
))
538 _cairo_type3_glyph_surface_set_stream (surface
, mem_stream
);
540 _cairo_output_stream_printf (surface
->stream
, "q\n");
541 status
= _cairo_recording_surface_replay (scaled_glyph
->recording_surface
,
544 status2
= _cairo_pdf_operators_flush (&surface
->pdf_operators
);
545 if (status
== CAIRO_INT_STATUS_SUCCESS
)
548 _cairo_output_stream_printf (surface
->stream
, "Q\n");
550 _cairo_type3_glyph_surface_set_stream (surface
, stream
);
551 if (status
== CAIRO_INT_STATUS_SUCCESS
)
552 _cairo_memory_stream_copy (mem_stream
, stream
);
554 status2
= _cairo_output_stream_destroy (mem_stream
);
555 if (status
== CAIRO_INT_STATUS_SUCCESS
)
559 if (status
== CAIRO_INT_STATUS_IMAGE_FALLBACK
)
560 status
= _cairo_type3_glyph_surface_emit_fallback_image (surface
, glyph_index
);
563 _cairo_scaled_font_thaw_cache (surface
->scaled_font
);
568 #endif /* CAIRO_HAS_FONT_SUBSET */