diff options
author | Adrian Johnson <ajohnson@redneon.com> | 2013-09-14 20:59:56 +0930 |
---|---|---|
committer | Adrian Johnson <ajohnson@redneon.com> | 2013-09-15 20:50:46 +0930 |
commit | 5c0caa6f82374ec38a33d5f25a725f60bc121887 (patch) | |
tree | f72d0efad6b57d4592713831c7c863de4e5432dc | |
parent | 2d6705671a900251f00c6b59375bd4d23ec6b4d0 (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.c | 1 | ||||
-rw-r--r-- | src/cairo-error-private.h | 1 | ||||
-rw-r--r-- | src/cairo-image-info-private.h | 5 | ||||
-rw-r--r-- | src/cairo-image-info.c | 135 | ||||
-rw-r--r-- | src/cairo-misc.c | 2 | ||||
-rw-r--r-- | src/cairo-pdf-surface-private.h | 8 | ||||
-rw-r--r-- | src/cairo-pdf-surface.c | 182 | ||||
-rw-r--r-- | src/cairo-region.c | 1 | ||||
-rw-r--r-- | src/cairo-spans.c | 2 | ||||
-rw-r--r-- | src/cairo-surface.c | 4 | ||||
-rw-r--r-- | src/cairo.c | 4 | ||||
-rw-r--r-- | src/cairo.h | 6 |
12 files changed, 349 insertions, 2 deletions
diff --git a/src/cairo-device.c b/src/cairo-device.c index 098f85601..585a9c1c4 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 ea9c2ea31..2d170efc0 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 0d9ef8498..e64928e40 100644 --- a/src/cairo-image-info-private.h +++ b/src/cairo-image-info-private.h @@ -60,4 +60,9 @@ _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 4489698e8..64053a218 100644 --- a/src/cairo-image-info.c +++ b/src/cairo-image-info.c @@ -1,3 +1,4 @@ +/* -*- 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 @@ -290,3 +291,137 @@ _cairo_image_info_get_png_info (cairo_image_info_t *info, 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 bb37e1a0a..7575d42ce 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 dfeb1aacb..003294772 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 92c614d19..4c9dd5a65 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 a51e2247f..ceaf4c0bf 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 b8d41800e..182390c20 100644 --- a/src/cairo-spans.c +++ b/src/cairo-spans.c @@ -127,6 +127,7 @@ _cairo_scan_converter_create_in_error (cairo_status_t status) 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; } @@ -239,6 +240,7 @@ _cairo_span_renderer_create_in_error (cairo_status_t status) 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; } diff --git a/src/cairo-surface.c b/src/cairo-surface.c index f2f2ef61e..d550131d0 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 82396d221..c7128ae50 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 de3512619..2e69793c7 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, |