Implement PS Type 3 font image support

There does not appear to be any way of emulating PDF inline images in
PostScript so we call back to the PS or PDF surface to emit the image.
This commit is contained in:
Adrian Johnson 2008-06-08 17:03:05 +09:30
parent 5b05034cc9
commit 42c212135d
4 changed files with 104 additions and 30 deletions

View file

@ -3397,6 +3397,46 @@ _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t *surface,
return status;
}
static cairo_status_t
_cairo_pdf_emit_imagemask (cairo_image_surface_t *image,
cairo_output_stream_t *stream)
{
unsigned char *byte, output_byte;
int row, col, num_cols;
/* The only image type supported by Type 3 fonts are 1-bit image
* masks */
assert (image->format == CAIRO_FORMAT_A1);
_cairo_output_stream_printf (stream,
"BI\n"
"/IM true\n"
"/W %d\n"
"/H %d\n"
"/BPC 1\n"
"/D [1 0]\n",
image->width,
image->height);
_cairo_output_stream_printf (stream,
"ID ");
num_cols = (image->width + 7) / 8;
for (row = 0; row < image->height; row++) {
byte = image->data + row * image->stride;
for (col = 0; col < num_cols; col++) {
output_byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte);
_cairo_output_stream_write (stream, &output_byte, 1);
byte++;
}
}
_cairo_output_stream_printf (stream,
"\nEI\n");
return _cairo_output_stream_get_status (stream);
}
static cairo_status_t
_cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface,
cairo_scaled_font_subset_t *font_subset)
@ -3430,7 +3470,9 @@ _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface,
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font, NULL);
type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font,
NULL,
_cairo_pdf_emit_imagemask);
for (i = 0; i < font_subset->num_glyphs; i++) {
status = _cairo_pdf_surface_open_stream (surface,

View file

@ -374,6 +374,51 @@ _cairo_ps_surface_emit_truetype_font_subset (cairo_ps_surface_t *surface,
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_ps_emit_imagemask (cairo_image_surface_t *image,
cairo_output_stream_t *stream)
{
unsigned char *row, *byte;
int rows, cols;
/* The only image type supported by Type 3 fonts are 1-bit image
* masks */
assert (image->format == CAIRO_FORMAT_A1);
_cairo_output_stream_printf (stream,
"<<\n"
" /ImageType 1\n"
" /Width %d\n"
" /Height %d\n"
" /ImageMatrix [%d 0 0 %d 0 %d]\n"
" /Decode [1 0]\n"
" /BitsPerComponent 1\n",
image->width,
image->height,
image->width,
-image->height,
image->height);
_cairo_output_stream_printf (stream,
" /DataSource {<");
for (row = image->data, rows = image->height; rows; row += image->stride, rows--) {
for (byte = row, cols = (image->width + 7) / 8; cols; byte++, cols--) {
unsigned char output_byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte);
_cairo_output_stream_printf (stream, "%02x ", output_byte);
}
_cairo_output_stream_printf (stream, "\n ");
}
_cairo_output_stream_printf (stream,
" >}\n");
_cairo_output_stream_printf (stream,
">>\n");
_cairo_output_stream_printf (stream,
"imagemask\n");
return _cairo_output_stream_get_status (stream);
}
static cairo_status_t
_cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface,
cairo_scaled_font_subset_t *font_subset)
@ -401,7 +446,9 @@ _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface,
"/Encoding 256 array def\n"
"0 1 255 { Encoding exch /.notdef put } for\n");
type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font, NULL);
type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font,
NULL,
_cairo_ps_emit_imagemask);
for (i = 1; i < font_subset->num_glyphs; i++) {
if (font_subset->glyph_names != NULL) {

View file

@ -40,6 +40,9 @@
#include "cairo-surface-private.h"
#include "cairo-pdf-operators-private.h"
typedef cairo_status_t (*cairo_type3_glyph_surface_emit_image_t) (cairo_image_surface_t *image,
cairo_output_stream_t *stream);
typedef struct cairo_type3_glyph_surface {
cairo_surface_t base;
@ -47,11 +50,13 @@ typedef struct cairo_type3_glyph_surface {
cairo_output_stream_t *stream;
cairo_pdf_operators_t pdf_operators;
cairo_matrix_t cairo_to_pdf;
cairo_type3_glyph_surface_emit_image_t emit_image;
} cairo_type3_glyph_surface_t;
cairo_private cairo_surface_t *
_cairo_type3_glyph_surface_create (cairo_scaled_font_t *scaled_font,
cairo_output_stream_t *stream);
_cairo_type3_glyph_surface_create (cairo_scaled_font_t *scaled_font,
cairo_output_stream_t *stream,
cairo_type3_glyph_surface_emit_image_t emit_image);
cairo_private cairo_status_t
_cairo_type3_glyph_surface_emit_notdef_glyph (void *abstract_surface,

View file

@ -42,8 +42,9 @@
static const cairo_surface_backend_t cairo_type3_glyph_surface_backend;
cairo_surface_t *
_cairo_type3_glyph_surface_create (cairo_scaled_font_t *scaled_font,
cairo_output_stream_t *stream)
_cairo_type3_glyph_surface_create (cairo_scaled_font_t *scaled_font,
cairo_output_stream_t *stream,
cairo_type3_glyph_surface_emit_image_t emit_image)
{
cairo_type3_glyph_surface_t *surface;
cairo_matrix_t invert_y_axis;
@ -57,6 +58,7 @@ _cairo_type3_glyph_surface_create (cairo_scaled_font_t *scaled_font,
surface->scaled_font = scaled_font;
surface->stream = stream;
surface->emit_image = emit_image;
/* Setup the transform from the user-font device space to Type 3
* font space. The Type 3 font space is defined by the FontMatrix
@ -81,8 +83,6 @@ _cairo_type3_glyph_surface_emit_image (cairo_type3_glyph_surface_t *surface,
{
cairo_status_t status;
cairo_image_surface_t *image_mask;
unsigned char *byte, output_byte;
int row, col, num_cols;
/* The only image type supported by Type 3 fonts are 1-bit image
* masks */
@ -104,30 +104,10 @@ _cairo_type3_glyph_surface_emit_image (cairo_type3_glyph_surface_t *surface,
image_matrix->x0,
image_matrix->y0);
_cairo_output_stream_printf (surface->stream,
"BI\n"
"/IM true\n"
"/W %d\n"
"/H %d\n"
"/BPC 1\n"
"/D [1 0]\n",
image_mask->width,
image_mask->height);
status = surface->emit_image (image_mask, surface->stream);
_cairo_output_stream_printf (surface->stream,
"ID ");
num_cols = (image_mask->width + 7) / 8;
for (row = 0; row < image_mask->height; row++) {
byte = image_mask->data + row * image_mask->stride;
for (col = 0; col < num_cols; col++) {
output_byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte);
_cairo_output_stream_write (surface->stream, &output_byte, 1);
byte++;
}
}
_cairo_output_stream_printf (surface->stream,
"\nEI Q\n");
"Q\n");
if (image_mask != image)
cairo_surface_destroy (&image_mask->base);