summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Johnson <ajohnson@redneon.com>2013-09-14 20:59:56 +0930
committerAdrian Johnson <ajohnson@redneon.com>2013-09-15 20:50:46 +0930
commit5c0caa6f82374ec38a33d5f25a725f60bc121887 (patch)
treef72d0efad6b57d4592713831c7c863de4e5432dc
parent2d6705671a900251f00c6b59375bd4d23ec6b4d0 (diff)
pdf: support JBIG2 mime data
JBIG2 images may have shared global data that is stored in a separate stream in PDF. The CAIRO_MIME_TYPE_JBIG2 mime type is for the JBIG2 data for each image. All images that use global data must also set CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID to a unique identifier. One of the images must also set CAIRO_MIME_TYPE_JBIG2_GLOBAL to the global data. The global data will be shared by all JBIG2 images with the same CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID.
-rw-r--r--src/cairo-device.c1
-rw-r--r--src/cairo-error-private.h1
-rw-r--r--src/cairo-image-info-private.h68
-rw-r--r--src/cairo-image-info.c427
-rw-r--r--src/cairo-misc.c2
-rw-r--r--src/cairo-pdf-surface-private.h8
-rw-r--r--src/cairo-pdf-surface.c182
-rw-r--r--src/cairo-region.c1
-rw-r--r--src/cairo-spans.c250
-rw-r--r--src/cairo-surface.c4
-rw-r--r--src/cairo.c4
-rw-r--r--src/cairo.h6
12 files changed, 952 insertions, 2 deletions
diff --git a/src/cairo-device.c b/src/cairo-device.c
index 098f856..585a9c1 100644
--- a/src/cairo-device.c
+++ b/src/cairo-device.c
@@ -158,6 +158,7 @@ _cairo_device_create_in_error (cairo_status_t status)
case CAIRO_STATUS_INVALID_CONTENT:
case CAIRO_STATUS_INVALID_MESH_CONSTRUCTION:
case CAIRO_STATUS_DEVICE_FINISHED:
+ case CAIRO_STATUS_JBIG2_GLOBAL_MISSING:
default:
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
return (cairo_device_t *) &_nil_device;
diff --git a/src/cairo-error-private.h b/src/cairo-error-private.h
index ea9c2ea..2d170ef 100644
--- a/src/cairo-error-private.h
+++ b/src/cairo-error-private.h
@@ -90,6 +90,7 @@ enum _cairo_int_status {
CAIRO_INT_STATUS_DEVICE_ERROR,
CAIRO_INT_STATUS_INVALID_MESH_CONSTRUCTION,
CAIRO_INT_STATUS_DEVICE_FINISHED,
+ CAIRO_INT_STATUS_JBIG2_GLOBAL_MISSING,
CAIRO_INT_STATUS_LAST_STATUS,
diff --git a/src/cairo-image-info-private.h b/src/cairo-image-info-private.h
index 0d9ef84..e64928e 100644
--- a/src/cairo-image-info-private.h
+++ b/src/cairo-image-info-private.h
@@ -0,0 +1,68 @@
+/* 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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@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);
+
+cairo_private cairo_int_status_t
+_cairo_image_info_get_jpx_info (cairo_image_info_t *info,
+ const unsigned char *data,
+ unsigned long length);
+
+cairo_private cairo_int_status_t
+_cairo_image_info_get_png_info (cairo_image_info_t *info,
+ const unsigned char *data,
+ unsigned long length);
+
+cairo_private cairo_int_status_t
+_cairo_image_info_get_jbig2_info (cairo_image_info_t *info,
+ const unsigned char *data,
+ unsigned long length);
+
+#endif /* CAIRO_IMAGE_INFO_PRIVATE_H */
diff --git a/src/cairo-image-info.c b/src/cairo-image-info.c
index 4489698..64053a2 100644
--- a/src/cairo-image-info.c
+++ b/src/cairo-image-info.c
@@ -0,0 +1,427 @@
+/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
+/* 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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@redneon.com>
+ */
+
+#include "cairoint.h"
+
+#include "cairo-error-private.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];
+}
+
+/* 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
+#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;
+}
+
+/* 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
+
+static const unsigned char _jpx_signature[] = {
+ 0x00, 0x00, 0x00, 0x0c, 0x6a, 0x50, 0x20, 0x20, 0x0d, 0x0a, 0x87, 0x0a
+};
+
+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)
+{
+ uint32_t 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,
+ unsigned 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;
+}
+
+/* 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 };
+
+cairo_int_status_t
+_cairo_image_info_get_png_info (cairo_image_info_t *info,
+ const unsigned char *data,
+ unsigned 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;
+}
+
+static const unsigned char *
+_jbig2_find_data_end (const unsigned char *p,
+ const unsigned char *end,
+ int type)
+{
+ unsigned char end_seq[2];
+ int mmr;
+
+ /* Segments of type "Immediate generic region" may have an
+ * unspecified data length. The JBIG2 specification specifies the
+ * method to find the end of the data for these segments. */
+ if (type == 36 || type == 38 || type == 39) {
+ if (p + 18 < end) {
+ mmr = p[17] & 0x01;
+ if (mmr) {
+ /* MMR encoding ends with 0x00, 0x00 */
+ end_seq[0] = 0x00;
+ end_seq[1] = 0x00;
+ } else {
+ /* Template encoding ends with 0xff, 0xac */
+ end_seq[0] = 0xff;
+ end_seq[1] = 0xac;
+ }
+ p += 18;
+ while (p < end) {
+ if (p[0] == end_seq[0] && p[1] == end_seq[1]) {
+ /* Skip the 2 terminating bytes and the 4 byte row count that follows. */
+ p += 6;
+ if (p < end)
+ return p;
+ }
+ p++;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+static const unsigned char *
+_jbig2_get_next_segment (const unsigned char *p,
+ const unsigned char *end,
+ int *type,
+ const unsigned char **data,
+ unsigned long *data_len)
+{
+ unsigned long seg_num;
+ cairo_bool_t big_page_size;
+ int num_segs;
+ int ref_seg_bytes;
+ int referred_size;
+
+ if (p + 6 >= end)
+ return NULL;
+
+ seg_num = _get_be32 (p);
+ *type = p[4] & 0x3f;
+ big_page_size = (p[4] & 0x40) != 0;
+ p += 5;
+
+ num_segs = p[0] >> 5;
+ if (num_segs == 7) {
+ num_segs = _get_be32 (p) & 0x1fffffff;
+ ref_seg_bytes = 4 + ((num_segs + 1)/8);
+ } else {
+ ref_seg_bytes = 1;
+ }
+ p += ref_seg_bytes;
+
+ if (seg_num <= 256)
+ referred_size = 1;
+ else if (seg_num <= 65536)
+ referred_size = 2;
+ else
+ referred_size = 4;
+
+ p += num_segs * referred_size;
+ p += big_page_size ? 4 : 1;
+ if (p + 4 >= end)
+ return NULL;
+
+ *data_len = _get_be32 (p);
+ p += 4;
+ *data = p;
+
+ if (*data_len == 0xffffffff) {
+ /* if data length is -1 we have to scan through the data to find the end */
+ p = _jbig2_find_data_end (*data, end, *type);
+ if (!p || p >= end)
+ return NULL;
+
+ *data_len = p - *data;
+ } else {
+ p += *data_len;
+ }
+
+ if (p < end)
+ return p;
+ else
+ return NULL;
+}
+
+static void
+_jbig2_extract_info (cairo_image_info_t *info, const unsigned char *p)
+{
+ info->width = _get_be32 (p);
+ info->height = _get_be32 (p + 4);
+ info->num_components = 1;
+ info->bits_per_component = 1;
+}
+
+cairo_int_status_t
+_cairo_image_info_get_jbig2_info (cairo_image_info_t *info,
+ const unsigned char *data,
+ unsigned long length)
+{
+ const unsigned char *p = data;
+ const unsigned char *end = data + length;
+ int seg_type;
+ const unsigned char *seg_data;
+ unsigned long seg_data_len;
+
+ while (p && p < end) {
+ p = _jbig2_get_next_segment (p, end, &seg_type, &seg_data, &seg_data_len);
+ if (p && seg_type == 48 && seg_data_len > 8) {
+ /* page information segment */
+ _jbig2_extract_info (info, seg_data);
+ return CAIRO_STATUS_SUCCESS;
+ }
+ }
+
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+}
diff --git a/src/cairo-misc.c b/src/cairo-misc.c
index bb37e1a..7575d42 100644
--- a/src/cairo-misc.c
+++ b/src/cairo-misc.c
@@ -156,6 +156,8 @@ cairo_status_to_string (cairo_status_t status)
return "invalid operation during mesh pattern construction";
case CAIRO_STATUS_DEVICE_FINISHED:
return "the target device has been finished";
+ case CAIRO_STATUS_JBIG2_GLOBAL_MISSING:
+ return "CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID used but no CAIRO_MIME_TYPE_JBIG2_GLOBAL data provided";
default:
case CAIRO_STATUS_LAST_STATUS:
return "<unknown error status>";
diff --git a/src/cairo-pdf-surface-private.h b/src/cairo-pdf-surface-private.h
index dfeb1aa..0032947 100644
--- a/src/cairo-pdf-surface-private.h
+++ b/src/cairo-pdf-surface-private.h
@@ -129,6 +129,13 @@ typedef struct _cairo_pdf_smask_group {
cairo_scaled_font_t *scaled_font;
} cairo_pdf_smask_group_t;
+typedef struct _cairo_pdf_jbig2_global {
+ unsigned char *id;
+ unsigned long id_length;
+ cairo_pdf_resource_t res;
+ cairo_bool_t emitted;
+} cairo_pdf_jbig2_global_t;
+
typedef struct _cairo_pdf_surface cairo_pdf_surface_t;
struct _cairo_pdf_surface {
@@ -151,6 +158,7 @@ struct _cairo_pdf_surface {
cairo_hash_table_t *all_surfaces;
cairo_array_t smask_groups;
cairo_array_t knockout_group;
+ cairo_array_t jbig2_global;
cairo_scaled_font_subsets_t *font_subsets;
cairo_array_t fonts;
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 92c614d..4c9dd5a 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -130,6 +130,23 @@
*
* The PDF surface is used to render cairo graphics to Adobe
* PDF files and is a multi-page vector surface backend.
+ *
+ * The following mime types are supported: %CAIRO_MIME_TYPE_JPEG,
+ * %CAIRO_MIME_TYPE_JP2, %CAIRO_MIME_TYPE_UNIQUE_ID,
+ * %CAIRO_MIME_TYPE_JBIG2, %CAIRO_MIME_TYPE_JBIG2_GLOBAL,
+ * %CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID.
+ *
+ * JBIG2 data in PDF must be in the embedded format as descibed in
+ * ISO/IEC 11544. Image specific JBIG2 data must be in
+ * %CAIRO_MIME_TYPE_JBIG2. Any global segments in the JBIG2 data
+ * (segments with page association field set to 0) must be in
+ * %CAIRO_MIME_TYPE_JBIG2_GLOBAL. The global data may be shared by
+ * multiple images. All images sharing the same global data must set
+ * %CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID to a unique identifer. At least
+ * one of the images must provide the global data using
+ * %CAIRO_MIME_TYPE_JBIG2_GLOBAL. The global data will only be
+ * embedded once but shared by all JBIG2 images with the same
+ * %CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID.
**/
static cairo_bool_t
@@ -164,6 +181,9 @@ static const char *_cairo_pdf_supported_mime_types[] =
CAIRO_MIME_TYPE_JPEG,
CAIRO_MIME_TYPE_JP2,
CAIRO_MIME_TYPE_UNIQUE_ID,
+ CAIRO_MIME_TYPE_JBIG2,
+ CAIRO_MIME_TYPE_JBIG2_GLOBAL,
+ CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID,
NULL
};
@@ -364,6 +384,7 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output,
_cairo_array_init (&surface->page_patterns, sizeof (cairo_pdf_pattern_t));
_cairo_array_init (&surface->page_surfaces, sizeof (cairo_pdf_source_surface_t));
+ _cairo_array_init (&surface->jbig2_global, sizeof (cairo_pdf_jbig2_global_t));
surface->all_surfaces = _cairo_hash_table_create (_cairo_pdf_source_surface_equal);
if (unlikely (surface->all_surfaces == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
@@ -1174,6 +1195,20 @@ _cairo_pdf_surface_release_source_image_from_pattern (cairo_pdf_surface_t
}
static cairo_int_status_t
+_get_jbig2_image_info (cairo_surface_t *source,
+ cairo_image_info_t *info,
+ const unsigned char **mime_data,
+ unsigned long *mime_data_length)
+{
+ cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JBIG2,
+ mime_data, mime_data_length);
+ if (*mime_data == NULL)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ return _cairo_image_info_get_jbig2_info (info, *mime_data, *mime_data_length);
+}
+
+static cairo_int_status_t
_get_jpx_image_info (cairo_surface_t *source,
cairo_image_info_t *info,
const unsigned char **mime_data,
@@ -1250,6 +1285,15 @@ _get_source_surface_size (cairo_surface_t *source,
extents->x = 0;
extents->y = 0;
+ status = _get_jbig2_image_info (source, &info, &mime_data, &mime_data_length);
+ if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
+ *width = info.width;
+ *height = info.height;
+ extents->width = info.width;
+ extents->height = info.height;
+ return status;
+ }
+
status = _get_jpx_image_info (source, &info, &mime_data, &mime_data_length);
if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
*width = info.width;
@@ -1969,6 +2013,8 @@ _cairo_pdf_surface_finish (void *abstract_surface)
long offset;
cairo_pdf_resource_t info, catalog;
cairo_status_t status, status2;
+ int size, i;
+ cairo_pdf_jbig2_global_t *global;
status = surface->base.status;
if (status == CAIRO_STATUS_SUCCESS)
@@ -2056,6 +2102,17 @@ _cairo_pdf_surface_finish (void *abstract_surface)
surface->font_subsets = NULL;
}
+ size = _cairo_array_num_elements (&surface->jbig2_global);
+ for (i = 0; i < size; i++) {
+ global = (cairo_pdf_jbig2_global_t *) _cairo_array_index (&surface->jbig2_global, i);
+ free(global->id);
+ if (!global->emitted)
+ return _cairo_error (CAIRO_STATUS_JBIG2_GLOBAL_MISSING);
+ }
+ _cairo_array_fini (&surface->jbig2_global);
+
+ _cairo_array_truncate (&surface->page_surfaces, 0);
+
_cairo_surface_clipper_reset (&surface->clipper);
return status;
@@ -2556,6 +2613,127 @@ CLEANUP:
}
static cairo_int_status_t
+_cairo_pdf_surface_lookup_jbig2_global (cairo_pdf_surface_t *surface,
+ const unsigned char *global_id,
+ unsigned long global_id_length,
+ cairo_pdf_jbig2_global_t **entry)
+{
+ cairo_pdf_jbig2_global_t global;
+ int size, i;
+ cairo_int_status_t status;
+
+ size = _cairo_array_num_elements (&surface->jbig2_global);
+ for (i = 0; i < size; i++) {
+ *entry = (cairo_pdf_jbig2_global_t *) _cairo_array_index (&surface->jbig2_global, i);
+ if ((*entry)->id && global_id && (*entry)->id_length == global_id_length
+ && memcmp((*entry)->id, global_id, global_id_length) == 0) {
+ return CAIRO_STATUS_SUCCESS;
+ }
+ }
+
+ global.id = malloc(global_id_length);
+ memcpy (global.id, global_id, global_id_length);
+ global.id_length = global_id_length;
+ global.res = _cairo_pdf_surface_new_object (surface);
+ if (global.res.id == 0)
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+ global.emitted = FALSE;
+ status = _cairo_array_append (&surface->jbig2_global, &global);
+ if (unlikely(status))
+ return status;
+
+ size = _cairo_array_num_elements (&surface->jbig2_global);
+ *entry = (cairo_pdf_jbig2_global_t *) _cairo_array_index (&surface->jbig2_global, size - 1);
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_int_status_t
+_cairo_pdf_surface_emit_jbig2_image (cairo_pdf_surface_t *surface,
+ cairo_surface_t *source,
+ cairo_pdf_resource_t res)
+{
+ cairo_int_status_t status;
+ const unsigned char *mime_data;
+ unsigned long mime_data_length;
+ cairo_image_info_t info;
+ const unsigned char *global_id;
+ unsigned long global_id_length;
+ const unsigned char *global_data;
+ unsigned long global_data_length;
+ cairo_pdf_jbig2_global_t *global_entry;
+
+ cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JBIG2,
+ &mime_data, &mime_data_length);
+ if (mime_data == NULL)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ status = _cairo_image_info_get_jbig2_info (&info, mime_data, mime_data_length);
+ if (status)
+ return status;
+
+ cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID,
+ &global_id, &global_id_length);
+ if (global_id && global_id_length > 0) {
+ status = _cairo_pdf_surface_lookup_jbig2_global (surface, global_id, global_id_length, &global_entry);
+ if (unlikely(status))
+ return status;
+
+ if (!global_entry->emitted) {
+ cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JBIG2_GLOBAL,
+ &global_data, &global_data_length);
+ if (global_data) {
+ status = _cairo_pdf_surface_open_stream (surface, &global_entry->res, FALSE, NULL);
+ if (unlikely(status))
+ return status;
+
+ _cairo_output_stream_write (surface->output, global_data, global_data_length);
+ status = _cairo_pdf_surface_close_stream (surface);
+ if (unlikely(status))
+ return status;
+
+ global_entry->emitted = TRUE;
+ }
+ }
+
+ status = _cairo_pdf_surface_open_stream (surface,
+ &res,
+ FALSE,
+ " /Type /XObject\n"
+ " /Subtype /Image\n"
+ " /Width %d\n"
+ " /Height %d\n"
+ " /ColorSpace /DeviceGray\n"
+ " /BitsPerComponent 1\n"
+ " /Filter /JBIG2Decode\n"
+ " /DecodeParms << /JBIG2Globals %d 0 R >>\n",
+ info.width,
+ info.height,
+ global_entry->res.id);
+ } else {
+ status = _cairo_pdf_surface_open_stream (surface,
+ &res,
+ FALSE,
+ " /Type /XObject\n"
+ " /Subtype /Image\n"
+ " /Width %d\n"
+ " /Height %d\n"
+ " /ColorSpace /DeviceGray\n"
+ " /BitsPerComponent 1\n"
+ " /Filter /JBIG2Decode\n",
+ info.width,
+ info.height);
+ }
+ if (unlikely(status))
+ return status;
+
+ _cairo_output_stream_write (surface->output, mime_data, mime_data_length);
+ status = _cairo_pdf_surface_close_stream (surface);
+
+ return status;
+}
+
+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)
@@ -2665,6 +2843,10 @@ _cairo_pdf_surface_emit_image_surface (cairo_pdf_surface_t *surface,
if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
if (!source->hash_entry->stencil_mask) {
+ status = _cairo_pdf_surface_emit_jbig2_image (surface, source->surface, source->hash_entry->surface_res);
+ if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+ return status;
+
status = _cairo_pdf_surface_emit_jpx_image (surface, source->surface, source->hash_entry->surface_res);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
diff --git a/src/cairo-region.c b/src/cairo-region.c
index a51e224..ceaf4c0 100644
--- a/src/cairo-region.c
+++ b/src/cairo-region.c
@@ -106,6 +106,7 @@ _cairo_region_create_in_error (cairo_status_t status)
case CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED:
case CAIRO_STATUS_INVALID_MESH_CONSTRUCTION:
case CAIRO_STATUS_DEVICE_FINISHED:
+ case CAIRO_STATUS_JBIG2_GLOBAL_MISSING:
default:
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
return (cairo_region_t *) &_cairo_region_nil;
diff --git a/src/cairo-spans.c b/src/cairo-spans.c
index b8d4180..182390c 100644
--- a/src/cairo-spans.c
+++ b/src/cairo-spans.c
@@ -0,0 +1,250 @@
+/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright (c) 2008 M Joonas Pihlaja
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "cairoint.h"
+
+#include "cairo-composite-rectangles-private.h"
+#include "cairo-clip-private.h"
+#include "cairo-error-private.h"
+#include "cairo-fixed-private.h"
+#include "cairo-types-private.h"
+
+static void
+_cairo_nil_destroy (void *abstract)
+{
+ (void) abstract;
+}
+
+static cairo_status_t
+_cairo_nil_scan_converter_generate (void *abstract_converter,
+ cairo_span_renderer_t *renderer)
+{
+ (void) abstract_converter;
+ (void) renderer;
+ return _cairo_scan_converter_status (abstract_converter);
+}
+
+cairo_status_t
+_cairo_scan_converter_status (void *abstract_converter)
+{
+ cairo_scan_converter_t *converter = abstract_converter;
+ return converter->status;
+}
+
+cairo_status_t
+_cairo_scan_converter_set_error (void *abstract_converter,
+ cairo_status_t error)
+{
+ cairo_scan_converter_t *converter = abstract_converter;
+ if (error == CAIRO_STATUS_SUCCESS)
+ ASSERT_NOT_REACHED;
+ if (converter->status == CAIRO_STATUS_SUCCESS) {
+ converter->generate = _cairo_nil_scan_converter_generate;
+ converter->status = error;
+ }
+ return converter->status;
+}
+
+static void
+_cairo_nil_scan_converter_init (cairo_scan_converter_t *converter,
+ cairo_status_t status)
+{
+ converter->destroy = _cairo_nil_destroy;
+ converter->status = CAIRO_STATUS_SUCCESS;
+ status = _cairo_scan_converter_set_error (converter, status);
+}
+
+cairo_scan_converter_t *
+_cairo_scan_converter_create_in_error (cairo_status_t status)
+{
+#define RETURN_NIL {\
+ static cairo_scan_converter_t nil;\
+ _cairo_nil_scan_converter_init (&nil, status);\
+ return &nil;\
+ }
+ switch (status) {
+ case CAIRO_STATUS_SUCCESS:
+ case CAIRO_STATUS_LAST_STATUS:
+ ASSERT_NOT_REACHED;
+ break;
+ case CAIRO_STATUS_INVALID_RESTORE: RETURN_NIL;
+ case CAIRO_STATUS_INVALID_POP_GROUP: RETURN_NIL;
+ case CAIRO_STATUS_NO_CURRENT_POINT: RETURN_NIL;
+ case CAIRO_STATUS_INVALID_MATRIX: RETURN_NIL;
+ case CAIRO_STATUS_INVALID_STATUS: RETURN_NIL;
+ case CAIRO_STATUS_NULL_POINTER: RETURN_NIL;
+ case CAIRO_STATUS_INVALID_STRING: RETURN_NIL;
+ case CAIRO_STATUS_INVALID_PATH_DATA: RETURN_NIL;
+ case CAIRO_STATUS_READ_ERROR: RETURN_NIL;
+ case CAIRO_STATUS_WRITE_ERROR: RETURN_NIL;
+ case CAIRO_STATUS_SURFACE_FINISHED: RETURN_NIL;
+ case CAIRO_STATUS_SURFACE_TYPE_MISMATCH: RETURN_NIL;
+ case CAIRO_STATUS_PATTERN_TYPE_MISMATCH: RETURN_NIL;
+ case CAIRO_STATUS_INVALID_CONTENT: RETURN_NIL;
+ case CAIRO_STATUS_INVALID_FORMAT: RETURN_NIL;
+ case CAIRO_STATUS_INVALID_VISUAL: RETURN_NIL;
+ case CAIRO_STATUS_FILE_NOT_FOUND: RETURN_NIL;
+ case CAIRO_STATUS_INVALID_DASH: RETURN_NIL;
+ case CAIRO_STATUS_INVALID_DSC_COMMENT: RETURN_NIL;
+ case CAIRO_STATUS_INVALID_INDEX: RETURN_NIL;
+ case CAIRO_STATUS_CLIP_NOT_REPRESENTABLE: RETURN_NIL;
+ case CAIRO_STATUS_TEMP_FILE_ERROR: RETURN_NIL;
+ case CAIRO_STATUS_INVALID_STRIDE: RETURN_NIL;
+ case CAIRO_STATUS_FONT_TYPE_MISMATCH: RETURN_NIL;
+ case CAIRO_STATUS_USER_FONT_IMMUTABLE: RETURN_NIL;
+ case CAIRO_STATUS_USER_FONT_ERROR: RETURN_NIL;
+ case CAIRO_STATUS_NEGATIVE_COUNT: RETURN_NIL;
+ case CAIRO_STATUS_INVALID_CLUSTERS: RETURN_NIL;
+ case CAIRO_STATUS_INVALID_SLANT: RETURN_NIL;
+ case CAIRO_STATUS_INVALID_WEIGHT: RETURN_NIL;
+ case CAIRO_STATUS_NO_MEMORY: RETURN_NIL;
+ case CAIRO_STATUS_INVALID_SIZE: RETURN_NIL;
+ case CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED: RETURN_NIL;
+ case CAIRO_STATUS_DEVICE_TYPE_MISMATCH: RETURN_NIL;
+ case CAIRO_STATUS_DEVICE_ERROR: RETURN_NIL;
+ case CAIRO_STATUS_INVALID_MESH_CONSTRUCTION: RETURN_NIL;
+ case CAIRO_STATUS_DEVICE_FINISHED: RETURN_NIL;
+ case CAIRO_STATUS_JBIG2_GLOBAL_MISSING:
+ default:
+ break;
+ }
+ status = CAIRO_STATUS_NO_MEMORY;
+ RETURN_NIL;
+#undef RETURN_NIL
+}
+
+static cairo_status_t
+_cairo_nil_span_renderer_render_rows (
+ void *abstract_renderer,
+ int y,
+ int height,
+ const cairo_half_open_span_t *coverages,
+ unsigned num_coverages)
+{
+ (void) y;
+ (void) height;
+ (void) coverages;
+ (void) num_coverages;
+ return _cairo_span_renderer_status (abstract_renderer);
+}
+
+static cairo_status_t
+_cairo_nil_span_renderer_finish (void *abstract_renderer)
+{
+ return _cairo_span_renderer_status (abstract_renderer);
+}
+
+cairo_status_t
+_cairo_span_renderer_status (void *abstract_renderer)
+{
+ cairo_span_renderer_t *renderer = abstract_renderer;
+ return renderer->status;
+}
+
+cairo_status_t
+_cairo_span_renderer_set_error (
+ void *abstract_renderer,
+ cairo_status_t error)
+{
+ cairo_span_renderer_t *renderer = abstract_renderer;
+ if (error == CAIRO_STATUS_SUCCESS) {
+ ASSERT_NOT_REACHED;
+ }
+ if (renderer->status == CAIRO_STATUS_SUCCESS) {
+ renderer->render_rows = _cairo_nil_span_renderer_render_rows;
+ renderer->finish = _cairo_nil_span_renderer_finish;
+ renderer->status = error;
+ }
+ return renderer->status;
+}
+
+static void
+_cairo_nil_span_renderer_init (cairo_span_renderer_t *renderer,
+ cairo_status_t status)
+{
+ renderer->destroy = _cairo_nil_destroy;
+ renderer->status = CAIRO_STATUS_SUCCESS;
+ status = _cairo_span_renderer_set_error (renderer, status);
+}
+
+cairo_span_renderer_t *
+_cairo_span_renderer_create_in_error (cairo_status_t status)
+{
+#define RETURN_NIL {\
+ static cairo_span_renderer_t nil;\
+ _cairo_nil_span_renderer_init (&nil, status);\
+ return &nil;\
+ }
+ switch (status) {
+ case CAIRO_STATUS_SUCCESS:
+ case CAIRO_STATUS_LAST_STATUS:
+ ASSERT_NOT_REACHED;
+ break;
+ case CAIRO_STATUS_INVALID_RESTORE: RETURN_NIL;
+ case CAIRO_STATUS_INVALID_POP_GROUP: RETURN_NIL;
+ case CAIRO_STATUS_NO_CURRENT_POINT: RETURN_NIL;
+ case CAIRO_STATUS_INVALID_MATRIX: RETURN_NIL;
+ case CAIRO_STATUS_INVALID_STATUS: RETURN_NIL;
+ case CAIRO_STATUS_NULL_POINTER: RETURN_NIL;
+ case CAIRO_STATUS_INVALID_STRING: RETURN_NIL;
+ case CAIRO_STATUS_INVALID_PATH_DATA: RETURN_NIL;
+ case CAIRO_STATUS_READ_ERROR: RETURN_NIL;
+ case CAIRO_STATUS_WRITE_ERROR: RETURN_NIL;
+ case CAIRO_STATUS_SURFACE_FINISHED: RETURN_NIL;
+ case CAIRO_STATUS_SURFACE_TYPE_MISMATCH: RETURN_NIL;
+ case CAIRO_STATUS_PATTERN_TYPE_MISMATCH: RETURN_NIL;
+ case CAIRO_STATUS_INVALID_CONTENT: RETURN_NIL;
+ case CAIRO_STATUS_INVALID_FORMAT: RETURN_NIL;
+ case CAIRO_STATUS_INVALID_VISUAL: RETURN_NIL;
+ case CAIRO_STATUS_FILE_NOT_FOUND: RETURN_NIL;
+ case CAIRO_STATUS_INVALID_DASH: RETURN_NIL;
+ case CAIRO_STATUS_INVALID_DSC_COMMENT: RETURN_NIL;
+ case CAIRO_STATUS_INVALID_INDEX: RETURN_NIL;
+ case CAIRO_STATUS_CLIP_NOT_REPRESENTABLE: RETURN_NIL;
+ case CAIRO_STATUS_TEMP_FILE_ERROR: RETURN_NIL;
+ case CAIRO_STATUS_INVALID_STRIDE: RETURN_NIL;
+ case CAIRO_STATUS_FONT_TYPE_MISMATCH: RETURN_NIL;
+ case CAIRO_STATUS_USER_FONT_IMMUTABLE: RETURN_NIL;
+ case CAIRO_STATUS_USER_FONT_ERROR: RETURN_NIL;
+ case CAIRO_STATUS_NEGATIVE_COUNT: RETURN_NIL;
+ case CAIRO_STATUS_INVALID_CLUSTERS: RETURN_NIL;
+ case CAIRO_STATUS_INVALID_SLANT: RETURN_NIL;
+ case CAIRO_STATUS_INVALID_WEIGHT: RETURN_NIL;
+ case CAIRO_STATUS_NO_MEMORY: RETURN_NIL;
+ case CAIRO_STATUS_INVALID_SIZE: RETURN_NIL;
+ case CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED: RETURN_NIL;
+ case CAIRO_STATUS_DEVICE_TYPE_MISMATCH: RETURN_NIL;
+ case CAIRO_STATUS_DEVICE_ERROR: RETURN_NIL;
+ case CAIRO_STATUS_INVALID_MESH_CONSTRUCTION: RETURN_NIL;
+ case CAIRO_STATUS_DEVICE_FINISHED: RETURN_NIL;
+ case CAIRO_STATUS_JBIG2_GLOBAL_MISSING: RETURN_NIL;
+ default:
+ break;
+ }
+ status = CAIRO_STATUS_NO_MEMORY;
+ RETURN_NIL;
+#undef RETURN_NIL
+}
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index f2f2ef6..d550131 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -1285,7 +1285,8 @@ _cairo_mime_data_destroy (void *ptr)
*
* The recognized MIME types are the following: %CAIRO_MIME_TYPE_JPEG,
* %CAIRO_MIME_TYPE_PNG, %CAIRO_MIME_TYPE_JP2, %CAIRO_MIME_TYPE_URI,
- * %CAIRO_MIME_TYPE_UNIQUE_ID.
+ * %CAIRO_MIME_TYPE_UNIQUE_ID, %CAIRO_MIME_TYPE_JBIG2,
+ * %CAIRO_MIME_TYPE_JBIG2_GLOBAL, %CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID.
*
* See corresponding backend surface docs for details about which MIME
* types it can handle. Caution: the associated MIME data will be
@@ -2674,6 +2675,7 @@ _cairo_surface_create_in_error (cairo_status_t status)
case CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED:
case CAIRO_STATUS_INVALID_MESH_CONSTRUCTION:
case CAIRO_STATUS_DEVICE_FINISHED:
+ case CAIRO_STATUS_JBIG2_GLOBAL_MISSING:
default:
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
return (cairo_surface_t *) &_cairo_surface_nil;
diff --git a/src/cairo.c b/src/cairo.c
index 82396d2..c7128ae 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -152,7 +152,9 @@ static const cairo_t _cairo_nil[] = {
DEFINE_NIL_CONTEXT (CAIRO_STATUS_DEVICE_TYPE_MISMATCH),
DEFINE_NIL_CONTEXT (CAIRO_STATUS_DEVICE_ERROR),
DEFINE_NIL_CONTEXT (CAIRO_STATUS_INVALID_MESH_CONSTRUCTION),
- DEFINE_NIL_CONTEXT (CAIRO_STATUS_DEVICE_FINISHED)
+ DEFINE_NIL_CONTEXT (CAIRO_STATUS_DEVICE_FINISHED),
+ DEFINE_NIL_CONTEXT (CAIRO_STATUS_JBIG2_GLOBAL_MISSING)
+
};
COMPILE_TIME_ASSERT (ARRAY_LENGTH (_cairo_nil) == CAIRO_STATUS_LAST_STATUS - 1);
diff --git a/src/cairo.h b/src/cairo.h
index de35126..2e69793 100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -290,6 +290,8 @@ typedef struct _cairo_user_data_key {
* cairo_mesh_pattern_begin_patch()/cairo_mesh_pattern_end_patch()
* pair (Since 1.12)
* @CAIRO_STATUS_DEVICE_FINISHED: target device has been finished (Since 1.12)
+ * @CAIRO_STATUS_JBIG2_GLOBAL_MISSING: %CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID has been used on at least one image
+ * but no image provided %CAIRO_MIME_TYPE_JBIG2_GLOBAL (Since 1.14)
* @CAIRO_STATUS_LAST_STATUS: this is a special value indicating the number of
* status values defined in this enumeration. When using this value, note
* that the version of cairo at run-time may have additional status values
@@ -345,6 +347,7 @@ typedef enum _cairo_status {
CAIRO_STATUS_DEVICE_ERROR,
CAIRO_STATUS_INVALID_MESH_CONSTRUCTION,
CAIRO_STATUS_DEVICE_FINISHED,
+ CAIRO_STATUS_JBIG2_GLOBAL_MISSING,
CAIRO_STATUS_LAST_STATUS
} cairo_status_t;
@@ -2419,6 +2422,9 @@ cairo_surface_set_user_data (cairo_surface_t *surface,
#define CAIRO_MIME_TYPE_JP2 "image/jp2"
#define CAIRO_MIME_TYPE_URI "text/x-uri"
#define CAIRO_MIME_TYPE_UNIQUE_ID "application/x-cairo.uuid"
+#define CAIRO_MIME_TYPE_JBIG2 "application/x-cairo.jbig2"
+#define CAIRO_MIME_TYPE_JBIG2_GLOBAL "application/x-cairo.jbig2-global"
+#define CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID "application/x-cairo.jbig2-global-id"
cairo_public void
cairo_surface_get_mime_data (cairo_surface_t *surface,