[cairo-commit] src/cairo-pdf-surface.c
Kristian Høgsberg
krh at kemper.freedesktop.org
Mon Feb 11 14:39:56 PST 2008
src/cairo-pdf-surface.c | 204 ++++++++++++------------------------------------
1 file changed, 55 insertions(+), 149 deletions(-)
New commits:
commit ba6788fc968477cfae6ed76414dd91b21671d028
Author: Kristian Høgsberg <krh at redhat.com>
Date: Mon Feb 11 13:44:48 2008 -0500
[pdf] Use compressed PDF stream instead of compress_dup()
The deflate stream has bounded (constant) memory overhead, whereas
compress_dup() allocates memory proportional to the uncompressed data.
This replaces compress_dup() usage with a compressed PDF stream for
emitting images, alpha masks and font subsets, and eliminates the
compress_dup() function.
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index e8c7ea4..08e08c7 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -1244,36 +1244,6 @@ _cairo_pdf_surface_start_page (void *abstract_surface)
return CAIRO_STATUS_SUCCESS;
}
-static void *
-compress_dup (const void *data, unsigned long data_size,
- unsigned long *compressed_size)
-{
- void *compressed;
- unsigned long additional_size;
-
- /* Bound calculation taken from zlib. */
- additional_size = (data_size >> 12) + (data_size >> 14) + 11;
- if (INT32_MAX - data_size <= additional_size) {
- _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
- return NULL;
- }
-
- *compressed_size = data_size + additional_size;
- compressed = malloc (*compressed_size);
- if (compressed == NULL) {
- _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
- return NULL;
- }
-
- if (compress (compressed, compressed_size, data, data_size) != Z_OK) {
- _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
- free (compressed);
- compressed = NULL;
- }
-
- return compressed;
-}
-
/* Emit alpha channel from the image into the given data, providing
* an id that can be used to reference the resulting SMask object.
*
@@ -1286,8 +1256,8 @@ _cairo_pdf_surface_emit_smask (cairo_pdf_surface_t *surface,
cairo_pdf_resource_t *stream_ret)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
- char *alpha, *alpha_compressed;
- unsigned long alpha_size, alpha_compressed_size;
+ char *alpha;
+ unsigned long alpha_size;
uint32_t *pixel32;
uint8_t *pixel8;
int i, x, y;
@@ -1368,35 +1338,24 @@ _cairo_pdf_surface_emit_smask (cairo_pdf_surface_t *surface,
if (opaque)
goto CLEANUP_ALPHA;
- alpha_compressed = compress_dup (alpha, alpha_size, &alpha_compressed_size);
- if (alpha_compressed == NULL) {
- status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
- goto CLEANUP_ALPHA;
- }
-
status = _cairo_pdf_surface_open_stream (surface,
NULL,
- FALSE,
+ TRUE,
" /Type /XObject\r\n"
" /Subtype /Image\r\n"
" /Width %d\r\n"
" /Height %d\r\n"
" /ColorSpace /DeviceGray\r\n"
- " /BitsPerComponent %d\r\n"
- " /Filter /FlateDecode\r\n",
+ " /BitsPerComponent %d\r\n",
image->width, image->height,
image->format == CAIRO_FORMAT_A1 ? 1 : 8);
if (status)
- goto CLEANUP_ALPHA_COMPRESSED;
+ goto CLEANUP_ALPHA;
*stream_ret = surface->pdf_stream.self;
-
- _cairo_output_stream_write (surface->output, alpha_compressed, alpha_compressed_size);
- _cairo_output_stream_printf (surface->output, "\r\n");
+ _cairo_output_stream_write (surface->output, alpha, alpha_size);
status = _cairo_pdf_surface_close_stream (surface);
- CLEANUP_ALPHA_COMPRESSED:
- free (alpha_compressed);
CLEANUP_ALPHA:
free (alpha);
CLEANUP:
@@ -1411,8 +1370,8 @@ _cairo_pdf_surface_emit_image (cairo_pdf_surface_t *surface,
cairo_pdf_resource_t *image_ret)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
- char *rgb, *compressed;
- unsigned long rgb_size, compressed_size;
+ char *rgb;
+ unsigned long rgb_size;
uint32_t *pixel;
int i, x, y;
cairo_pdf_resource_t smask = {0}; /* squelch bogus compiler warning */
@@ -1474,19 +1433,13 @@ _cairo_pdf_surface_emit_image (cairo_pdf_surface_t *surface,
}
}
- compressed = compress_dup (rgb, rgb_size, &compressed_size);
- if (compressed == NULL) {
- status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
- goto CLEANUP_RGB;
- }
-
need_smask = FALSE;
if (image->format == CAIRO_FORMAT_ARGB32 ||
image->format == CAIRO_FORMAT_A8 ||
image->format == CAIRO_FORMAT_A1) {
status = _cairo_pdf_surface_emit_smask (surface, image, &smask);
if (status)
- goto CLEANUP_COMPRESSED;
+ goto CLEANUP_RGB;
if (smask.id)
need_smask = TRUE;
@@ -1497,13 +1450,12 @@ _cairo_pdf_surface_emit_image (cairo_pdf_surface_t *surface,
" /Width %d\r\n" \
" /Height %d\r\n" \
" /ColorSpace /DeviceRGB\r\n" \
- " /BitsPerComponent 8\r\n" \
- " /Filter /FlateDecode\r\n"
+ " /BitsPerComponent 8\r\n"
if (need_smask)
status = _cairo_pdf_surface_open_stream (surface,
NULL,
- FALSE,
+ TRUE,
IMAGE_DICTIONARY
" /SMask %d 0 R\r\n",
image->width, image->height,
@@ -1511,22 +1463,18 @@ _cairo_pdf_surface_emit_image (cairo_pdf_surface_t *surface,
else
status = _cairo_pdf_surface_open_stream (surface,
NULL,
- FALSE,
+ TRUE,
IMAGE_DICTIONARY,
image->width, image->height);
if (status)
- goto CLEANUP_COMPRESSED;
+ goto CLEANUP_RGB;
#undef IMAGE_DICTIONARY
*image_ret = surface->pdf_stream.self;
-
- _cairo_output_stream_write (surface->output, compressed, compressed_size);
- _cairo_output_stream_printf (surface->output, "\r\n");
+ _cairo_output_stream_write (surface->output, rgb, rgb_size);
status = _cairo_pdf_surface_close_stream (surface);
-CLEANUP_COMPRESSED:
- free (compressed);
CLEANUP_RGB:
free (rgb);
CLEANUP:
@@ -2911,8 +2859,6 @@ _cairo_pdf_surface_emit_cff_font (cairo_pdf_surface_t *surface,
cairo_pdf_resource_t stream, descriptor, cidfont_dict;
cairo_pdf_resource_t subset_resource, to_unicode_stream;
cairo_pdf_font_t font;
- unsigned long compressed_length;
- char *compressed;
unsigned int i;
cairo_status_t status;
@@ -2922,31 +2868,19 @@ _cairo_pdf_surface_emit_cff_font (cairo_pdf_surface_t *surface,
if (subset_resource.id == 0)
return CAIRO_STATUS_SUCCESS;
- compressed = compress_dup (subset->data, subset->data_length, &compressed_length);
- if (compressed == NULL)
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- stream = _cairo_pdf_surface_new_object (surface);
- if (stream.id == 0) {
- free (compressed);
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
- }
+ status = _cairo_pdf_surface_open_stream (surface,
+ NULL,
+ TRUE,
+ " /Subtype /CIDFontType0C\r\n");
+ if (status)
+ return status;
- _cairo_output_stream_printf (surface->output,
- "%d 0 obj\r\n"
- "<< /Filter /FlateDecode\r\n"
- " /Length %lu\r\n"
- " /Subtype /CIDFontType0C\r\n"
- ">>\r\n"
- "stream\r\n",
- stream.id,
- compressed_length);
- _cairo_output_stream_write (surface->output, compressed, compressed_length);
- _cairo_output_stream_printf (surface->output,
- "\r\n"
- "endstream\r\n"
- "endobj\r\n");
- free (compressed);
+ stream = surface->pdf_stream.self;
+ _cairo_output_stream_write (surface->output,
+ subset->data, subset->data_length);
+ status = _cairo_pdf_surface_close_stream (surface);
+ if (status)
+ return status;
status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
font_subset, TRUE,
@@ -3092,8 +3026,7 @@ _cairo_pdf_surface_emit_type1_font (cairo_pdf_surface_t *surface,
cairo_pdf_resource_t stream, descriptor, subset_resource, to_unicode_stream;
cairo_pdf_font_t font;
cairo_status_t status;
- unsigned long length, compressed_length;
- char *compressed;
+ unsigned long length;
unsigned int i;
subset_resource = _cairo_pdf_surface_get_font_resource (surface,
@@ -3103,36 +3036,22 @@ _cairo_pdf_surface_emit_type1_font (cairo_pdf_surface_t *surface,
return CAIRO_STATUS_SUCCESS;
/* We ignore the zero-trailer and set Length3 to 0. */
- length = subset->header_length + subset->data_length;
- compressed = compress_dup (subset->data, length, &compressed_length);
- if (compressed == NULL)
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- stream = _cairo_pdf_surface_new_object (surface);
- if (stream.id == 0) {
- free (compressed);
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
- }
+ status = _cairo_pdf_surface_open_stream (surface,
+ NULL,
+ TRUE,
+ " /Length1 %lu\r\n"
+ " /Length2 %lu\r\n"
+ " /Length3 0\r\n",
+ subset->header_length,
+ subset->data_length);
+ if (status)
+ return status;
- _cairo_output_stream_printf (surface->output,
- "%d 0 obj\r\n"
- "<< /Filter /FlateDecode\r\n"
- " /Length %lu\r\n"
- " /Length1 %lu\r\n"
- " /Length2 %lu\r\n"
- " /Length3 0\r\n"
- ">>\r\n"
- "stream\r\n",
- stream.id,
- compressed_length,
- subset->header_length,
- subset->data_length);
- _cairo_output_stream_write (surface->output, compressed, compressed_length);
- _cairo_output_stream_printf (surface->output,
- "\r\n"
- "endstream\r\n"
- "endobj\r\n");
- free (compressed);
+ stream = surface->pdf_stream.self;
+ _cairo_output_stream_write (surface->output, subset->data, length);
+ status = _cairo_pdf_surface_close_stream (surface);
+ if (status)
+ return status;
status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
font_subset, FALSE,
@@ -3260,8 +3179,6 @@ _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t *surface,
cairo_status_t status;
cairo_pdf_font_t font;
cairo_truetype_subset_t subset;
- unsigned long compressed_length;
- char *compressed;
unsigned int i;
subset_resource = _cairo_pdf_surface_get_font_resource (surface,
@@ -3274,35 +3191,24 @@ _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t *surface,
if (status)
return status;
- compressed = compress_dup (subset.data, subset.data_length,
- &compressed_length);
- if (compressed == NULL) {
+ status = _cairo_pdf_surface_open_stream (surface,
+ NULL,
+ TRUE,
+ " /Length1 %lu\r\n",
+ subset.data_length);
+ if (status) {
_cairo_truetype_subset_fini (&subset);
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return status;
}
- stream = _cairo_pdf_surface_new_object (surface);
- if (stream.id == 0) {
- free (compressed);
+ stream = surface->pdf_stream.self;
+ _cairo_output_stream_write (surface->output,
+ subset.data, subset.data_length);
+ status = _cairo_pdf_surface_close_stream (surface);
+ if (status) {
_cairo_truetype_subset_fini (&subset);
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return status;
}
- _cairo_output_stream_printf (surface->output,
- "%d 0 obj\r\n"
- "<< /Filter /FlateDecode\r\n"
- " /Length %lu\r\n"
- " /Length1 %lu\r\n"
- ">>\r\n"
- "stream\r\n",
- stream.id,
- compressed_length,
- subset.data_length);
- _cairo_output_stream_write (surface->output, compressed, compressed_length);
- _cairo_output_stream_printf (surface->output,
- "\r\n"
- "endstream\r\n"
- "endobj\r\n");
- free (compressed);
status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
font_subset, TRUE,
More information about the cairo-commit
mailing list