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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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-meta-surface-private.h"
44 #include "cairo-analysis-surface-private.h"
46 static const cairo_surface_backend_t cairo_type3_glyph_surface_backend
;
49 _cairo_type3_glyph_surface_create (cairo_scaled_font_t
*scaled_font
,
50 cairo_output_stream_t
*stream
,
51 cairo_type3_glyph_surface_emit_image_t emit_image
,
52 cairo_scaled_font_subsets_t
*font_subsets
)
54 cairo_type3_glyph_surface_t
*surface
;
55 cairo_matrix_t invert_y_axis
;
57 if (unlikely (stream
!= NULL
&& stream
->status
))
58 return _cairo_surface_create_in_error (stream
->status
);
60 surface
= malloc (sizeof (cairo_type3_glyph_surface_t
));
61 if (unlikely (surface
== NULL
))
62 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY
));
64 _cairo_surface_init (&surface
->base
, &cairo_type3_glyph_surface_backend
,
65 CAIRO_CONTENT_COLOR_ALPHA
);
67 surface
->scaled_font
= scaled_font
;
68 surface
->stream
= stream
;
69 surface
->emit_image
= emit_image
;
71 /* Setup the transform from the user-font device space to Type 3
72 * font space. The Type 3 font space is defined by the FontMatrix
73 * entry in the Type 3 dictionary. In the PDF backend this is an
75 surface
->cairo_to_pdf
= scaled_font
->scale_inverse
;
76 cairo_matrix_init_scale (&invert_y_axis
, 1, -1);
77 cairo_matrix_multiply (&surface
->cairo_to_pdf
, &surface
->cairo_to_pdf
, &invert_y_axis
);
79 _cairo_pdf_operators_init (&surface
->pdf_operators
,
81 &surface
->cairo_to_pdf
,
84 return &surface
->base
;
88 _cairo_type3_glyph_surface_emit_image (cairo_type3_glyph_surface_t
*surface
,
89 cairo_image_surface_t
*image
,
90 cairo_matrix_t
*image_matrix
)
92 cairo_status_t status
;
94 /* The only image type supported by Type 3 fonts are 1-bit masks */
95 image
= _cairo_image_surface_coerce (image
, CAIRO_FORMAT_A1
);
96 status
= image
->base
.status
;
97 if (unlikely (status
))
100 _cairo_output_stream_printf (surface
->stream
,
101 "q %f %f %f %f %f %f cm\n",
109 status
= surface
->emit_image (image
, surface
->stream
);
110 cairo_surface_destroy (&image
->base
);
112 _cairo_output_stream_printf (surface
->stream
,
118 static cairo_status_t
119 _cairo_type3_glyph_surface_emit_image_pattern (cairo_type3_glyph_surface_t
*surface
,
120 cairo_image_surface_t
*image
,
121 const cairo_matrix_t
*pattern_matrix
)
123 cairo_matrix_t mat
, upside_down
;
124 cairo_status_t status
;
126 if (image
->width
== 0 || image
->height
== 0)
127 return CAIRO_STATUS_SUCCESS
;
129 mat
= *pattern_matrix
;
131 /* Get the pattern space to user space matrix */
132 status
= cairo_matrix_invert (&mat
);
134 /* cairo_pattern_set_matrix ensures the matrix is invertible */
135 assert (status
== CAIRO_STATUS_SUCCESS
);
137 /* Make this a pattern space to Type 3 font space matrix */
138 cairo_matrix_multiply (&mat
, &mat
, &surface
->cairo_to_pdf
);
140 /* PDF images are in a 1 unit by 1 unit image space. Turn the 1 by
141 * 1 image upside down to convert to flip the Y-axis going from
142 * cairo to PDF. Then scale the image up to the required size. */
143 cairo_matrix_scale (&mat
, image
->width
, image
->height
);
144 cairo_matrix_init (&upside_down
, 1, 0, 0, -1, 0, 1);
145 cairo_matrix_multiply (&mat
, &upside_down
, &mat
);
147 return _cairo_type3_glyph_surface_emit_image (surface
, image
, &mat
);
150 static cairo_status_t
151 _cairo_type3_glyph_surface_finish (void *abstract_surface
)
153 cairo_type3_glyph_surface_t
*surface
= abstract_surface
;
155 return _cairo_pdf_operators_fini (&surface
->pdf_operators
);
158 static cairo_int_status_t
159 _cairo_type3_glyph_surface_intersect_clip_path (void *abstract_surface
,
160 cairo_path_fixed_t
*path
,
161 cairo_fill_rule_t fill_rule
,
163 cairo_antialias_t antialias
)
165 cairo_type3_glyph_surface_t
*surface
= abstract_surface
;
168 _cairo_output_stream_printf (surface
->stream
, "Q q\n");
169 return CAIRO_STATUS_SUCCESS
;
172 return _cairo_pdf_operators_clip (&surface
->pdf_operators
,
177 static cairo_int_status_t
178 _cairo_type3_glyph_surface_paint (void *abstract_surface
,
180 const cairo_pattern_t
*source
,
181 cairo_rectangle_int_t
*extents
)
183 cairo_type3_glyph_surface_t
*surface
= abstract_surface
;
184 const cairo_surface_pattern_t
*pattern
;
185 cairo_image_surface_t
*image
;
187 cairo_status_t status
;
189 if (source
->type
!= CAIRO_PATTERN_TYPE_SURFACE
)
190 return CAIRO_INT_STATUS_IMAGE_FALLBACK
;
192 pattern
= (const cairo_surface_pattern_t
*) source
;
193 status
= _cairo_surface_acquire_source_image (pattern
->surface
, &image
, &image_extra
);
194 if (unlikely (status
))
197 status
= _cairo_type3_glyph_surface_emit_image_pattern (surface
,
199 &pattern
->base
.matrix
);
202 _cairo_surface_release_source_image (pattern
->surface
, image
, image_extra
);
207 static cairo_int_status_t
208 _cairo_type3_glyph_surface_mask (void *abstract_surface
,
210 const cairo_pattern_t
*source
,
211 const cairo_pattern_t
*mask
,
212 cairo_rectangle_int_t
*extents
)
214 return _cairo_type3_glyph_surface_paint (abstract_surface
, op
, mask
, extents
);
217 static cairo_int_status_t
218 _cairo_type3_glyph_surface_stroke (void *abstract_surface
,
220 const cairo_pattern_t
*source
,
221 cairo_path_fixed_t
*path
,
222 cairo_stroke_style_t
*style
,
224 cairo_matrix_t
*ctm_inverse
,
226 cairo_antialias_t antialias
,
227 cairo_rectangle_int_t
*extents
)
229 cairo_type3_glyph_surface_t
*surface
= abstract_surface
;
231 return _cairo_pdf_operators_stroke (&surface
->pdf_operators
,
238 static cairo_int_status_t
239 _cairo_type3_glyph_surface_fill (void *abstract_surface
,
241 const cairo_pattern_t
*source
,
242 cairo_path_fixed_t
*path
,
243 cairo_fill_rule_t fill_rule
,
245 cairo_antialias_t antialias
,
246 cairo_rectangle_int_t
*extents
)
248 cairo_type3_glyph_surface_t
*surface
= abstract_surface
;
249 cairo_int_status_t status
;
251 status
= _cairo_pdf_operators_fill (&surface
->pdf_operators
,
258 static cairo_int_status_t
259 _cairo_type3_glyph_surface_show_glyphs (void *abstract_surface
,
261 const cairo_pattern_t
*source
,
262 cairo_glyph_t
*glyphs
,
264 cairo_scaled_font_t
*scaled_font
,
265 int *remaining_glyphs
,
266 cairo_rectangle_int_t
*extents
)
268 cairo_type3_glyph_surface_t
*surface
= abstract_surface
;
269 cairo_int_status_t status
;
270 cairo_scaled_font_t
*font
;
271 cairo_matrix_t new_ctm
, ctm_inverse
;
274 for (i
= 0; i
< num_glyphs
; i
++)
275 cairo_matrix_transform_point (&surface
->cairo_to_pdf
, &glyphs
[i
].x
, &glyphs
[i
].y
);
277 /* We require the matrix to be invertable. */
278 ctm_inverse
= scaled_font
->ctm
;
279 status
= cairo_matrix_invert (&ctm_inverse
);
280 if (unlikely (status
))
281 return CAIRO_INT_STATUS_IMAGE_FALLBACK
;
283 cairo_matrix_multiply (&new_ctm
, &scaled_font
->ctm
, &ctm_inverse
);
284 font
= cairo_scaled_font_create (scaled_font
->font_face
,
285 &scaled_font
->font_matrix
,
287 &scaled_font
->options
);
288 if (unlikely (font
->status
))
291 status
= _cairo_pdf_operators_show_text_glyphs (&surface
->pdf_operators
,
298 cairo_scaled_font_destroy (font
);
303 static const cairo_surface_backend_t cairo_type3_glyph_surface_backend
= {
304 CAIRO_INTERNAL_SURFACE_TYPE_TYPE3_GLYPH
,
305 NULL
, /* _cairo_type3_glyph_surface_create_similar */
306 _cairo_type3_glyph_surface_finish
,
307 NULL
, /* acquire_source_image */
308 NULL
, /* release_source_image */
309 NULL
, /* acquire_dest_image */
310 NULL
, /* release_dest_image */
311 NULL
, /* clone_similar */
312 NULL
, /* composite */
313 NULL
, /* fill_rectangles */
314 NULL
, /* composite_trapezoids */
315 NULL
, /* create_span_renderer */
316 NULL
, /* check_span_renderer */
317 NULL
, /* cairo_type3_glyph_surface_copy_page */
318 NULL
, /* _cairo_type3_glyph_surface_show_page */
319 NULL
, /* set_clip_region */
320 _cairo_type3_glyph_surface_intersect_clip_path
,
321 NULL
, /* _cairo_type3_glyph_surface_get_extents */
322 NULL
, /* old_show_glyphs */
323 NULL
, /* _cairo_type3_glyph_surface_get_font_options */
325 NULL
, /* mark_dirty_rectangle */
326 NULL
, /* scaled_font_fini */
327 NULL
, /* scaled_glyph_fini */
328 _cairo_type3_glyph_surface_paint
,
329 _cairo_type3_glyph_surface_mask
,
330 _cairo_type3_glyph_surface_stroke
,
331 _cairo_type3_glyph_surface_fill
,
332 _cairo_type3_glyph_surface_show_glyphs
,
337 _cairo_type3_glyph_surface_set_stream (cairo_type3_glyph_surface_t
*surface
,
338 cairo_output_stream_t
*stream
)
340 surface
->stream
= stream
;
341 _cairo_pdf_operators_set_stream (&surface
->pdf_operators
, stream
);
344 static cairo_status_t
345 _cairo_type3_glyph_surface_emit_fallback_image (cairo_type3_glyph_surface_t
*surface
,
346 unsigned long glyph_index
)
348 cairo_scaled_glyph_t
*scaled_glyph
;
349 cairo_status_t status
;
350 cairo_image_surface_t
*image
;
354 status
= _cairo_scaled_glyph_lookup (surface
->scaled_font
,
356 CAIRO_SCALED_GLYPH_INFO_METRICS
|
357 CAIRO_SCALED_GLYPH_INFO_SURFACE
,
359 if (unlikely (status
))
362 image
= scaled_glyph
->surface
;
363 if (image
->width
== 0 || image
->height
== 0)
364 return CAIRO_STATUS_SUCCESS
;
366 x
= _cairo_fixed_to_double (scaled_glyph
->bbox
.p1
.x
);
367 y
= _cairo_fixed_to_double (scaled_glyph
->bbox
.p2
.y
);
368 mat
.xx
= image
->width
;
371 mat
.yy
= image
->height
;
374 cairo_matrix_multiply (&mat
, &mat
, &surface
->scaled_font
->scale_inverse
);
377 return _cairo_type3_glyph_surface_emit_image (surface
, image
, &mat
);
381 _cairo_type3_glyph_surface_set_font_subsets_callback (void *abstract_surface
,
382 cairo_pdf_operators_use_font_subset_t use_font_subset
,
385 cairo_type3_glyph_surface_t
*surface
= abstract_surface
;
387 if (unlikely (surface
->base
.status
))
390 _cairo_pdf_operators_set_font_subsets_callback (&surface
->pdf_operators
,
396 _cairo_type3_glyph_surface_analyze_glyph (void *abstract_surface
,
397 unsigned long glyph_index
)
399 cairo_type3_glyph_surface_t
*surface
= abstract_surface
;
400 cairo_scaled_glyph_t
*scaled_glyph
;
401 cairo_status_t status
, status2
;
402 cairo_output_stream_t
*null_stream
;
404 if (unlikely (surface
->base
.status
))
405 return surface
->base
.status
;
407 null_stream
= _cairo_null_stream_create ();
408 if (unlikely (null_stream
->status
))
409 return null_stream
->status
;
411 _cairo_type3_glyph_surface_set_stream (surface
, null_stream
);
413 _cairo_scaled_font_freeze_cache (surface
->scaled_font
);
414 status
= _cairo_scaled_glyph_lookup (surface
->scaled_font
,
416 CAIRO_SCALED_GLYPH_INFO_METRICS
|
417 CAIRO_SCALED_GLYPH_INFO_META_SURFACE
,
420 if (_cairo_status_is_error (status
))
423 if (status
== CAIRO_INT_STATUS_UNSUPPORTED
) {
424 status
= CAIRO_STATUS_SUCCESS
;
428 status
= _cairo_meta_surface_replay (scaled_glyph
->meta_surface
,
430 if (unlikely (status
))
433 status2
= _cairo_pdf_operators_flush (&surface
->pdf_operators
);
434 if (status
== CAIRO_STATUS_SUCCESS
)
437 if (status
== CAIRO_INT_STATUS_IMAGE_FALLBACK
)
438 status
= CAIRO_STATUS_SUCCESS
;
441 _cairo_scaled_font_thaw_cache (surface
->scaled_font
);
443 status2
= _cairo_output_stream_destroy (null_stream
);
444 if (status
== CAIRO_STATUS_SUCCESS
)
451 _cairo_type3_glyph_surface_emit_glyph (void *abstract_surface
,
452 cairo_output_stream_t
*stream
,
453 unsigned long glyph_index
,
457 cairo_type3_glyph_surface_t
*surface
= abstract_surface
;
458 cairo_scaled_glyph_t
*scaled_glyph
;
459 cairo_status_t status
, status2
;
460 double x_advance
, y_advance
;
461 cairo_matrix_t font_matrix_inverse
;
463 if (unlikely (surface
->base
.status
))
464 return surface
->base
.status
;
466 _cairo_type3_glyph_surface_set_stream (surface
, stream
);
468 _cairo_scaled_font_freeze_cache (surface
->scaled_font
);
469 status
= _cairo_scaled_glyph_lookup (surface
->scaled_font
,
471 CAIRO_SCALED_GLYPH_INFO_METRICS
|
472 CAIRO_SCALED_GLYPH_INFO_META_SURFACE
,
474 if (status
== CAIRO_INT_STATUS_UNSUPPORTED
) {
475 status
= _cairo_scaled_glyph_lookup (surface
->scaled_font
,
477 CAIRO_SCALED_GLYPH_INFO_METRICS
,
479 if (status
== CAIRO_STATUS_SUCCESS
)
480 status
= CAIRO_INT_STATUS_IMAGE_FALLBACK
;
482 if (_cairo_status_is_error (status
)) {
483 _cairo_scaled_font_thaw_cache (surface
->scaled_font
);
487 x_advance
= scaled_glyph
->metrics
.x_advance
;
488 y_advance
= scaled_glyph
->metrics
.y_advance
;
489 font_matrix_inverse
= surface
->scaled_font
->font_matrix
;
490 status2
= cairo_matrix_invert (&font_matrix_inverse
);
492 /* The invertability of font_matrix is tested in
493 * pdf_operators_show_glyphs before any glyphs are mappped to the
495 assert (status2
== CAIRO_STATUS_SUCCESS
);
497 cairo_matrix_transform_distance (&font_matrix_inverse
, &x_advance
, &y_advance
);
500 *bbox
= scaled_glyph
->bbox
;
501 _cairo_matrix_transform_bounding_box_fixed (&surface
->scaled_font
->scale_inverse
,
504 _cairo_output_stream_printf (surface
->stream
,
505 "%f 0 %f %f %f %f d1\n",
507 _cairo_fixed_to_double (bbox
->p1
.x
),
508 - _cairo_fixed_to_double (bbox
->p2
.y
),
509 _cairo_fixed_to_double (bbox
->p2
.x
),
510 - _cairo_fixed_to_double (bbox
->p1
.y
));
512 if (status
== CAIRO_STATUS_SUCCESS
) {
513 cairo_output_stream_t
*mem_stream
;
515 mem_stream
= _cairo_memory_stream_create ();
516 status
= mem_stream
->status
;
517 if (unlikely (status
))
520 _cairo_type3_glyph_surface_set_stream (surface
, mem_stream
);
522 _cairo_output_stream_printf (surface
->stream
, "q\n");
523 status
= _cairo_meta_surface_replay (scaled_glyph
->meta_surface
,
526 status2
= _cairo_pdf_operators_flush (&surface
->pdf_operators
);
527 if (status
== CAIRO_STATUS_SUCCESS
)
530 _cairo_output_stream_printf (surface
->stream
, "Q\n");
532 _cairo_type3_glyph_surface_set_stream (surface
, stream
);
533 if (status
== CAIRO_STATUS_SUCCESS
)
534 _cairo_memory_stream_copy (mem_stream
, stream
);
536 status2
= _cairo_output_stream_destroy (mem_stream
);
537 if (status
== CAIRO_STATUS_SUCCESS
)
541 if (status
== CAIRO_INT_STATUS_IMAGE_FALLBACK
)
542 status
= _cairo_type3_glyph_surface_emit_fallback_image (surface
, glyph_index
);
545 _cairo_scaled_font_thaw_cache (surface
->scaled_font
);
550 #endif /* CAIRO_HAS_FONT_SUBSET */