[cairo-commit] 11 commits - src/cairo.h src/cairo-image-info.c src/cairo-image-info-private.h src/cairo-jpeg-info.c src/cairo-jpeg-info-private.h src/cairo-misc.c src/cairo-pdf.h src/cairo-pdf-operators.c src/cairo-pdf-operators-private.h src/cairo-pdf-surface.c src/cairo-pdf-surface-private.h src/cairo-ps-surface.c src/cairo-surface-fallback.c src/cairo-svg-surface.c src/cairo-win32-printing-surface.c src/cairo-win32-private.h src/Makefile.sources test/jp2.jp2 test/mime-data.c test/mime-data.pdf.ref.png test/mime-data.ps.ref.png test/mime-data.ref.png test/mime-data.svg.ref.png

Adrian Johnson ajohnson at kemper.freedesktop.org
Mon Nov 24 12:19:01 PST 2008


 src/Makefile.sources               |    4 
 src/cairo-image-info-private.h     |   63 ++++++++
 src/cairo-image-info.c             |  290 +++++++++++++++++++++++++++++++++++++
 src/cairo-jpeg-info-private.h      |   54 ------
 src/cairo-jpeg-info.c              |  141 -----------------
 src/cairo-misc.c                   |    2 
 src/cairo-pdf-operators-private.h  |    5 
 src/cairo-pdf-operators.c          |    8 +
 src/cairo-pdf-surface-private.h    |    2 
 src/cairo-pdf-surface.c            |  181 +++++++++++++++++++++--
 src/cairo-pdf.h                    |   24 +++
 src/cairo-ps-surface.c             |    6 
 src/cairo-surface-fallback.c       |    1 
 src/cairo-svg-surface.c            |    6 
 src/cairo-win32-printing-surface.c |  108 ++++++++++---
 src/cairo-win32-private.h          |    3 
 src/cairo.h                        |    1 
 test/jp2.jp2                       |binary
 test/mime-data.c                   |    7 
 test/mime-data.pdf.ref.png         |binary
 test/mime-data.ps.ref.png          |binary
 test/mime-data.ref.png             |binary
 test/mime-data.svg.ref.png         |binary
 23 files changed, 664 insertions(+), 242 deletions(-)

New commits:
commit 721cad9b24c2ad049320950d231ed84046c5b8ab
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Mon Nov 24 22:41:03 2008 +1030

    Fix typo

diff --git a/src/cairo-misc.c b/src/cairo-misc.c
index 5d258ff..397b0ef 100644
--- a/src/cairo-misc.c
+++ b/src/cairo-misc.c
@@ -617,7 +617,7 @@ _cairo_lround (double d)
 #include <windows.h>
 #include <io.h>
 
-/* tmpfile() replacment for Windows.
+/* tmpfile() replacement for Windows.
  *
  * On Windows tmpfile() creates the file in the root directory. This
  * may fail due to unsufficient privileges.
commit 70e4c532722bbcad1eca50438e6ab2cdd0ea9b53
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Mon Nov 24 22:38:30 2008 +1030

    Document location of image format specifications

diff --git a/src/cairo-image-info.c b/src/cairo-image-info.c
index 7742c88..f84bcaf 100644
--- a/src/cairo-image-info.c
+++ b/src/cairo-image-info.c
@@ -42,6 +42,11 @@ _get_be32 (const unsigned char *p)
     return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
 }
 
+/* JPEG (image/jpeg)
+ *
+ * http://www.w3.org/Graphics/JPEG/itu-t81.pdf
+ */
+
 /* Markers with no parameters. All other markers are followed by a two
  * byte length of the parameters. */
 #define TEM       0x01
@@ -146,6 +151,11 @@ _cairo_image_info_get_jpeg_info (cairo_image_info_t	*info,
     return CAIRO_STATUS_SUCCESS;
 }
 
+/* JPEG 2000 (image/jp2)
+ *
+ * http://www.jpeg.org/public/15444-1annexi.pdf
+ */
+
 #define JPX_FILETYPE 0x66747970
 #define JPX_JP2_HEADER 0x6A703268
 #define JPX_IMAGE_HEADER 0x69686472
@@ -240,6 +250,11 @@ _cairo_image_info_get_jpx_info (cairo_image_info_t	*info,
     return CAIRO_STATUS_SUCCESS;
 }
 
+/* PNG (image/png)
+ *
+ * http://www.w3.org/TR/2003/REC-PNG-20031110/
+ */
+
 #define PNG_IHDR 0x49484452
 
 static const unsigned char _png_magic[8] = { 137, 80, 78, 71, 13, 10, 26, 10 };
commit 4ca644af274bda4603e7d02dbeca8641bbb3ff79
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Mon Nov 24 00:29:54 2008 +1030

    Win32-print: Add PNG embedding support

diff --git a/src/cairo-win32-printing-surface.c b/src/cairo-win32-printing-surface.c
index 625f4b0..4133019 100644
--- a/src/cairo-win32-printing-surface.c
+++ b/src/cairo-win32-printing-surface.c
@@ -80,6 +80,10 @@
 # define CHECKJPEGFORMAT 0x1017
 #endif
 
+#if !defined(CHECKPNGFORMAT)
+# define CHECKPNGFORMAT 0x1018
+#endif
+
 #define PELS_72DPI  ((LONG)(72. / 0.0254))
 
 static const cairo_surface_backend_t cairo_win32_printing_surface_backend;
@@ -112,6 +116,10 @@ _cairo_win32_printing_surface_init_image_support (cairo_win32_surface_t *surface
     word = CHECKJPEGFORMAT;
     if (ExtEscape(surface->dc, QUERYESCSUPPORT, sizeof(word), (char *)&word, 0, (char *)NULL) > 0)
 	surface->flags |= CAIRO_WIN32_SURFACE_CAN_CHECK_JPEG;
+
+    word = CHECKPNGFORMAT;
+    if (ExtEscape(surface->dc, QUERYESCSUPPORT, sizeof(word), (char *)&word, 0, (char *)NULL) > 0)
+	surface->flags |= CAIRO_WIN32_SURFACE_CAN_CHECK_PNG;
 }
 
 static cairo_int_status_t
@@ -504,14 +512,12 @@ _cairo_win32_printing_surface_paint_meta_pattern (cairo_win32_surface_t   *surfa
 static cairo_int_status_t
 _cairo_win32_printing_surface_check_jpeg (cairo_win32_surface_t   *surface,
 					  cairo_surface_t         *source,
-					  const unsigned char    **jpeg_data,
-					  unsigned int            *jpeg_length,
-					  int 			  *jpeg_width,
-					  int 			  *jpeg_height)
+					  const unsigned char    **data,
+					  unsigned int            *length,
+					  cairo_image_info_t      *info)
 {
     const unsigned char *mime_data;
     unsigned int mime_data_length;
-    cairo_image_info_t info;
     cairo_int_status_t status;
     DWORD result;
 
@@ -523,7 +529,7 @@ _cairo_win32_printing_surface_check_jpeg (cairo_win32_surface_t   *surface,
     if (mime_data == NULL)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
-    status = _cairo_image_info_get_jpeg_info (&info, mime_data, mime_data_length);
+    status = _cairo_image_info_get_jpeg_info (info, mime_data, mime_data_length);
     if (status)
 	return status;
 
@@ -535,10 +541,47 @@ _cairo_win32_printing_surface_check_jpeg (cairo_win32_surface_t   *surface,
     if (result != 1)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
-    *jpeg_data = mime_data;
-    *jpeg_length = mime_data_length;
-    *jpeg_width = info.width;
-    *jpeg_height = info.height;
+    *data = mime_data;
+    *length = mime_data_length;
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_int_status_t
+_cairo_win32_printing_surface_check_png (cairo_win32_surface_t   *surface,
+					 cairo_surface_t         *source,
+					 const unsigned char    **data,
+					 unsigned int            *length,
+					 cairo_image_info_t      *info)
+{
+    const unsigned char *mime_data;
+    unsigned int mime_data_length;
+
+    cairo_int_status_t status;
+    DWORD result;
+
+    if (!(surface->flags & CAIRO_WIN32_SURFACE_CAN_CHECK_PNG))
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_PNG,
+				 &mime_data, &mime_data_length);
+    if (mime_data == NULL)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    status = _cairo_image_info_get_png_info (info, mime_data, mime_data_length);
+    if (status)
+	return status;
+
+    result = 0;
+    if (ExtEscape(surface->dc, CHECKPNGFORMAT, mime_data_length, (char *) mime_data,
+		  sizeof(result), (char *) &result) <= 0)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    if (result != 1)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    *data = mime_data;
+    *length = mime_data_length;
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -560,10 +603,11 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t   *surf
     int x_tile, y_tile, left, right, top, bottom;
     RECT clip;
     const cairo_color_t *background_color;
-    const unsigned char *jpeg_data;
-    unsigned int jpeg_size;
-    int jpeg_width, jpeg_height;
-    cairo_bool_t use_jpeg;
+    const unsigned char *mime_data;
+    unsigned int mime_size;
+    cairo_image_info_t mime_info;
+    cairo_bool_t use_mime;
+    DWORD mime_type;
 
     /* If we can't use StretchDIBits with this surface, we can't do anything
      * here.
@@ -593,18 +637,26 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t   *surf
 	goto CLEANUP_IMAGE;
     }
 
+    mime_type = BI_JPEG;
     status = _cairo_win32_printing_surface_check_jpeg (surface,
 						       pattern->surface,
-						       &jpeg_data,
-						       &jpeg_size,
-						       &jpeg_width,
-						       &jpeg_height);
+						       &mime_data,
+						       &mime_size,
+						       &mime_info);
+    if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
+	mime_type = BI_PNG;
+	status = _cairo_win32_printing_surface_check_png (surface,
+							  pattern->surface,
+							  &mime_data,
+							  &mime_size,
+							  &mime_info);
+    }
     if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
 	return status;
 
-    use_jpeg = (status == CAIRO_STATUS_SUCCESS);
+    use_mime = (status == CAIRO_STATUS_SUCCESS);
 
-    if (!use_jpeg && image->format != CAIRO_FORMAT_RGB24) {
+    if (!use_mime && image->format != CAIRO_FORMAT_RGB24) {
 	cairo_surface_pattern_t opaque_pattern;
 
 	opaque_surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
@@ -649,14 +701,14 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t   *surf
     }
 
     bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
-    bi.bmiHeader.biWidth = use_jpeg ? jpeg_width : opaque_image->width;
-    bi.bmiHeader.biHeight = use_jpeg ? - jpeg_height : -opaque_image->height;
-    bi.bmiHeader.biSizeImage = use_jpeg ? jpeg_size : 0;
+    bi.bmiHeader.biWidth = use_mime ? mime_info.width : opaque_image->width;
+    bi.bmiHeader.biHeight = use_mime ? - mime_info.height : -opaque_image->height;
+    bi.bmiHeader.biSizeImage = use_mime ? mime_size : 0;
     bi.bmiHeader.biXPelsPerMeter = PELS_72DPI;
     bi.bmiHeader.biYPelsPerMeter = PELS_72DPI;
     bi.bmiHeader.biPlanes = 1;
     bi.bmiHeader.biBitCount = 32;
-    bi.bmiHeader.biCompression = use_jpeg ? BI_JPEG : BI_RGB;
+    bi.bmiHeader.biCompression = use_mime ? mime_type : BI_RGB;
     bi.bmiHeader.biClrUsed = 0;
     bi.bmiHeader.biClrImportant = 0;
 
@@ -698,9 +750,9 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t   *surf
 				opaque_image->height,
 				0,
 				0,
-				use_jpeg ? jpeg_width : opaque_image->width,
-				use_jpeg ? jpeg_height : opaque_image->height,
-				use_jpeg ? jpeg_data : opaque_image->data,
+				use_mime ? mime_info.width : opaque_image->width,
+				use_mime ? mime_info.height : opaque_image->height,
+				use_mime ? mime_data : opaque_image->data,
 				&bi,
 				DIB_RGB_COLORS,
 				SRCCOPY))
diff --git a/src/cairo-win32-private.h b/src/cairo-win32-private.h
index 7b07a86..51564d0 100644
--- a/src/cairo-win32-private.h
+++ b/src/cairo-win32-private.h
@@ -120,6 +120,9 @@ enum {
 
     /* Whether we can use the CHECKJPEGFORMAT escape function */
     CAIRO_WIN32_SURFACE_CAN_CHECK_JPEG = (1<<7),
+
+    /* Whether we can use the CHECKJPEGFORMAT escape function */
+    CAIRO_WIN32_SURFACE_CAN_CHECK_PNG = (1<<8),
 };
 
 cairo_status_t
commit f59a3e03fc91dc4a1769b07bda77a364cc570bc8
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Nov 23 22:27:49 2008 +1030

    Add PNG get info function

diff --git a/src/cairo-image-info-private.h b/src/cairo-image-info-private.h
index 030b1d0..6e1c4ad 100644
--- a/src/cairo-image-info-private.h
+++ b/src/cairo-image-info-private.h
@@ -55,4 +55,9 @@ _cairo_image_info_get_jpx_info (cairo_image_info_t	*info,
 				const unsigned char	*data,
 				long			 length);
 
+cairo_private cairo_int_status_t
+_cairo_image_info_get_png_info (cairo_image_info_t     	*info,
+				const unsigned char     *data,
+				long                     length);
+
 #endif /* CAIRO_IMAGE_INFO_PRIVATE_H */
diff --git a/src/cairo-image-info.c b/src/cairo-image-info.c
index e793ba5..7742c88 100644
--- a/src/cairo-image-info.c
+++ b/src/cairo-image-info.c
@@ -36,6 +36,12 @@
 #include "cairoint.h"
 #include "cairo-image-info-private.h"
 
+static uint32_t
+_get_be32 (const unsigned char *p)
+{
+    return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
+}
+
 /* Markers with no parameters. All other markers are followed by a two
  * byte length of the parameters. */
 #define TEM       0x01
@@ -148,12 +154,6 @@ static const unsigned char _jpx_signature[] = {
     0x00, 0x00, 0x00, 0x0c, 0x6a, 0x50, 0x20, 0x20, 0x0d, 0x0a, 0x87, 0x0a
 };
 
-static uint32_t
-_get_be32 (const unsigned char *p)
-{
-    return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
-}
-
 static const unsigned char *
 _jpx_next_box (const unsigned char *p)
 {
@@ -239,3 +239,37 @@ _cairo_image_info_get_jpx_info (cairo_image_info_t	*info,
 
     return CAIRO_STATUS_SUCCESS;
 }
+
+#define PNG_IHDR 0x49484452
+
+static const unsigned char _png_magic[8] = { 137, 80, 78, 71, 13, 10, 26, 10 };
+
+cairo_int_status_t
+_cairo_image_info_get_png_info (cairo_image_info_t     *info,
+                               const unsigned char     *data,
+                               long                     length)
+{
+    const unsigned char *p = data;
+    const unsigned char *end = data + length;
+
+    if (length < 8 || memcmp (data, _png_magic, 8) != 0)
+       return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    p += 8;
+
+    /* The first chunk must be IDHR. IDHR has 13 bytes of data plus
+     * the 12 bytes of overhead for the chunk. */
+    if (p + 13 + 12 > end)
+       return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    p += 4;
+    if (_get_be32 (p) != PNG_IHDR)
+       return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    p += 4;
+    info->width = _get_be32 (p);
+    p += 4;
+    info->height = _get_be32 (p);
+
+    return CAIRO_STATUS_SUCCESS;
+}
commit 1892907e24d9f9f31942c6962aaa6d2ff9553ce7
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Nov 23 21:36:40 2008 +1030

    PDF: Disable PDF 1.5 features when version 1.4 is selected
    
    JPEG 2000 image embedding and ActualText marked content are
    PDF 1.5 features.

diff --git a/src/cairo-pdf-operators-private.h b/src/cairo-pdf-operators-private.h
index 7ff843b..4ef0fca 100644
--- a/src/cairo-pdf-operators-private.h
+++ b/src/cairo-pdf-operators-private.h
@@ -68,6 +68,7 @@ typedef struct _cairo_pdf_operators {
     cairo_scaled_font_subsets_t *font_subsets;
     cairo_pdf_operators_use_font_subset_t use_font_subset;
     void *use_font_subset_closure;
+    cairo_bool_t use_actual_text;
     cairo_bool_t in_text_object; /* inside BT/ET pair */
 
     /* PDF text state */
@@ -115,6 +116,10 @@ cairo_private void
 _cairo_pdf_operators_set_cairo_to_pdf_matrix (cairo_pdf_operators_t *pdf_operators,
 					      cairo_matrix_t 	    *cairo_to_pdf);
 
+cairo_private void
+_cairo_pdf_operators_enable_actual_text (cairo_pdf_operators_t *pdf_operators,
+					 cairo_bool_t 	  	enable);
+
 cairo_private cairo_status_t
 _cairo_pdf_operators_flush (cairo_pdf_operators_t	 *pdf_operators);
 
diff --git a/src/cairo-pdf-operators.c b/src/cairo-pdf-operators.c
index f335a37..d363805 100644
--- a/src/cairo-pdf-operators.c
+++ b/src/cairo-pdf-operators.c
@@ -68,6 +68,7 @@ _cairo_pdf_operators_init (cairo_pdf_operators_t	*pdf_operators,
     pdf_operators->in_text_object = FALSE;
     pdf_operators->num_glyphs = 0;
     pdf_operators->has_line_style = FALSE;
+    pdf_operators->use_actual_text = FALSE;
 }
 
 cairo_status_t
@@ -105,6 +106,13 @@ _cairo_pdf_operators_set_cairo_to_pdf_matrix (cairo_pdf_operators_t *pdf_operato
     pdf_operators->has_line_style = FALSE;
 }
 
+cairo_private void
+_cairo_pdf_operators_enable_actual_text (cairo_pdf_operators_t *pdf_operators,
+					 cairo_bool_t 	  	enable)
+{
+    pdf_operators->use_actual_text = enable;
+}
+
 /* Finish writing out any pending commands to the stream. This
  * function must be called by the surface before emitting anything
  * into the PDF stream.
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index bf80a94..b98f7d7 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -309,6 +309,7 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t	*output,
     _cairo_pdf_operators_set_font_subsets_callback (&surface->pdf_operators,
 						    _cairo_pdf_surface_add_font,
 						    surface);
+    _cairo_pdf_operators_enable_actual_text(&surface->pdf_operators, TRUE);
 
     surface->paginated_surface =  _cairo_paginated_surface_create (
 	                                  &surface->base,
@@ -477,6 +478,9 @@ cairo_pdf_surface_restrict_to_version (cairo_surface_t 		*abstract_surface,
 
     if (version < CAIRO_PDF_VERSION_LAST)
 	surface->pdf_version = version;
+
+    _cairo_pdf_operators_enable_actual_text(&surface->pdf_operators,
+					    version >= CAIRO_PDF_VERSION_1_5);
 }
 
 /**
@@ -1667,6 +1671,9 @@ _cairo_pdf_surface_emit_jpx_image (cairo_pdf_surface_t   *surface,
     unsigned int mime_data_length;
     cairo_image_info_t info;
 
+    if (surface->pdf_version < CAIRO_PDF_VERSION_1_5)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
     cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JP2,
 				 &mime_data, &mime_data_length);
     if (mime_data == NULL)
commit c4a57385fa2e69020f43519bea21b98182bf5fd7
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Nov 23 21:12:08 2008 +1030

    PDF: Add cairo_pdf_surface_restrict_to_version API
    
    Now that we are using PDF 1.5 features, add an api to select between
    version 1.4 or 1.5.

diff --git a/src/cairo-pdf-surface-private.h b/src/cairo-pdf-surface-private.h
index 7f2764f..d2fa43c 100644
--- a/src/cairo-pdf-surface-private.h
+++ b/src/cairo-pdf-surface-private.h
@@ -128,12 +128,14 @@ struct _cairo_pdf_surface {
     cairo_pdf_resource_t next_available_resource;
     cairo_pdf_resource_t pages_resource;
 
+    cairo_pdf_version_t pdf_version;
     cairo_bool_t compress_content;
 
     cairo_pdf_resource_t content;
     cairo_pdf_resource_t content_resources;
     cairo_pdf_group_resources_t resources;
     cairo_bool_t has_fallback_images;
+    cairo_bool_t header_emitted;
 
     struct {
 	cairo_bool_t active;
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 322c773..bf80a94 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -111,6 +111,20 @@
  *   XObject instead of using an indirect object.
  */
 
+static const cairo_pdf_version_t _cairo_pdf_versions[] =
+{
+    CAIRO_PDF_VERSION_1_4,
+    CAIRO_PDF_VERSION_1_5
+};
+
+#define CAIRO_PDF_VERSION_LAST ARRAY_LENGTH (_cairo_pdf_versions)
+
+static const char * _cairo_pdf_version_strings[CAIRO_PDF_VERSION_LAST] =
+{
+    "PDF 1.4",
+    "PDF 1.5"
+};
+
 typedef struct _cairo_pdf_object {
     long offset;
 } cairo_pdf_object_t;
@@ -273,6 +287,7 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t	*output,
         goto BAIL1;
     }
 
+    surface->pdf_version = CAIRO_PDF_VERSION_1_5;
     surface->compress_content = TRUE;
     surface->pdf_stream.active = FALSE;
     surface->pdf_stream.old_output = NULL;
@@ -285,6 +300,7 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t	*output,
     surface->force_fallbacks = FALSE;
     surface->select_pattern_gstate_saved = FALSE;
     surface->current_pattern_is_solid_color = FALSE;
+    surface->header_emitted = FALSE;
 
     _cairo_pdf_operators_init (&surface->pdf_operators,
 			       surface->output,
@@ -294,12 +310,6 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t	*output,
 						    _cairo_pdf_surface_add_font,
 						    surface);
 
-    /* Document header */
-    _cairo_output_stream_printf (surface->output,
-				 "%%PDF-1.5\n");
-    _cairo_output_stream_printf (surface->output,
-				 "%%%c%c%c%c\n", 181, 237, 174, 251);
-
     surface->paginated_surface =  _cairo_paginated_surface_create (
 	                                  &surface->base,
 					  CAIRO_CONTENT_COLOR_ALPHA,
@@ -438,6 +448,80 @@ _extract_pdf_surface (cairo_surface_t		 *surface,
 }
 
 /**
+ * cairo_pdf_surface_restrict_to_version:
+ * @surface: a PDF #cairo_surface_t
+ * @version: PDF version
+ *
+ * Restricts the generated PDF file to @version. See cairo_pdf_get_versions()
+ * for a list of available version values that can be used here.
+ *
+ * This function should only be called before any drawing operations
+ * have been performed on the given surface. The simplest way to do
+ * this is to call this function immediately after creating the
+ * surface.
+ *
+ * Since: 1.10
+ **/
+void
+cairo_pdf_surface_restrict_to_version (cairo_surface_t 		*abstract_surface,
+				       cairo_pdf_version_t  	 version)
+{
+    cairo_pdf_surface_t *surface = NULL; /* hide compiler warning */
+    cairo_status_t status;
+
+    status = _extract_pdf_surface (abstract_surface, &surface);
+    if (status) {
+	status = _cairo_surface_set_error (abstract_surface, status);
+	return;
+    }
+
+    if (version < CAIRO_PDF_VERSION_LAST)
+	surface->pdf_version = version;
+}
+
+/**
+ * cairo_pdf_get_versions:
+ * @versions: supported version list
+ * @num_versions: list length
+ *
+ * Used to retrieve the list of supported versions. See
+ * cairo_pdf_surface_restrict_to_version().
+ *
+ * Since: 1.10
+ **/
+void
+cairo_pdf_get_versions (cairo_pdf_version_t const	**versions,
+                        int                     	 *num_versions)
+{
+    if (versions != NULL)
+	*versions = _cairo_pdf_versions;
+
+    if (num_versions != NULL)
+	*num_versions = CAIRO_PDF_VERSION_LAST;
+}
+
+/**
+ * cairo_pdf_version_to_string:
+ * @version: a version id
+ *
+ * Get the string representation of the given @version id. This function
+ * will return %NULL if @version isn't valid. See cairo_pdf_get_versions()
+ * for a way to get the list of valid version ids.
+ *
+ * Return value: the string associated to given version.
+ *
+ * Since: 1.10
+ **/
+const char *
+cairo_pdf_version_to_string (cairo_pdf_version_t version)
+{
+    if (version >= CAIRO_PDF_VERSION_LAST)
+	return NULL;
+
+    return _cairo_pdf_version_strings[version];
+}
+
+/**
  * cairo_pdf_surface_set_size:
  * @surface: a PDF #cairo_surface_t
  * @width_in_points: new surface width, in points (1 point == 1/72.0 inch)
@@ -1291,6 +1375,26 @@ _cairo_pdf_surface_start_page (void *abstract_surface)
 {
     cairo_pdf_surface_t *surface = abstract_surface;
 
+    /* Document header */
+    if (! surface->header_emitted) {
+	const char *version;
+
+	switch (surface->pdf_version) {
+	case CAIRO_PDF_VERSION_1_4:
+	    version = "1.4";
+	    break;
+	case CAIRO_PDF_VERSION_1_5:
+	    version = "1.5";
+	    break;
+	}
+
+	_cairo_output_stream_printf (surface->output,
+				     "%%PDF-%s\n", version);
+	_cairo_output_stream_printf (surface->output,
+				     "%%%c%c%c%c\n", 181, 237, 174, 251);
+	surface->header_emitted = TRUE;
+    }
+
     _cairo_pdf_group_resources_clear (&surface->resources);
 
     return CAIRO_STATUS_SUCCESS;
diff --git a/src/cairo-pdf.h b/src/cairo-pdf.h
index 1a066b3..294f36d 100644
--- a/src/cairo-pdf.h
+++ b/src/cairo-pdf.h
@@ -43,6 +43,19 @@
 
 CAIRO_BEGIN_DECLS
 
+/**
+ * cairo_pdf_version_t:
+ * @CAIRO_PDF_VERSION_1_4: The version 1.4 of the PDF specification.
+ * @CAIRO_PDF_VERSION_1_5: The version 1.5 of the PDF specification.
+ *
+ * #cairo_pdf_version_t is used to describe the version number of the PDF
+ * specification that a generated PDF file will conform to.
+ */
+typedef enum _cairo_pdf_version {
+    CAIRO_PDF_VERSION_1_4,
+    CAIRO_PDF_VERSION_1_5
+} cairo_pdf_version_t;
+
 cairo_public cairo_surface_t *
 cairo_pdf_surface_create (const char		*filename,
 			  double		 width_in_points,
@@ -55,6 +68,17 @@ cairo_pdf_surface_create_for_stream (cairo_write_func_t	write_func,
 				     double		height_in_points);
 
 cairo_public void
+cairo_pdf_surface_restrict_to_version (cairo_surface_t 		*surface,
+				       cairo_pdf_version_t  	 version);
+
+cairo_public void
+cairo_pdf_get_versions (cairo_pdf_version_t const	**versions,
+                        int                      	 *num_versions);
+
+cairo_public const char *
+cairo_pdf_version_to_string (cairo_pdf_version_t version);
+
+cairo_public void
 cairo_pdf_surface_set_size (cairo_surface_t	*surface,
 			    double		 width_in_points,
 			    double		 height_in_points);
commit d85e836911d661275c29f2348a047e5d911f9004
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Nov 23 21:03:22 2008 +1030

    PDF: Add newline to end of binary streams
    
    PDF requires white space before the "endstream"

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 6d007ad..322c773 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -1588,6 +1588,7 @@ _cairo_pdf_surface_emit_jpx_image (cairo_pdf_surface_t   *surface,
 
     *res = surface->pdf_stream.self;
     _cairo_output_stream_write (surface->output, mime_data, mime_data_length);
+    _cairo_output_stream_printf (surface->output, "\n");
     status = _cairo_pdf_surface_close_stream (surface);
 
     *width = info.width;
@@ -1639,6 +1640,7 @@ _cairo_pdf_surface_emit_jpeg_image (cairo_pdf_surface_t   *surface,
 
     *res = surface->pdf_stream.self;
     _cairo_output_stream_write (surface->output, mime_data, mime_data_length);
+    _cairo_output_stream_printf (surface->output, "\n");
     status = _cairo_pdf_surface_close_stream (surface);
 
     *width = info.width;
commit b87d81ef0bb52570385a3c9e331651cbeb87b2bb
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Nov 23 19:29:26 2008 +1030

    Add image/jp2 to mime-data test

diff --git a/test/jp2.jp2 b/test/jp2.jp2
new file mode 100644
index 0000000..fe8dd6e
Binary files /dev/null and b/test/jp2.jp2 differ
diff --git a/test/mime-data.c b/test/mime-data.c
index ec855f8..febc322 100644
--- a/test/mime-data.c
+++ b/test/mime-data.c
@@ -116,6 +116,7 @@ draw (cairo_t *cr, int width, int height)
 {
     const char jpg_filename[] = "jpeg.jpg";
     const char png_filename[] = "png.png";
+    const char jp2_filename[] = "jp2.jp2";
     cairo_test_status_t status;
 
     status = paint_file (cr, jpg_filename, CAIRO_MIME_TYPE_JPEG, 0, 0);
@@ -126,6 +127,10 @@ draw (cairo_t *cr, int width, int height)
     if (status)
 	return status;
 
+    status = paint_file (cr, jp2_filename, CAIRO_MIME_TYPE_JP2, 0, 100);
+    if (status)
+	return status;
+
     return CAIRO_TEST_SUCCESS;
 }
 
@@ -133,5 +138,5 @@ CAIRO_TEST (mime_data,
 	    "Check that the mime-data embedding works",
 	    "jpeg, api", /* keywords */
 	    NULL, /* requirements */
-	    200, 100,
+	    200, 150,
 	    NULL, draw)
diff --git a/test/mime-data.pdf.ref.png b/test/mime-data.pdf.ref.png
index ebfcb79..90a08f5 100644
Binary files a/test/mime-data.pdf.ref.png and b/test/mime-data.pdf.ref.png differ
diff --git a/test/mime-data.ps.ref.png b/test/mime-data.ps.ref.png
index ebfcb79..721fb9c 100644
Binary files a/test/mime-data.ps.ref.png and b/test/mime-data.ps.ref.png differ
diff --git a/test/mime-data.ref.png b/test/mime-data.ref.png
index ccbf1b6..3a912c5 100644
Binary files a/test/mime-data.ref.png and b/test/mime-data.ref.png differ
diff --git a/test/mime-data.svg.ref.png b/test/mime-data.svg.ref.png
index 96a7bec..81fde72 100644
Binary files a/test/mime-data.svg.ref.png and b/test/mime-data.svg.ref.png differ
commit 7fdb712cbaadc95c02f607a9f6c995f8beb01342
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Nov 23 18:56:12 2008 +1030

    PDF: Add JPEG2000 image embedding
    
    Requires increasing the PDF version to 1.5.

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index afc56da..6d007ad 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -296,7 +296,7 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t	*output,
 
     /* Document header */
     _cairo_output_stream_printf (surface->output,
-				 "%%PDF-1.4\n");
+				 "%%PDF-1.5\n");
     _cairo_output_stream_printf (surface->output,
 				 "%%%c%c%c%c\n", 181, 237, 174, 251);
 
@@ -1552,6 +1552,51 @@ CLEANUP:
 }
 
 static cairo_int_status_t
+_cairo_pdf_surface_emit_jpx_image (cairo_pdf_surface_t   *surface,
+				   cairo_surface_t	 *source,
+				   cairo_pdf_resource_t  *res,
+				   int                   *width,
+				   int                   *height)
+{
+    cairo_status_t status;
+    const unsigned char *mime_data;
+    unsigned int mime_data_length;
+    cairo_image_info_t info;
+
+    cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JP2,
+				 &mime_data, &mime_data_length);
+    if (mime_data == NULL)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    status = _cairo_image_info_get_jpx_info (&info, mime_data, mime_data_length);
+    if (status)
+	return status;
+
+    status = _cairo_pdf_surface_open_stream (surface,
+					     NULL,
+					     FALSE,
+					     "   /Type /XObject\n"
+					     "   /Subtype /Image\n"
+					     "   /Width %d\n"
+					     "   /Height %d\n"
+					     "   /ColorSpace /DeviceRGB\n"
+					     "   /Filter /JPXDecode\n",
+					     info.width,
+					     info.height);
+    if (status)
+	return status;
+
+    *res = surface->pdf_stream.self;
+    _cairo_output_stream_write (surface->output, mime_data, mime_data_length);
+    status = _cairo_pdf_surface_close_stream (surface);
+
+    *width = info.width;
+    *height = info.height;
+
+    return status;
+}
+
+static cairo_int_status_t
 _cairo_pdf_surface_emit_jpeg_image (cairo_pdf_surface_t   *surface,
 				    cairo_surface_t	  *source,
 				    cairo_pdf_resource_t  *res,
@@ -1619,6 +1664,11 @@ _cairo_pdf_surface_emit_image_surface (cairo_pdf_surface_t     *surface,
     int x = 0;
     int y = 0;
 
+    status = _cairo_pdf_surface_emit_jpx_image (surface, pattern->surface,
+						resource, width, height);
+    if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+	return status;
+
     status = _cairo_pdf_surface_emit_jpeg_image (surface, pattern->surface,
 						 resource, width, height);
     if (status != CAIRO_INT_STATUS_UNSUPPORTED)
commit 0746efbf0718095920d9258942d32a7023d22131
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Nov 23 18:47:13 2008 +1030

    Add JPEG2000 mimetype and image info function

diff --git a/src/cairo-image-info-private.h b/src/cairo-image-info-private.h
index 42878cb..030b1d0 100644
--- a/src/cairo-image-info-private.h
+++ b/src/cairo-image-info-private.h
@@ -50,5 +50,9 @@ _cairo_image_info_get_jpeg_info (cairo_image_info_t	*info,
 				 const unsigned char	*data,
 				 long			 length);
 
+cairo_private cairo_int_status_t
+_cairo_image_info_get_jpx_info (cairo_image_info_t	*info,
+				const unsigned char	*data,
+				long			 length);
 
 #endif /* CAIRO_IMAGE_INFO_PRIVATE_H */
diff --git a/src/cairo-image-info.c b/src/cairo-image-info.c
index bac0bd0..e793ba5 100644
--- a/src/cairo-image-info.c
+++ b/src/cairo-image-info.c
@@ -139,3 +139,103 @@ _cairo_image_info_get_jpeg_info (cairo_image_info_t	*info,
 
     return CAIRO_STATUS_SUCCESS;
 }
+
+#define JPX_FILETYPE 0x66747970
+#define JPX_JP2_HEADER 0x6A703268
+#define JPX_IMAGE_HEADER 0x69686472
+
+static const unsigned char _jpx_signature[] = {
+    0x00, 0x00, 0x00, 0x0c, 0x6a, 0x50, 0x20, 0x20, 0x0d, 0x0a, 0x87, 0x0a
+};
+
+static uint32_t
+_get_be32 (const unsigned char *p)
+{
+    return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
+}
+
+static const unsigned char *
+_jpx_next_box (const unsigned char *p)
+{
+    return p + _get_be32 (p);
+}
+
+static const unsigned char *
+_jpx_get_box_contents (const unsigned char *p)
+{
+    return p + 8;
+}
+
+static cairo_bool_t
+_jpx_match_box (const unsigned char *p, const unsigned char *end, uint32_t type)
+{
+    uint length;
+
+    if (p + 8 < end) {
+	length = _get_be32 (p);
+	if (_get_be32 (p + 4) == type &&  p + length < end)
+	    return TRUE;
+    }
+
+    return FALSE;
+}
+
+static const unsigned char *
+_jpx_find_box (const unsigned char *p, const unsigned char *end, uint32_t type)
+{
+    while (p < end) {
+	if (_jpx_match_box (p, end, type))
+	    return p;
+	p = _jpx_next_box (p);
+    }
+
+    return NULL;
+}
+
+static void
+_jpx_extract_info (const unsigned char *p, cairo_image_info_t *info)
+{
+    info->height = _get_be32 (p);
+    info->width = _get_be32 (p + 4);
+    info->num_components = (p[8] << 8) + p[9];
+    info->bits_per_component = p[10];
+}
+
+cairo_int_status_t
+_cairo_image_info_get_jpx_info (cairo_image_info_t	*info,
+				const unsigned char	*data,
+				long			 length)
+{
+    const unsigned char *p = data;
+    const unsigned char *end = data + length;
+
+    /* First 12 bytes must be the JPEG 2000 signature box. */
+    if (length < ARRAY_LENGTH(_jpx_signature) ||
+	memcmp(p, _jpx_signature, ARRAY_LENGTH(_jpx_signature)) != 0)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    p += ARRAY_LENGTH(_jpx_signature);
+
+    /* Next box must be a File Type Box */
+    if (! _jpx_match_box (p, end, JPX_FILETYPE))
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    p = _jpx_next_box (p);
+
+    /* Locate the JP2 header box. */
+    p = _jpx_find_box (p, end, JPX_JP2_HEADER);
+    if (!p)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    /* Step into the JP2 header box. First box must be the Image
+     * Header */
+    p = _jpx_get_box_contents (p);
+    if (! _jpx_match_box (p, end, JPX_IMAGE_HEADER))
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    /* Get the image info */
+    p = _jpx_get_box_contents (p);
+    _jpx_extract_info (p, info);
+
+    return CAIRO_STATUS_SUCCESS;
+}
diff --git a/src/cairo-surface-fallback.c b/src/cairo-surface-fallback.c
index bb29a9f..2dcaa58 100644
--- a/src/cairo-surface-fallback.c
+++ b/src/cairo-surface-fallback.c
@@ -1039,6 +1039,7 @@ _cairo_surface_fallback_snapshot (cairo_surface_t *surface)
     const char *mime_types[] = {
 	CAIRO_MIME_TYPE_JPEG,
 	CAIRO_MIME_TYPE_PNG,
+	CAIRO_MIME_TYPE_JP2,
 	NULL
     }, **mime_type;
 
diff --git a/src/cairo.h b/src/cairo.h
index 3365523..8f57ae0 100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -1951,6 +1951,7 @@ cairo_surface_set_user_data (cairo_surface_t		 *surface,
 
 #define CAIRO_MIME_TYPE_JPEG "image/jpeg"
 #define CAIRO_MIME_TYPE_PNG "image/png"
+#define CAIRO_MIME_TYPE_JP2 "image/jp2"
 
 cairo_public void
 cairo_surface_get_mime_data (cairo_surface_t		*surface,
commit 5de1e4de938d03406ce3364c6c1baa958f210410
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Nov 23 18:33:58 2008 +1030

    Move cairo-jpeg-info.c to cairo-image-info.c
    
    Other image formats will be added to the same file.

diff --git a/src/Makefile.sources b/src/Makefile.sources
index 58781dd..5d643dc 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -64,7 +64,7 @@ cairo_private = \
 	cairo-freelist-private.h \
 	cairo-gstate-private.h \
 	cairo-hash-private.h \
-	cairo-jpeg-info-private.h \
+	cairo-image-info-private.h \
 	cairo-malloc-private.h \
 	cairo-meta-surface-private.h \
 	cairo-mutex-impl-private.h \
@@ -109,8 +109,8 @@ cairo_sources = \
 	cairo-gstate.c \
 	cairo-hash.c \
 	cairo-hull.c \
+	cairo-image-info.c \
 	cairo-image-surface.c \
-	cairo-jpeg-info.c \
 	cairo-lzw.c \
 	cairo-matrix.c \
 	cairo-meta-surface.c \
diff --git a/src/cairo-image-info-private.h b/src/cairo-image-info-private.h
new file mode 100644
index 0000000..42878cb
--- /dev/null
+++ b/src/cairo-image-info-private.h
@@ -0,0 +1,54 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2008 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 the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is Adrian Johnson.
+ *
+ * Contributor(s):
+ *	Adrian Johnson <ajohnson at redneon.com>
+ */
+
+#ifndef CAIRO_IMAGE_INFO_PRIVATE_H
+#define CAIRO_IMAGE_INFO_PRIVATE_H
+
+#include "cairoint.h"
+
+typedef struct _cairo_image_info {
+    int		 width;
+    int		 height;
+    int		 num_components;
+    int		 bits_per_component;
+} cairo_image_info_t;
+
+cairo_private cairo_int_status_t
+_cairo_image_info_get_jpeg_info (cairo_image_info_t	*info,
+				 const unsigned char	*data,
+				 long			 length);
+
+
+#endif /* CAIRO_IMAGE_INFO_PRIVATE_H */
diff --git a/src/cairo-image-info.c b/src/cairo-image-info.c
new file mode 100644
index 0000000..bac0bd0
--- /dev/null
+++ b/src/cairo-image-info.c
@@ -0,0 +1,141 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2008 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 the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is Adrian Johnson.
+ *
+ * Contributor(s):
+ *	Adrian Johnson <ajohnson at redneon.com>
+ */
+
+#include "cairoint.h"
+#include "cairo-image-info-private.h"
+
+/* Markers with no parameters. All other markers are followed by a two
+ * byte length of the parameters. */
+#define TEM       0x01
+#define RST_begin 0xd0
+#define RST_end   0xd7
+#define SOI       0xd8
+#define EOI       0xd9
+
+/* Start of frame markers. */
+#define SOF0  0xc0
+#define SOF1  0xc1
+#define SOF2  0xc2
+#define SOF3  0xc3
+#define SOF5  0xc5
+#define SOF6  0xc6
+#define SOF7  0xc7
+#define SOF9  0xc9
+#define SOF10 0xca
+#define SOF11 0xcb
+#define SOF13 0xcd
+#define SOF14 0xce
+#define SOF15 0xcf
+
+static const unsigned char *
+_jpeg_skip_segment (const unsigned char *p)
+{
+    int len;
+
+    p++;
+    len = (p[0] << 8) | p[1];
+
+    return p + len;
+}
+
+static void
+_jpeg_extract_info (cairo_image_info_t *info, const unsigned char *p)
+{
+    info->width = (p[6] << 8) + p[7];
+    info->height = (p[4] << 8) + p[5];
+    info->num_components = p[8];
+    info->bits_per_component = p[3];
+}
+
+cairo_int_status_t
+_cairo_image_info_get_jpeg_info (cairo_image_info_t	*info,
+				 const unsigned char	*data,
+				 long			 length)
+{
+    const unsigned char *p = data;
+
+    while (p + 1 < data + length) {
+	if (*p != 0xff)
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
+	p++;
+
+	switch (*p) {
+	    /* skip fill bytes */
+	case 0xff:
+	    p++;
+	    break;
+
+	case TEM:
+	case SOI:
+	case EOI:
+	    p++;
+	    break;
+
+	case SOF0:
+	case SOF1:
+	case SOF2:
+	case SOF3:
+	case SOF5:
+	case SOF6:
+	case SOF7:
+	case SOF9:
+	case SOF10:
+	case SOF11:
+	case SOF13:
+	case SOF14:
+	case SOF15:
+	    /* Start of frame found. Extract the image parameters. */
+	    if (p + 8 > data + length)
+		return CAIRO_INT_STATUS_UNSUPPORTED;
+
+	    _jpeg_extract_info (info, p);
+	    return CAIRO_STATUS_SUCCESS;
+
+	default:
+	    if (*p >= RST_begin && *p <= RST_end) {
+		p++;
+		break;
+	    }
+
+	    if (p + 2 > data + length)
+		return CAIRO_INT_STATUS_UNSUPPORTED;
+
+	    p = _jpeg_skip_segment (p);
+	    break;
+	}
+    }
+
+    return CAIRO_STATUS_SUCCESS;
+}
diff --git a/src/cairo-jpeg-info-private.h b/src/cairo-jpeg-info-private.h
deleted file mode 100644
index 365825c..0000000
--- a/src/cairo-jpeg-info-private.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/* cairo - a vector graphics library with display and print output
- *
- * Copyright © 2008 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 the cairo graphics library.
- *
- * The Initial Developer of the Original Code is Adrian Johnson.
- *
- * Contributor(s):
- *	Adrian Johnson <ajohnson at redneon.com>
- */
-
-#ifndef CAIRO_JPEG_INFO_PRIVATE_H
-#define CAIRO_JPEG_INFO_PRIVATE_H
-
-#include "cairoint.h"
-
-typedef struct _cairo_jpeg_info {
-    int		 width;
-    int		 height;
-    int		 num_components;
-    int		 bits_per_component;
-} cairo_jpeg_info_t;
-
-cairo_private cairo_int_status_t
-_cairo_jpeg_get_info (const unsigned char	*data,
-		      long			 length,
-		      cairo_jpeg_info_t		*info);
-
-
-#endif /* CAIRO_JPEG_INFO_PRIVATE_H */
diff --git a/src/cairo-jpeg-info.c b/src/cairo-jpeg-info.c
deleted file mode 100644
index ca85cef..0000000
--- a/src/cairo-jpeg-info.c
+++ /dev/null
@@ -1,141 +0,0 @@
-/* cairo - a vector graphics library with display and print output
- *
- * Copyright © 2008 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 the cairo graphics library.
- *
- * The Initial Developer of the Original Code is Adrian Johnson.
- *
- * Contributor(s):
- *	Adrian Johnson <ajohnson at redneon.com>
- */
-
-#include "cairoint.h"
-#include "cairo-jpeg-info-private.h"
-
-/* Markers with no parameters. All other markers are followed by a two
- * byte length of the parameters. */
-#define TEM       0x01
-#define RST_begin 0xd0
-#define RST_end   0xd7
-#define SOI       0xd8
-#define EOI       0xd9
-
-/* Start of frame markers. */
-#define SOF0  0xc0
-#define SOF1  0xc1
-#define SOF2  0xc2
-#define SOF3  0xc3
-#define SOF5  0xc5
-#define SOF6  0xc6
-#define SOF7  0xc7
-#define SOF9  0xc9
-#define SOF10 0xca
-#define SOF11 0xcb
-#define SOF13 0xcd
-#define SOF14 0xce
-#define SOF15 0xcf
-
-static const unsigned char *
-_skip_segment (const unsigned char *p)
-{
-    int len;
-
-    p++;
-    len = (p[0] << 8) | p[1];
-
-    return p + len;
-}
-
-static void
-_extract_info (cairo_jpeg_info_t *info, const unsigned char *p)
-{
-    info->width = (p[6] << 8) + p[7];
-    info->height = (p[4] << 8) + p[5];
-    info->num_components = p[8];
-    info->bits_per_component = p[3];
-}
-
-cairo_int_status_t
-_cairo_jpeg_get_info (const unsigned char	*data,
-		      long			length,
-		      cairo_jpeg_info_t		*info)
-{
-    const unsigned char *p = data;
-
-    while (p + 1 < data + length) {
-	if (*p != 0xff)
-	    return CAIRO_INT_STATUS_UNSUPPORTED;
-	p++;
-
-	switch (*p) {
-	    /* skip fill bytes */
-	case 0xff:
-	    p++;
-	    break;
-
-	case TEM:
-	case SOI:
-	case EOI:
-	    p++;
-	    break;
-
-	case SOF0:
-	case SOF1:
-	case SOF2:
-	case SOF3:
-	case SOF5:
-	case SOF6:
-	case SOF7:
-	case SOF9:
-	case SOF10:
-	case SOF11:
-	case SOF13:
-	case SOF14:
-	case SOF15:
-	    /* Start of frame found. Extract the image parameters. */
-	    if (p + 8 > data + length)
-		return CAIRO_INT_STATUS_UNSUPPORTED;
-
-	    _extract_info (info, p);
-	    return CAIRO_STATUS_SUCCESS;
-
-	default:
-	    if (*p >= RST_begin && *p <= RST_end) {
-		p++;
-		break;
-	    }
-
-	    if (p + 2 > data + length)
-		return CAIRO_INT_STATUS_UNSUPPORTED;
-
-	    p = _skip_segment (p);
-	    break;
-	}
-    }
-
-    return CAIRO_STATUS_SUCCESS;
-}
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 6edea4a..afc56da 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -45,12 +45,12 @@
 #include "cairo-pdf-surface-private.h"
 #include "cairo-pdf-operators-private.h"
 #include "cairo-analysis-surface-private.h"
+#include "cairo-image-info-private.h"
 #include "cairo-meta-surface-private.h"
 #include "cairo-output-stream-private.h"
 #include "cairo-paginated-private.h"
 #include "cairo-scaled-font-subsets-private.h"
 #include "cairo-type3-glyph-surface-private.h"
-#include "cairo-jpeg-info-private.h"
 
 #include <time.h>
 #include <zlib.h>
@@ -1561,14 +1561,14 @@ _cairo_pdf_surface_emit_jpeg_image (cairo_pdf_surface_t   *surface,
     cairo_status_t status;
     const unsigned char *mime_data;
     unsigned int mime_data_length;
-    cairo_jpeg_info_t info;
+    cairo_image_info_t info;
 
     cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JPEG,
 				 &mime_data, &mime_data_length);
     if (mime_data == NULL)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
-    status = _cairo_jpeg_get_info (mime_data, mime_data_length, &info);
+    status = _cairo_image_info_get_jpeg_info (&info, mime_data, mime_data_length);
     if (status)
 	return status;
 
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index f4431fa..0c9ef7f 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -63,7 +63,7 @@
 #include "cairo-meta-surface-private.h"
 #include "cairo-output-stream-private.h"
 #include "cairo-type3-glyph-surface-private.h"
-#include "cairo-jpeg-info-private.h"
+#include "cairo-image-info-private.h"
 
 #include <stdio.h>
 #include <ctype.h>
@@ -2130,14 +2130,14 @@ _cairo_ps_surface_emit_jpeg_image (cairo_ps_surface_t    *surface,
     cairo_status_t status;
     const unsigned char *mime_data;
     unsigned int mime_data_length;
-    cairo_jpeg_info_t info;
+    cairo_image_info_t info;
 
     cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JPEG,
 				 &mime_data, &mime_data_length);
     if (mime_data == NULL)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
-    status = _cairo_jpeg_get_info (mime_data, mime_data_length, &info);
+    status = _cairo_image_info_get_jpeg_info (&info, mime_data, mime_data_length);
     if (status)
 	return status;
 
diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index cfc56c4..ab2e4b9 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -43,7 +43,7 @@
 #include "cairoint.h"
 #include "cairo-svg.h"
 #include "cairo-analysis-surface-private.h"
-#include "cairo-jpeg-info-private.h"
+#include "cairo-image-info-private.h"
 #include "cairo-meta-surface-private.h"
 #include "cairo-output-stream-private.h"
 #include "cairo-path-fixed-private.h"
@@ -982,7 +982,7 @@ _cairo_surface_base64_encode_jpeg (cairo_surface_t       *surface,
 {
     const unsigned char *mime_data;
     unsigned int mime_data_length;
-    cairo_jpeg_info_t jpeg_info;
+    cairo_image_info_t image_info;
     base64_write_closure_t info;
     cairo_status_t status;
 
@@ -991,7 +991,7 @@ _cairo_surface_base64_encode_jpeg (cairo_surface_t       *surface,
     if (mime_data == NULL)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
-    status = _cairo_jpeg_get_info (mime_data, mime_data_length, &jpeg_info);
+    status = _cairo_image_info_get_jpeg_info (&image_info, mime_data, mime_data_length);
     if (status)
 	return status;
 
diff --git a/src/cairo-win32-printing-surface.c b/src/cairo-win32-printing-surface.c
index 34b31c7..625f4b0 100644
--- a/src/cairo-win32-printing-surface.c
+++ b/src/cairo-win32-printing-surface.c
@@ -52,7 +52,7 @@
 #include "cairo-win32-private.h"
 #include "cairo-meta-surface-private.h"
 #include "cairo-scaled-font-subsets-private.h"
-#include "cairo-jpeg-info-private.h"
+#include "cairo-image-info-private.h"
 
 #include <windows.h>
 
@@ -511,7 +511,7 @@ _cairo_win32_printing_surface_check_jpeg (cairo_win32_surface_t   *surface,
 {
     const unsigned char *mime_data;
     unsigned int mime_data_length;
-    cairo_jpeg_info_t info;
+    cairo_image_info_t info;
     cairo_int_status_t status;
     DWORD result;
 
@@ -523,7 +523,7 @@ _cairo_win32_printing_surface_check_jpeg (cairo_win32_surface_t   *surface,
     if (mime_data == NULL)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
-    status = _cairo_jpeg_get_info (mime_data, mime_data_length, &info);
+    status = _cairo_image_info_get_jpeg_info (&info, mime_data, mime_data_length);
     if (status)
 	return status;
 


More information about the cairo-commit mailing list