[cairo-commit] 3 commits - src/cairo-deflate-stream.c
src/cairo-output-stream-private.h src/cairo-pdf-surface.c
src/Makefile.am
Carl Worth
cworth at kemper.freedesktop.org
Wed Jan 17 13:28:15 PST 2007
src/Makefile.am | 1
src/cairo-deflate-stream.c | 142 ++++++++++++++++++++++++++++++++++++++
src/cairo-output-stream-private.h | 4 +
src/cairo-pdf-surface.c | 70 ++++++++++++++----
4 files changed, 202 insertions(+), 15 deletions(-)
New commits:
diff-tree b02b86da5c6c82f9b653698f8480855a35777155 (from 7f246462eb3cc2576387755fa2d554394e86225c)
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Sun Sep 24 00:55:20 2006 +0930
PDF: Compress the content stream
Use cairo-deflate-stream to compress all content streams emitted by the
PDF surface.
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index d290059..ec98345 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -129,6 +129,8 @@ typedef struct _cairo_pdf_surface {
cairo_pdf_resource_t self;
cairo_pdf_resource_t length;
long start_offset;
+ cairo_bool_t compressed;
+ cairo_output_stream_t *old_output;
} current_stream;
cairo_bool_t has_clip;
@@ -146,8 +148,9 @@ _cairo_pdf_surface_clear (cairo_pdf_surf
static cairo_pdf_resource_t
_cairo_pdf_surface_open_stream (cairo_pdf_surface_t *surface,
+ cairo_bool_t compressed,
const char *fmt,
- ...) CAIRO_PRINTF_FORMAT(2, 3);
+ ...) CAIRO_PRINTF_FORMAT(3, 4);
static void
_cairo_pdf_surface_close_stream (cairo_pdf_surface_t *surface);
@@ -456,6 +459,7 @@ _cairo_pdf_surface_clear (cairo_pdf_surf
static cairo_pdf_resource_t
_cairo_pdf_surface_open_stream (cairo_pdf_surface_t *surface,
+ cairo_bool_t compressed,
const char *fmt,
...)
{
@@ -464,12 +468,16 @@ _cairo_pdf_surface_open_stream (cairo_pd
surface->current_stream.active = TRUE;
surface->current_stream.self = _cairo_pdf_surface_new_object (surface);
surface->current_stream.length = _cairo_pdf_surface_new_object (surface);
+ surface->current_stream.compressed = compressed;
_cairo_output_stream_printf (surface->output,
"%d 0 obj\r\n"
"<< /Length %d 0 R\r\n",
surface->current_stream.self.id,
surface->current_stream.length.id);
+ if (compressed)
+ _cairo_output_stream_printf (surface->output,
+ " /Filter /FlateDecode\r\n");
if (fmt != NULL) {
va_start (ap, fmt);
@@ -483,6 +491,11 @@ _cairo_pdf_surface_open_stream (cairo_pd
surface->current_stream.start_offset = _cairo_output_stream_get_position (surface->output);
+ if (compressed) {
+ surface->current_stream.old_output = surface->output;
+ surface->output = _cairo_deflate_stream_create (surface->output);
+ }
+
return surface->current_stream.self;
}
@@ -494,6 +507,13 @@ _cairo_pdf_surface_close_stream (cairo_p
if (! surface->current_stream.active)
return;
+ if (surface->current_stream.compressed) {
+ _cairo_output_stream_destroy (surface->output);
+ surface->output = surface->current_stream.old_output;
+ _cairo_output_stream_printf (surface->output,
+ "\r\n");
+ }
+
length = _cairo_output_stream_get_position (surface->output) -
surface->current_stream.start_offset;
_cairo_output_stream_printf (surface->output,
@@ -577,6 +597,7 @@ _cairo_pdf_surface_resume_content_stream
cairo_pdf_resource_t stream;
stream = _cairo_pdf_surface_open_stream (surface,
+ TRUE,
" /Type /XObject\r\n"
" /Subtype /Form\r\n"
" /BBox [ 0 0 %f %f ]\r\n",
@@ -593,6 +614,7 @@ _cairo_pdf_surface_start_page (void *abs
cairo_pdf_resource_t stream;
stream = _cairo_pdf_surface_open_stream (surface,
+ TRUE,
" /Type /XObject\r\n"
" /Subtype /Form\r\n"
" /BBox [ 0 0 %f %f ]\r\n",
@@ -680,6 +702,7 @@ emit_smask (cairo_pdf_surface_t *surfac
}
*stream_ret = _cairo_pdf_surface_open_stream (surface,
+ FALSE,
" /Type /XObject\r\n"
" /Subtype /Image\r\n"
" /Width %d\r\n"
@@ -789,12 +812,14 @@ emit_image (cairo_pdf_surface_t *surfac
if (need_smask)
*image_ret = _cairo_pdf_surface_open_stream (surface,
+ FALSE,
IMAGE_DICTIONARY
" /SMask %d 0 R\r\n",
image->width, image->height,
smask.id);
else
*image_ret = _cairo_pdf_surface_open_stream (surface,
+ FALSE,
IMAGE_DICTIONARY,
image->width, image->height);
@@ -928,6 +953,7 @@ emit_surface_pattern (cairo_pdf_surface_
cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);
stream = _cairo_pdf_surface_open_stream (surface,
+ FALSE,
" /BBox [0 0 %d %d]\r\n"
" /XStep %d\r\n"
" /YStep %d\r\n"
@@ -1942,7 +1968,7 @@ _cairo_pdf_surface_emit_outline_glyph (c
if (status)
return status;
- *glyph_ret = _cairo_pdf_surface_open_stream (surface, NULL);
+ *glyph_ret = _cairo_pdf_surface_open_stream (surface, FALSE, NULL);
_cairo_output_stream_printf (surface->output,
"0 0 %f %f %f %f d1\r\n",
@@ -1997,7 +2023,7 @@ _cairo_pdf_surface_emit_bitmap_glyph (ca
return cairo_surface_status (&image->base);
}
- *glyph_ret = _cairo_pdf_surface_open_stream (surface, NULL);
+ *glyph_ret = _cairo_pdf_surface_open_stream (surface, FALSE, NULL);
_cairo_output_stream_printf (surface->output,
"0 0 %f %f %f %f d1\r\n",
diff-tree 7f246462eb3cc2576387755fa2d554394e86225c (from b3440e85305af4f5ceef9437af7c26d3232dc55a)
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Sun Sep 24 00:52:01 2006 +0930
Add cairo-deflate-stream.c
Add a new stream type that compresses the stream using the zlib deflate method.
This is intended for use by the PDF surface.
diff --git a/src/Makefile.am b/src/Makefile.am
index 5206d3f..5983867 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -177,6 +177,7 @@ libcairo_la_SOURCES = \
cairo-clip-private.h \
cairo-color.c \
cairo-debug.c \
+ cairo-deflate-stream.c \
cairo-fixed.c \
cairo-font.c \
cairo-font-options.c \
diff --git a/src/cairo-deflate-stream.c b/src/cairo-deflate-stream.c
new file mode 100644
index 0000000..816f5c5
--- /dev/null
+++ b/src/cairo-deflate-stream.c
@@ -0,0 +1,142 @@
+/* cairo_deflate_stream.c: Output stream abstraction
+ *
+ * Copyright © 2006 Adrian Johnson
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is cairo_output_stream.c as distributed with the
+ * cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is Adrian Johnson.
+ *
+ * Author(s):
+ * Adrian Johnson <ajohnson at redneon.com>
+ */
+
+#include "cairoint.h"
+#include "cairo-output-stream-private.h"
+#include <zlib.h>
+
+#define BUFFER_SIZE 16384
+
+typedef struct _cairo_deflate_stream {
+ cairo_output_stream_t base;
+ cairo_output_stream_t *output;
+ z_stream zlib_stream;
+ unsigned char input_buf[BUFFER_SIZE];
+ unsigned char output_buf[BUFFER_SIZE];
+} cairo_deflate_stream_t;
+
+static void
+cairo_deflate_stream_deflate (cairo_deflate_stream_t *stream, cairo_bool_t flush)
+{
+ int ret;
+ cairo_bool_t finished;
+
+ do {
+ ret = deflate (&stream->zlib_stream, flush ? Z_FINISH : Z_NO_FLUSH);
+ if (flush || stream->zlib_stream.avail_out == 0)
+ {
+ _cairo_output_stream_write (stream->output,
+ stream->output_buf,
+ BUFFER_SIZE - stream->zlib_stream.avail_out);
+ stream->zlib_stream.next_out = stream->output_buf;
+ stream->zlib_stream.avail_out = BUFFER_SIZE;
+ }
+
+ finished = TRUE;
+ if (stream->zlib_stream.avail_in != 0)
+ finished = FALSE;
+ if (flush && ret != Z_STREAM_END)
+ finished = FALSE;
+
+ } while (!finished);
+
+ stream->zlib_stream.next_in = stream->input_buf;
+}
+
+static cairo_status_t
+_cairo_deflate_stream_write (cairo_output_stream_t *base,
+ const unsigned char *data,
+ unsigned int length)
+{
+ cairo_deflate_stream_t *stream = (cairo_deflate_stream_t *) base;
+ unsigned int count;
+ const unsigned char *p = data;
+
+ while (length) {
+ count = length;
+ if (count > BUFFER_SIZE - stream->zlib_stream.avail_in)
+ count = BUFFER_SIZE - stream->zlib_stream.avail_in;
+ memcpy (stream->input_buf + stream->zlib_stream.avail_in, p, count);
+ p += count;
+ stream->zlib_stream.avail_in += count;
+ length -= count;
+
+ if (stream->zlib_stream.avail_in == BUFFER_SIZE)
+ cairo_deflate_stream_deflate (stream, FALSE);
+ }
+
+ return _cairo_output_stream_get_status (stream->output);
+}
+
+static cairo_status_t
+_cairo_deflate_stream_close (cairo_output_stream_t *base)
+{
+ cairo_deflate_stream_t *stream = (cairo_deflate_stream_t *) base;
+
+ cairo_deflate_stream_deflate (stream, TRUE);
+ deflateEnd (&stream->zlib_stream);
+
+ return _cairo_output_stream_get_status (stream->output);
+}
+
+cairo_output_stream_t *
+_cairo_deflate_stream_create (cairo_output_stream_t *output)
+{
+ cairo_deflate_stream_t *stream;
+
+ stream = malloc (sizeof (cairo_deflate_stream_t));
+ if (stream == NULL)
+ return (cairo_output_stream_t *) &cairo_output_stream_nil;
+
+ _cairo_output_stream_init (&stream->base,
+ _cairo_deflate_stream_write,
+ _cairo_deflate_stream_close);
+ stream->output = output;
+
+ stream->zlib_stream.zalloc = Z_NULL;
+ stream->zlib_stream.zfree = Z_NULL;
+ stream->zlib_stream.opaque = Z_NULL;
+
+ if (deflateInit (&stream->zlib_stream, Z_DEFAULT_COMPRESSION) != Z_OK)
+ return (cairo_output_stream_t *) &cairo_output_stream_nil;
+
+ stream->zlib_stream.next_in = stream->input_buf;
+ stream->zlib_stream.avail_in = 0;
+ stream->zlib_stream.next_out = stream->output_buf;
+ stream->zlib_stream.avail_out = BUFFER_SIZE;
+
+ return &stream->base;
+}
diff --git a/src/cairo-output-stream-private.h b/src/cairo-output-stream-private.h
index 913fb60..d68fbb4 100644
--- a/src/cairo-output-stream-private.h
+++ b/src/cairo-output-stream-private.h
@@ -159,4 +159,8 @@ _cairo_memory_stream_length (cairo_outpu
cairo_private cairo_output_stream_t *
_cairo_base85_stream_create (cairo_output_stream_t *output);
+/* cairo_deflate_stream.c */
+cairo_private cairo_output_stream_t *
+_cairo_deflate_stream_create (cairo_output_stream_t *output);
+
#endif /* CAIRO_OUTPUT_STREAM_PRIVATE_H */
diff-tree b3440e85305af4f5ceef9437af7c26d3232dc55a (from 5c2136ea7c3aea1ae90b46b0dd645a4e1b5cc9a1)
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Sun Sep 24 00:48:36 2006 +0930
PDF: Use Td where possible instead of Tm for positioning glyphs
This avoids emitting the font matrix for every single glyph.
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 821ea5f..d290059 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -2726,6 +2726,7 @@ _cairo_pdf_surface_show_glyphs (void *
cairo_pdf_surface_t *surface = abstract_surface;
unsigned int current_subset_id = (unsigned int)-1;
unsigned int font_id, subset_id, subset_glyph_index;
+ cairo_bool_t diagonal;
cairo_status_t status;
int i;
@@ -2741,6 +2742,12 @@ _cairo_pdf_surface_show_glyphs (void *
_cairo_output_stream_printf (surface->output,
"BT\r\n");
+ if (scaled_font->scale.xy == 0.0 &&
+ scaled_font->scale.yx == 0.0)
+ diagonal = TRUE;
+ else
+ diagonal = FALSE;
+
for (i = 0; i < num_glyphs; i++) {
status = _cairo_scaled_font_subsets_map_glyph (surface->font_subsets,
scaled_font, glyphs[i].index,
@@ -2748,22 +2755,29 @@ _cairo_pdf_surface_show_glyphs (void *
if (status)
return status;
- if (subset_id != current_subset_id) {
+ if (subset_id != current_subset_id)
_cairo_output_stream_printf (surface->output,
"/CairoFont-%d-%d 1 Tf\r\n",
font_id, subset_id);
- current_subset_id = subset_id;
- }
- _cairo_output_stream_printf (surface->output,
- "%f %f %f %f %f %f Tm <%02x> Tj\r\n",
- scaled_font->scale.xx,
- scaled_font->scale.yx,
- -scaled_font->scale.xy,
- -scaled_font->scale.yy,
- glyphs[i].x,
- glyphs[i].y,
- subset_glyph_index);
+ if (subset_id != current_subset_id || !diagonal) {
+ _cairo_output_stream_printf (surface->output,
+ "%f %f %f %f %f %f Tm <%02x> Tj\r\n",
+ scaled_font->scale.xx,
+ scaled_font->scale.yx,
+ -scaled_font->scale.xy,
+ -scaled_font->scale.yy,
+ glyphs[i].x,
+ glyphs[i].y,
+ subset_glyph_index);
+ current_subset_id = subset_id;
+ } else {
+ _cairo_output_stream_printf (surface->output,
+ "%f %f Td <%02x> Tj\r\n",
+ (glyphs[i].x - glyphs[i-1].x)/scaled_font->scale.xx,
+ (glyphs[i].y - glyphs[i-1].y)/scaled_font->scale.yy,
+ subset_glyph_index);
+ }
}
_cairo_output_stream_printf (surface->output,
More information about the cairo-commit
mailing list