diff options
Diffstat (limited to 'xps')
-rw-r--r-- | xps/muxps.h (renamed from xps/ghostxps.h) | 227 | ||||
-rw-r--r-- | xps/xpsanalyze.c | 22 | ||||
-rw-r--r-- | xps/xpscolor.c | 85 | ||||
-rw-r--r-- | xps/xpscommon.c | 67 | ||||
-rw-r--r-- | xps/xpscrc.c | 18 | ||||
-rw-r--r-- | xps/xpsdoc.c | 33 | ||||
-rw-r--r-- | xps/xpsfont.c | 519 | ||||
-rw-r--r-- | xps/xpsglyphs.c | 126 | ||||
-rw-r--r-- | xps/xpsgradient.c | 440 | ||||
-rw-r--r-- | xps/xpshash.c | 24 | ||||
-rw-r--r-- | xps/xpsimage.c | 308 | ||||
-rw-r--r-- | xps/xpsjpeg.c | 142 | ||||
-rw-r--r-- | xps/xpsjxr.c | 34 | ||||
-rw-r--r-- | xps/xpsmem.c | 51 | ||||
-rw-r--r-- | xps/xpsopacity.c | 60 | ||||
-rw-r--r-- | xps/xpspage.c | 225 | ||||
-rw-r--r-- | xps/xpspath.c | 440 | ||||
-rw-r--r-- | xps/xpspng.c | 64 | ||||
-rw-r--r-- | xps/xpsresource.c | 44 | ||||
-rw-r--r-- | xps/xpstiff.c | 87 | ||||
-rw-r--r-- | xps/xpstile.c | 172 | ||||
-rw-r--r-- | xps/xpstop.c | 780 | ||||
-rw-r--r-- | xps/xpsutf.c | 18 | ||||
-rw-r--r-- | xps/xpsvisual.c | 29 | ||||
-rw-r--r-- | xps/xpsxml.c | 24 | ||||
-rw-r--r-- | xps/xpszip.c | 242 |
26 files changed, 1192 insertions, 3089 deletions
diff --git a/xps/ghostxps.h b/xps/muxps.h index 3f06a80d..f2145d2f 100644 --- a/xps/ghostxps.h +++ b/xps/muxps.h @@ -1,88 +1,14 @@ -/* Copyright (C) 2006-2010 Artifex Software, Inc. - All Rights Reserved. - - This software is provided AS-IS with no warranty, either express or - implied. - - This software is distributed under license and may not be copied, modified - or distributed except as expressly authorized under the terms of that - license. Refer to licensing information at http://www.artifex.com/ - or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, - San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information. -*/ - -/* combined internal header for the XPS interpreter */ - -#include "memory_.h" -#include "math_.h" - -#include <stdlib.h> -#include <ctype.h> /* for toupper() */ - -#include "gp.h" - -#include "gsgc.h" -#include "gstypes.h" -#include "gsstate.h" -#include "gsmatrix.h" -#include "gscoord.h" -#include "gsmemory.h" -#include "gsparam.h" -#include "gsdevice.h" -#include "scommon.h" -#include "gdebug.h" -#include "gserror.h" -#include "gserrors.h" -#include "gspaint.h" -#include "gspath.h" -#include "gsimage.h" -#include "gscspace.h" -#include "gsptype1.h" -#include "gscolor2.h" -#include "gscolor3.h" -#include "gsutil.h" -#include "gsicc.h" - -#include "gstrans.h" - -#include "gxpath.h" /* gsshade.h depends on it */ -#include "gxfixed.h" /* gsshade.h depends on it */ -#include "gxmatrix.h" /* gxtype1.h depends on it */ -#include "gsshade.h" -#include "gsfunc.h" -#include "gsfunc3.h" /* we use stitching and exponential interp */ - -#include "gxfont.h" -#include "gxchar.h" -#include "gxcolor2.h" /* Required for definition of gs_pattern1_instance_t */ -#include "gxtype1.h" -#include "gxfont1.h" -#include "gxfont42.h" -#include "gxfcache.h" -#include "gxistate.h" - -#include "gzstate.h" -#include "gzpath.h" -#include "gzcpath.h" - -#include "gsicc_manage.h" -#include "gscms.h" -#include "gsicc_cache.h" - -#include "zlib.h" - -#ifndef MIN -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#endif -#ifndef MAX -#define MAX(a,b) ((a) < (b) ? (b) : (a)) -#endif -#ifndef ABS -#define ABS(a) ((a) < 0 ? -(a) : (a)) +#ifndef _MUXPS_H_ +#define _MUXPS_H_ + +#ifndef _FITZ_H_ +#error "fitz.h must be included before muxps.h" #endif +typedef unsigned char byte; + /* - * XPS and ZIP contants. + * XPS and ZIP constants. */ typedef struct xps_context_s xps_context_t; @@ -103,16 +29,10 @@ typedef struct xps_context_s xps_context_t; * Memory, and string functions. */ -void * xps_realloc_imp(xps_context_t *ctx, void *ptr, int size, const char *func); - -#define xps_alloc(ctx, size) \ - ((void*)gs_alloc_bytes(ctx->memory, size, __func__)) -#define xps_realloc(ctx, ptr, size) \ - xps_realloc_imp(ctx, ptr, size, __func__) -#define xps_strdup(ctx, str) \ - xps_strdup_imp(ctx, str, __func__) -#define xps_free(ctx, ptr) \ - gs_free_object(ctx->memory, ptr, __func__) +#define xps_alloc(ctx, size) fz_malloc(size) +#define xps_realloc(ctx, ptr, size) fz_realloc(ptr, size, 1) +#define xps_strdup(ctx, str) fz_strdup(str) +#define xps_free(ctx, ptr) fz_free(ptr) size_t xps_strlcpy(char *destination, const char *source, size_t size); size_t xps_strlcat(char *destination, const char *source, size_t size); @@ -172,6 +92,7 @@ struct xps_page_s char *name; int width; int height; + struct xps_item_s *root; xps_page_t *next; }; @@ -193,14 +114,13 @@ struct xps_image_s int width; int height; int stride; - gs_color_space *colorspace; + fz_colorspace *colorspace; int comps; int hasalpha; /* chunky alpha */ int bits; int xres; int yres; byte *samples; - byte *alpha; /* isolated alpha plane */ byte *profile; int profilesize; }; @@ -220,48 +140,19 @@ void xps_free_image(xps_context_t *ctx, xps_image_t *image); * Fonts. */ -typedef struct xps_font_s xps_font_t; typedef struct xps_glyph_metrics_s xps_glyph_metrics_t; -struct xps_font_s -{ - byte *data; - int length; - gs_font *font; - - int subfontid; - int cmaptable; - int cmapsubcount; - int cmapsubtable; - int usepua; - - /* these are for CFF opentypes only */ - byte *cffdata; - byte *cffend; - byte *gsubrs; - byte *subrs; - byte *charstrings; -}; - struct xps_glyph_metrics_s { float hadv, vadv, vorg; }; -xps_font_t *xps_new_font(xps_context_t *ctx, byte *buf, int buflen, int index); -void xps_free_font(xps_context_t *ctx, xps_font_t *font); +int xps_count_font_encodings(fz_font *font); +void xps_identify_font_encoding(fz_font *font, int idx, int *pid, int *eid); +void xps_select_font_encoding(fz_font *font, int idx); +int xps_encode_font_char(fz_font *font, int key); -int xps_count_font_encodings(xps_font_t *font); -void xps_identify_font_encoding(xps_font_t *font, int idx, int *pid, int *eid); -void xps_select_font_encoding(xps_font_t *font, int idx); -int xps_encode_font_char(xps_font_t *font, int key); - -void xps_measure_font_glyph(xps_context_t *ctx, xps_font_t *font, int gid, xps_glyph_metrics_t *mtx); - -int xps_find_sfnt_table(xps_font_t *font, const char *name, int *lengthp); -void xps_load_sfnt_name(xps_font_t *font, char *namep); -int xps_init_truetype_font(xps_context_t *ctx, xps_font_t *font); -int xps_init_postscript_font(xps_context_t *ctx, xps_font_t *font); +void xps_measure_font_glyph(xps_context_t *ctx, fz_font *font, int gid, xps_glyph_metrics_t *mtx); void xps_debug_path(xps_context_t *ctx); @@ -269,9 +160,9 @@ void xps_debug_path(xps_context_t *ctx); * Colorspaces and colors. */ -gs_color_space *xps_read_icc_colorspace(xps_context_t *ctx, char *base_uri, char *profile); -void xps_parse_color(xps_context_t *ctx, char *base_uri, char *hexstring, gs_color_space **csp, float *samples); -void xps_set_color(xps_context_t *ctx, gs_color_space *colorspace, float *samples); +fz_colorspace *xps_read_icc_colorspace(xps_context_t *ctx, char *base_uri, char *profile); +void xps_parse_color(xps_context_t *ctx, char *base_uri, char *hexstring, fz_colorspace **csp, float *samples); +void xps_set_color(xps_context_t *ctx, fz_colorspace *colorspace, float *samples); /* * XML document model @@ -313,33 +204,34 @@ void xps_debug_resource_dictionary(xps_resource_t *dict); * Fixed page/graphics parsing. */ -int xps_parse_fixed_page(xps_context_t *ctx, xps_part_t *part); -int xps_parse_canvas(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, xps_item_t *node); -int xps_parse_path(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, xps_item_t *node); -int xps_parse_glyphs(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, xps_item_t *node); -int xps_parse_solid_color_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, xps_item_t *node); -int xps_parse_image_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, xps_item_t *node); -int xps_parse_visual_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, xps_item_t *node); -int xps_parse_linear_gradient_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, xps_item_t *node); -int xps_parse_radial_gradient_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, xps_item_t *node); - -int xps_parse_tiling_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, xps_item_t *root, int (*func)(xps_context_t*, char*, xps_resource_t*, xps_item_t*, void*), void *user); - -void xps_parse_matrix_transform(xps_context_t *ctx, xps_item_t *root, gs_matrix *matrix); -void xps_parse_render_transform(xps_context_t *ctx, char *text, gs_matrix *matrix); -void xps_parse_rectangle(xps_context_t *ctx, char *text, gs_rect *rect); +int xps_load_fixed_page(xps_context_t *ctx, xps_page_t *page); +int xps_parse_fixed_page(xps_context_t *ctx, fz_matrix ctm, xps_page_t *page); +int xps_parse_canvas(xps_context_t *ctx, fz_matrix ctm, char *base_uri, xps_resource_t *dict, xps_item_t *node); +int xps_parse_path(xps_context_t *ctx, fz_matrix ctm, char *base_uri, xps_resource_t *dict, xps_item_t *node); +int xps_parse_glyphs(xps_context_t *ctx, fz_matrix ctm, char *base_uri, xps_resource_t *dict, xps_item_t *node); +int xps_parse_solid_color_brush(xps_context_t *ctx, fz_matrix ctm, char *base_uri, xps_resource_t *dict, xps_item_t *node); +int xps_parse_image_brush(xps_context_t *ctx, fz_matrix ctm, char *base_uri, xps_resource_t *dict, xps_item_t *node); +int xps_parse_visual_brush(xps_context_t *ctx, fz_matrix ctm, char *base_uri, xps_resource_t *dict, xps_item_t *node); +int xps_parse_linear_gradient_brush(xps_context_t *ctx, fz_matrix ctm, char *base_uri, xps_resource_t *dict, xps_item_t *node); +int xps_parse_radial_gradient_brush(xps_context_t *ctx, fz_matrix ctm, char *base_uri, xps_resource_t *dict, xps_item_t *node); + +int xps_parse_tiling_brush(xps_context_t *ctx, fz_matrix ctm, char *base_uri, xps_resource_t *dict, xps_item_t *root, int (*func)(xps_context_t*, fz_matrix, char*, xps_resource_t*, xps_item_t*, void*), void *user); + +void xps_parse_matrix_transform(xps_context_t *ctx, xps_item_t *root, fz_matrix *matrix); +void xps_parse_render_transform(xps_context_t *ctx, char *text, fz_matrix *matrix); +void xps_parse_rectangle(xps_context_t *ctx, char *text, fz_rect *rect); void xps_parse_abbreviated_geometry(xps_context_t *ctx, char *geom); void xps_parse_path_geometry(xps_context_t *ctx, xps_resource_t *dict, xps_item_t *root, int stroking); -int xps_begin_opacity(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, char *opacity_att, xps_item_t *opacity_mask_tag); +int xps_begin_opacity(xps_context_t *ctx, fz_matrix ctm, char *base_uri, xps_resource_t *dict, char *opacity_att, xps_item_t *opacity_mask_tag); void xps_end_opacity(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, char *opacity_att, xps_item_t *opacity_mask_tag); -int xps_parse_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, xps_item_t *node); -int xps_parse_element(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, xps_item_t *node); +int xps_parse_brush(xps_context_t *ctx, fz_matrix ctm, char *base_uri, xps_resource_t *dict, xps_item_t *node); +int xps_parse_element(xps_context_t *ctx, fz_matrix ctm, char *base_uri, xps_resource_t *dict, xps_item_t *node); -void xps_clip(xps_context_t *ctx); -void xps_fill(xps_context_t *ctx); -void xps_bounds_in_user_space(xps_context_t *ctx, gs_rect *user); +void xps_fill(xps_context_t *ctx, fz_matrix ctm); +void xps_clip(xps_context_t *ctx, fz_matrix ctm); +void xps_bounds_in_user_space(xps_context_t *ctx, fz_rect *user); int xps_element_has_transparency(xps_context_t *ctx, char *base_uri, xps_item_t *node); int xps_resource_dictionary_has_transparency(xps_context_t *ctx, char *base_uri, xps_item_t *node); @@ -361,16 +253,6 @@ struct xps_entry_s struct xps_context_s { - void *instance; - gs_memory_t *memory; - gs_state *pgs; - gs_font_dir *fontdir; - - gs_color_space *gray; - gs_color_space *srgb; - gs_color_space *scrgb; - gs_color_space *cmyk; - char *directory; FILE *file; int zip_count; @@ -404,9 +286,24 @@ struct xps_context_s * 1=nonzero, 0=evenodd */ int fill_rule; + + /* Current path being accumulated */ + fz_path *path; + + /* Current color */ + fz_colorspace *colorspace; + float color[8]; + float alpha; + + /* Current device */ + fz_device *dev; }; -int xps_process_file(xps_context_t *ctx, char *filename); +int xps_read_and_process_page_part(xps_context_t *ctx, fz_matrix ctm, char *name); +int xps_open_file(xps_context_t *ctx, char *filename); +int xps_count_pages(xps_context_t *ctx); +xps_page_t *xps_load_page(xps_context_t *ctx, int number); +xps_context_t *xps_new_context(void); +int xps_free_context(xps_context_t *ctx); -/* end of page device callback foo */ -int xps_show_page(xps_context_t *ctx, int num_copies, int flush); +#endif diff --git a/xps/xpsanalyze.c b/xps/xpsanalyze.c index 6e2f9d3e..41dc28c6 100644 --- a/xps/xpsanalyze.c +++ b/xps/xpsanalyze.c @@ -1,22 +1,10 @@ -/* Copyright (C) 2006-2010 Artifex Software, Inc. - All Rights Reserved. - - This software is provided AS-IS with no warranty, either express or - implied. - - This software is distributed under license and may not be copied, modified - or distributed except as expressly authorized under the terms of that - license. Refer to licensing information at http://www.artifex.com/ - or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, - San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information. -*/ - /* XPS interpreter - analyze page checking for transparency. * This is a stripped down parser that looks for alpha values < 1.0 in * any part of the page. */ -#include "ghostxps.h" +#include "fitz.h" +#include "muxps.h" static int xps_remote_resource_dictionary_has_transparency(xps_context_t *ctx, char *base_uri, char *source_att) @@ -47,7 +35,7 @@ static int xps_gradient_stops_have_transparency(xps_context_t *ctx, char *base_uri, xps_item_t *root) { xps_item_t *node; - gs_color_space *colorspace; + fz_colorspace *colorspace; char *color_att; float samples[32]; @@ -111,7 +99,7 @@ xps_brush_has_transparency(xps_context_t *ctx, char *base_uri, xps_item_t *root) char *color_att; xps_item_t *node; - gs_color_space *colorspace; + fz_colorspace *colorspace; float samples[32]; if (!strcmp(xps_tag(root), "SolidColorBrush")) @@ -266,7 +254,7 @@ xps_element_has_transparency(xps_context_t *ctx, char *base_uri, xps_item_t *nod char *stroke_att; char *fill_att; - gs_color_space *colorspace; + fz_colorspace *colorspace; float samples[32]; stroke_att = xps_att(node, "Stroke"); diff --git a/xps/xpscolor.c b/xps/xpscolor.c index dcc7b0ca..2c701c4a 100644 --- a/xps/xpscolor.c +++ b/xps/xpscolor.c @@ -1,43 +1,25 @@ -/* Copyright (C) 2006-2010 Artifex Software, Inc. - All Rights Reserved. +#include "fitz.h" +#include "muxps.h" - This software is provided AS-IS with no warranty, either express or - implied. - - This software is distributed under license and may not be copied, modified - or distributed except as expressly authorized under the terms of that - license. Refer to licensing information at http://www.artifex.com/ - or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, - San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information. -*/ - -/* XPS interpreter - color functions */ - -#include "ghostxps.h" - -#include "stream.h" /* for sizeof(stream) to work */ +#include <ctype.h> /* for toupper() */ void -xps_set_color(xps_context_t *ctx, gs_color_space *cs, float *samples) +xps_set_color(xps_context_t *ctx, fz_colorspace *colorspace, float *samples) { - gs_client_color cc; - int i, n; + int i; if (ctx->opacity_only) { - gs_setopacityalpha(ctx->pgs, 1.0); - gs_setgray(ctx->pgs, samples[0]); + ctx->colorspace = fz_devicegray; + ctx->color[0] = samples[0]; + ctx->alpha = 1.0; } else { - n = cs_num_components(cs); - cc.pattern = 0; - for (i = 0; i < n; i++) - cc.paint.values[i] = samples[i + 1]; - - gs_setopacityalpha(ctx->pgs, samples[0]); - gs_setcolorspace(ctx->pgs, cs); - gs_setcolor(ctx->pgs, &cc); + ctx->colorspace = colorspace; + for (i = 0; i < colorspace->n; i++) + ctx->color[i] = samples[i + 1]; + ctx->alpha = samples[0]; } } @@ -61,14 +43,14 @@ static int count_commas(char *s) void xps_parse_color(xps_context_t *ctx, char *base_uri, char *string, - gs_color_space **csp, float *samples) + fz_colorspace **csp, float *samples) { char *p; int i, n; char buf[1024]; char *profile; - *csp = ctx->srgb; + *csp = fz_devicergb; samples[0] = 1.0; samples[1] = 0.0; @@ -100,8 +82,6 @@ xps_parse_color(xps_context_t *ctx, char *base_uri, char *string, else if (string[0] == 's' && string[1] == 'c' && string[2] == '#') { - *csp = ctx->scrgb; - if (count_commas(string) == 2) sscanf(string, "sc#%g,%g,%g", samples + 1, samples + 2, samples + 3); if (count_commas(string) == 3) @@ -116,7 +96,7 @@ xps_parse_color(xps_context_t *ctx, char *base_uri, char *string, profile = strchr(buf, ' '); if (!profile) { - gs_warn1("cannot find icc profile uri in '%s'", string); + fz_warn("cannot find icc profile uri in '%s'", string); return; } @@ -124,7 +104,7 @@ xps_parse_color(xps_context_t *ctx, char *base_uri, char *string, p = strchr(profile, ' '); if (!p) { - gs_warn1("cannot find component values in '%s'", profile); + fz_warn("cannot find component values in '%s'", profile); return; } @@ -152,20 +132,20 @@ xps_parse_color(xps_context_t *ctx, char *base_uri, char *string, /* Default fallbacks if the ICC stuff fails */ switch (n) { - case 2: *csp = ctx->gray; break; /* alpha + tint */ - case 4: *csp = ctx->srgb; break; /* alpha + RGB */ - case 5: *csp = ctx->cmyk; break; /* alpha + CMYK */ - default: *csp = ctx->gray; break; + case 2: *csp = fz_devicegray; break; /* alpha + tint */ + case 4: *csp = fz_devicergb; break; /* alpha + RGB */ + case 5: *csp = fz_devicecmyk; break; /* alpha + CMYK */ + default: *csp = fz_devicegray; break; } } } } -gs_color_space * +fz_colorspace * xps_read_icc_colorspace(xps_context_t *ctx, char *base_uri, char *profilename) { - gs_color_space *space; - cmm_profile_t *profile; +#if 0 + fz_colorspace *space; xps_part_t *part; char partname[1024]; @@ -178,9 +158,9 @@ xps_read_icc_colorspace(xps_context_t *ctx, char *base_uri, char *profilename) { part = xps_read_part(ctx, partname); - /* Problem finding profile. Don't fail, just use default */ + /* Problem finding profile. Don't fail, just use default */ if (!part) { - gs_warn1("cannot find icc profile part: %s", partname); + fz_warn("cannot find icc profile part: %s", partname); return NULL; } @@ -194,11 +174,11 @@ xps_read_icc_colorspace(xps_context_t *ctx, char *base_uri, char *profilename) /* Parse */ gsicc_init_profile_info(profile); - /* Problem with profile. Don't fail, just use the default */ + /* Problem with profile. Don't fail, just use the default */ if (profile->profile_handle == NULL) { gsicc_profile_reference(profile, -1); - gs_warn1("there was a problem with the profile: %s", partname); + fz_warn("there was a problem with the profile: %s", partname); return NULL; } @@ -215,20 +195,23 @@ xps_read_icc_colorspace(xps_context_t *ctx, char *base_uri, char *profilename) } return space; +#else + return NULL; +#endif } int -xps_parse_solid_color_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, xps_item_t *node) +xps_parse_solid_color_brush(xps_context_t *ctx, fz_matrix ctm, char *base_uri, xps_resource_t *dict, xps_item_t *node) { char *opacity_att; char *color_att; - gs_color_space *colorspace; + fz_colorspace *colorspace; float samples[32]; color_att = xps_att(node, "Color"); opacity_att = xps_att(node, "Opacity"); - colorspace = ctx->srgb; + colorspace = fz_devicergb; samples[0] = 1.0; samples[1] = 0.0; samples[2] = 0.0; @@ -242,7 +225,7 @@ xps_parse_solid_color_brush(xps_context_t *ctx, char *base_uri, xps_resource_t * xps_set_color(ctx, colorspace, samples); - xps_fill(ctx); + xps_fill(ctx, ctm); return 0; } diff --git a/xps/xpscommon.c b/xps/xpscommon.c index 6908b3c5..4ba38f7c 100644 --- a/xps/xpscommon.c +++ b/xps/xpscommon.c @@ -1,56 +1,37 @@ -/* Copyright (C) 2006-2010 Artifex Software, Inc. - All Rights Reserved. - - This software is provided AS-IS with no warranty, either express or - implied. - - This software is distributed under license and may not be copied, modified - or distributed except as expressly authorized under the terms of that - license. Refer to licensing information at http://www.artifex.com/ - or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, - San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information. -*/ - -/* XPS interpreter - common parse functions */ - -#include "ghostxps.h" +#include "fitz.h" +#include "muxps.h" int -xps_parse_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, xps_item_t *node) +xps_parse_brush(xps_context_t *ctx, fz_matrix ctm, char *base_uri, xps_resource_t *dict, xps_item_t *node) { if (!strcmp(xps_tag(node), "SolidColorBrush")) - return xps_parse_solid_color_brush(ctx, base_uri, dict, node); + return xps_parse_solid_color_brush(ctx, ctm, base_uri, dict, node); if (!strcmp(xps_tag(node), "ImageBrush")) - { - int code = xps_parse_image_brush(ctx, base_uri, dict, node); - if (code) - gs_catch(code, "ignoring error in image brush"); - return gs_okay; - } + return xps_parse_image_brush(ctx, ctm, base_uri, dict, node); if (!strcmp(xps_tag(node), "VisualBrush")) - return xps_parse_visual_brush(ctx, base_uri, dict, node); + return xps_parse_visual_brush(ctx, ctm, base_uri, dict, node); if (!strcmp(xps_tag(node), "LinearGradientBrush")) - return xps_parse_linear_gradient_brush(ctx, base_uri, dict, node); + return xps_parse_linear_gradient_brush(ctx, ctm, base_uri, dict, node); if (!strcmp(xps_tag(node), "RadialGradientBrush")) - return xps_parse_radial_gradient_brush(ctx, base_uri, dict, node); - return gs_throw1(-1, "unknown brush tag: %s", xps_tag(node)); + return xps_parse_radial_gradient_brush(ctx, ctm, base_uri, dict, node); + return fz_throw("unknown brush tag: %s", xps_tag(node)); } int -xps_parse_element(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, xps_item_t *node) +xps_parse_element(xps_context_t *ctx, fz_matrix ctm, char *base_uri, xps_resource_t *dict, xps_item_t *node) { if (!strcmp(xps_tag(node), "Path")) - return xps_parse_path(ctx, base_uri, dict, node); + return xps_parse_path(ctx, ctm, base_uri, dict, node); if (!strcmp(xps_tag(node), "Glyphs")) - return xps_parse_glyphs(ctx, base_uri, dict, node); + return xps_parse_glyphs(ctx, ctm, base_uri, dict, node); if (!strcmp(xps_tag(node), "Canvas")) - return xps_parse_canvas(ctx, base_uri, dict, node); + return xps_parse_canvas(ctx, ctm, base_uri, dict, node); /* skip unknown tags (like Foo.Resources and similar) */ return 0; } void -xps_parse_render_transform(xps_context_t *ctx, char *transform, gs_matrix *matrix) +xps_parse_render_transform(xps_context_t *ctx, char *transform, fz_matrix *matrix) { float args[6]; char *s = transform; @@ -69,17 +50,17 @@ xps_parse_render_transform(xps_context_t *ctx, char *transform, gs_matrix *matri s++; } - matrix->xx = args[0]; matrix->xy = args[1]; - matrix->yx = args[2]; matrix->yy = args[3]; - matrix->tx = args[4]; matrix->ty = args[5]; + matrix->a = args[0]; matrix->b = args[1]; + matrix->c = args[2]; matrix->d = args[3]; + matrix->e = args[4]; matrix->f = args[5]; } void -xps_parse_matrix_transform(xps_context_t *ctx, xps_item_t *root, gs_matrix *matrix) +xps_parse_matrix_transform(xps_context_t *ctx, xps_item_t *root, fz_matrix *matrix) { char *transform; - gs_make_identity(matrix); + *matrix = fz_identity; if (!strcmp(xps_tag(root), "MatrixTransform")) { @@ -90,7 +71,7 @@ xps_parse_matrix_transform(xps_context_t *ctx, xps_item_t *root, gs_matrix *matr } void -xps_parse_rectangle(xps_context_t *ctx, char *text, gs_rect *rect) +xps_parse_rectangle(xps_context_t *ctx, char *text, fz_rect *rect) { float args[4]; char *s = text; @@ -108,8 +89,8 @@ xps_parse_rectangle(xps_context_t *ctx, char *text, gs_rect *rect) s++; } - rect->p.x = args[0]; - rect->p.y = args[1]; - rect->q.x = args[0] + args[2]; - rect->q.y = args[1] + args[3]; + rect->x0 = args[0]; + rect->y0 = args[1]; + rect->x1 = args[0] + args[2]; + rect->y1 = args[1] + args[3]; } diff --git a/xps/xpscrc.c b/xps/xpscrc.c index 7dea3c32..d5d4acd8 100644 --- a/xps/xpscrc.c +++ b/xps/xpscrc.c @@ -1,19 +1,5 @@ -/* Copyright (C) 2006-2010 Artifex Software, Inc. - All Rights Reserved. - - This software is provided AS-IS with no warranty, either express or - implied. - - This software is distributed under license and may not be copied, modified - or distributed except as expressly authorized under the terms of that - license. Refer to licensing information at http://www.artifex.com/ - or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, - San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information. -*/ - -/* XPS interpreter - CRC-32 implementation */ - -#include "ghostxps.h" +#include "fitz.h" +#include "muxps.h" static const unsigned long crctab[256] = { diff --git a/xps/xpsdoc.c b/xps/xpsdoc.c index 3e9f7c96..c0e83e4a 100644 --- a/xps/xpsdoc.c +++ b/xps/xpsdoc.c @@ -1,19 +1,5 @@ -/* Copyright (C) 2006-2010 Artifex Software, Inc. - All Rights Reserved. - - This software is provided AS-IS with no warranty, either express or - implied. - - This software is distributed under license and may not be copied, modified - or distributed except as expressly authorized under the terms of that - license. Refer to licensing information at http://www.artifex.com/ - or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, - San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information. -*/ - -/* XPS interpreter - document parsing */ - -#include "ghostxps.h" +#include "fitz.h" +#include "muxps.h" #include <expat.h> @@ -50,17 +36,17 @@ xps_debug_fixdocseq(xps_context_t *ctx) xps_page_t *page = ctx->first_page; if (ctx->start_part) - dprintf1("start part %s\n", ctx->start_part); + printf("start part %s\n", ctx->start_part); while (fixdoc) { - dprintf1("fixdoc %s\n", fixdoc->name); + printf("fixdoc %s\n", fixdoc->name); fixdoc = fixdoc->next; } while (page) { - dprintf3("page %s w=%d h=%d\n", page->name, page->width, page->height); + printf("page %s w=%d h=%d\n", page->name, page->width, page->height); page = page->next; } } @@ -75,8 +61,6 @@ xps_add_fixed_document(xps_context_t *ctx, char *name) if (!strcmp(fixdoc->name, name)) return; - if_debug1('|', "doc: adding fixdoc %s\n", name); - fixdoc = xps_alloc(ctx, sizeof(xps_document_t)); fixdoc->name = xps_strdup(ctx, name); fixdoc->next = NULL; @@ -118,12 +102,11 @@ xps_add_fixed_page(xps_context_t *ctx, char *name, int width, int height) if (!strcmp(page->name, name)) return; - if_debug1('|', "doc: adding page %s\n", name); - page = xps_alloc(ctx, sizeof(xps_page_t)); page->name = xps_strdup(ctx, name); page->width = width; page->height = height; + page->root = NULL; page->next = NULL; if (!ctx->first_page) @@ -257,7 +240,7 @@ xps_parse_metadata(xps_context_t *ctx, xps_part_t *part) xp = XML_ParserCreate(NULL); if (!xp) - return gs_throw(-1, "cannot create XML parser"); + return fz_throw("cannot create XML parser"); XML_SetUserData(xp, ctx); XML_SetParamEntityParsing(xp, XML_PARAM_ENTITY_PARSING_NEVER); @@ -271,7 +254,7 @@ xps_parse_metadata(xps_context_t *ctx, xps_part_t *part) ctx->part_uri = NULL; if (code == 0) - return gs_throw1(-1, "cannot parse XML in part: %s", part->name); + return fz_throw("cannot parse XML in part: %s", part->name); return 0; } diff --git a/xps/xpsfont.c b/xps/xpsfont.c index 93adf71d..ecedfabb 100644 --- a/xps/xpsfont.c +++ b/xps/xpsfont.c @@ -1,532 +1,53 @@ -/* Copyright (C) 2006-2010 Artifex Software, Inc. - All Rights Reserved. +#include "fitz.h" +#include "muxps.h" - This software is provided AS-IS with no warranty, either express or - implied. - - This software is distributed under license and may not be copied, modified - or distributed except as expressly authorized under the terms of that - license. Refer to licensing information at http://www.artifex.com/ - or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, - San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information. -*/ - -/* XPS interpreter - general font functions */ - -#include "ghostxps.h" - -static void xps_load_sfnt_cmap(xps_font_t *font); - -/* - * Big-endian memory accessor functions - */ - -static inline int s16(byte *p) -{ - return (signed short)( (p[0] << 8) | p[1] ); -} - -static inline int u16(byte *p) -{ - return (p[0] << 8) | p[1]; -} - -static inline int u24(byte *p) -{ - return (p[0] << 16) | (p[1] << 8) | p[2]; -} - -static inline int u32(byte *p) -{ - return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; -} - -xps_font_t * -xps_new_font(xps_context_t *ctx, byte *buf, int buflen, int index) -{ - xps_font_t *font; - int code; - - font = xps_alloc(ctx, sizeof(xps_font_t)); - if (!font) - { - gs_throw(-1, "out of memory"); - return NULL; - } - - font->data = buf; - font->length = buflen; - font->font = NULL; - - font->subfontid = index; - font->cmaptable = 0; - font->cmapsubcount = 0; - font->cmapsubtable = 0; - font->usepua = 0; - - font->cffdata = 0; - font->cffend = 0; - font->gsubrs = 0; - font->subrs = 0; - font->charstrings = 0; - - if (memcmp(font->data, "OTTO", 4) == 0) - code = xps_init_postscript_font(ctx, font); - else if (memcmp(font->data, "\0\1\0\0", 4) == 0) - code = xps_init_truetype_font(ctx, font); - else if (memcmp(font->data, "true", 4) == 0) - code = xps_init_truetype_font(ctx, font); - else if (memcmp(font->data, "ttcf", 4) == 0) - code = xps_init_truetype_font(ctx, font); - else - { - xps_free_font(ctx, font); - gs_throw(-1, "not an opentype font"); - return NULL; - } - - if (code < 0) - { - xps_free_font(ctx, font); - gs_rethrow(-1, "cannot init font"); - return NULL; - } - - xps_load_sfnt_cmap(font); - - return font; -} - -void -xps_free_font(xps_context_t *ctx, xps_font_t *font) -{ - if (font->font) - { - gs_font_finalize(font->font); - gs_free_object(ctx->memory, font->font, "font object"); - } - xps_free(ctx, font); -} - -/* - * Find the offset and length of an SFNT table. - * Return -1 if no table by the specified name is found. - */ - -int -xps_find_sfnt_table(xps_font_t *font, const char *name, int *lengthp) -{ - int offset; - int ntables; - int i; - - if (font->length < 12) - return -1; - - if (!memcmp(font->data, "ttcf", 4)) - { - int nfonts = u32(font->data + 8); - if (font->subfontid < 0 || font->subfontid >= nfonts) - { - gs_warn("Invalid subfont ID"); - return -1; - } - offset = u32(font->data + 12 + font->subfontid * 4); - } - else - { - offset = 0; - } - - ntables = u16(font->data + offset + 4); - if (font->length < offset + 12 + ntables * 16) - return -1; - - for (i = 0; i < ntables; i++) - { - byte *entry = font->data + offset + 12 + i * 16; - if (!memcmp(entry, name, 4)) - { - if (lengthp) - *lengthp = u32(entry + 12); - return u32(entry + 8); - } - } - - return -1; -} - -/* - * Get the windows truetype font file name - position 4 in the name table. - */ -void -xps_load_sfnt_name(xps_font_t *font, char *namep) -{ - byte *namedata; - int offset, length; - int format, count, stringoffset; - int i; - - strcpy(namep, "Unknown"); - - offset = xps_find_sfnt_table(font, "name", &length); - if (offset < 0 || length < 6) - { - gs_warn("cannot find name table"); - return; - } - - namedata = font->data + offset; - - format = u16(namedata + 0); - count = u16(namedata + 2); - stringoffset = u16(namedata + 4); - - for (i = 0; i < count; i++) - { - byte *record = namedata + 6 + i * 12; - int pid = u16(record + 0); - int eid = u16(record + 2); - int langid = u16(record + 4); - int nameid = u16(record + 6); - length = u16(record + 8); - offset = u16(record + 10); - - /* Mac Roman English */ - if (pid == 1 && eid == 0 && langid == 0) - { - /* Full font name or postscript name */ - if (nameid == 4 || nameid == 6) - { - memcpy(namep, namedata + stringoffset + offset, length); - namep[length] = 0; - } - } - } -} - -/* - * Locate the 'cmap' table and count the number of subtables. - */ - -static void -xps_load_sfnt_cmap(xps_font_t *font) -{ - byte *cmapdata; - int offset, length; - int nsubtables; - - offset = xps_find_sfnt_table(font, "cmap", &length); - if (offset < 0 || length < 4) - { - gs_warn("cannot find cmap table"); - return; - } - - cmapdata = font->data + offset; - - nsubtables = u16(cmapdata + 2); - if (nsubtables < 0 || length < 4 + nsubtables * 8) - { - gs_warn("cannot find cmap sub-tables"); - return; - } - - font->cmaptable = offset; - font->cmapsubcount = nsubtables; - font->cmapsubtable = 0; -} - -/* - * Return the number of cmap subtables. - */ +#include <ft2build.h> +#include FT_FREETYPE_H int -xps_count_font_encodings(xps_font_t *font) +xps_count_font_encodings(fz_font *font) { - return font->cmapsubcount; + FT_Face face = font->ftface; + return face->num_charmaps; } -/* - * Extract PlatformID and EncodingID for a cmap subtable. - */ - void -xps_identify_font_encoding(xps_font_t *font, int idx, int *pid, int *eid) +xps_identify_font_encoding(fz_font *font, int idx, int *pid, int *eid) { - byte *cmapdata, *entry; - if (idx < 0 || idx >= font->cmapsubcount) - return; - cmapdata = font->data + font->cmaptable; - entry = cmapdata + 4 + idx * 8; - *pid = u16(entry + 0); - *eid = u16(entry + 2); + FT_Face face = font->ftface; + *pid = face->charmaps[idx]->platform_id; + *eid = face->charmaps[idx]->encoding_id; } -/* - * Select a cmap subtable for use with encoding functions. - */ - void -xps_select_font_encoding(xps_font_t *font, int idx) +xps_select_font_encoding(fz_font *font, int idx) { - byte *cmapdata, *entry; - int pid, eid; - if (idx < 0 || idx >= font->cmapsubcount) - return; - cmapdata = font->data + font->cmaptable; - entry = cmapdata + 4 + idx * 8; - pid = u16(entry + 0); - eid = u16(entry + 2); - font->cmapsubtable = font->cmaptable + u32(entry + 4); - font->usepua = (pid == 3 && eid == 0); -} - -/* - * Encode a character using the selected cmap subtable. - * TODO: extend this to cover more cmap formats. - */ - -static int -xps_encode_font_char_imp(xps_font_t *font, int code) -{ - byte *table; - - /* no cmap selected: return identity */ - if (font->cmapsubtable <= 0) - return code; - - table = font->data + font->cmapsubtable; - - switch (u16(table)) - { - case 0: /* Apple standard 1-to-1 mapping. */ - return table[code + 6]; - - case 4: /* Microsoft/Adobe segmented mapping. */ - { - int segCount2 = u16(table + 6); - byte *endCount = table + 14; - byte *startCount = endCount + segCount2 + 2; - byte *idDelta = startCount + segCount2; - byte *idRangeOffset = idDelta + segCount2; - int i2; - - for (i2 = 0; i2 < segCount2 - 3; i2 += 2) - { - int delta, roff; - int start = u16(startCount + i2); - int glyph; - - if ( code < start ) - return 0; - if ( code > u16(endCount + i2) ) - continue; - delta = s16(idDelta + i2); - roff = s16(idRangeOffset + i2); - if ( roff == 0 ) - { - return ( code + delta ) & 0xffff; /* mod 65536 */ - return 0; - } - glyph = u16(idRangeOffset + i2 + roff + ((code - start) << 1)); - return (glyph == 0 ? 0 : glyph + delta); - } - - /* - * The TrueType documentation says that the last range is - * always supposed to end with 0xffff, so this shouldn't - * happen; however, in some real fonts, it does. - */ - return 0; - } - - case 6: /* Single interval lookup. */ - { - int firstCode = u16(table + 6); - int entryCount = u16(table + 8); - if ( code < firstCode || code >= firstCode + entryCount ) - return 0; - return u16(table + 10 + ((code - firstCode) << 1)); - } - - case 10: /* Trimmed array (like 6) */ - { - int startCharCode = u32(table + 12); - int numChars = u32(table + 16); - if ( code < startCharCode || code >= startCharCode + numChars ) - return 0; - return u32(table + 20 + (code - startCharCode) * 4); - } - - case 12: /* Segmented coverage. (like 4) */ - { - int nGroups = u32(table + 12); - byte *group = table + 16; - int i; - - for (i = 0; i < nGroups; i++) - { - int startCharCode = u32(group + 0); - int endCharCode = u32(group + 4); - int startGlyphID = u32(group + 8); - if ( code < startCharCode ) - return 0; - if ( code <= endCharCode ) - return startGlyphID + (code - startCharCode); - group += 12; - } - - return 0; - } - - case 2: /* High-byte mapping through table. */ - case 8: /* Mixed 16-bit and 32-bit coverage (like 2) */ - default: - gs_warn1("unknown cmap format: %d\n", u16(table)); - return 0; - } - - return 0; + FT_Face face = font->ftface; + FT_Set_Charmap(face, face->charmaps[idx]); } int -xps_encode_font_char(xps_font_t *font, int code) +xps_encode_font_char(fz_font *font, int code) { - int gid = xps_encode_font_char_imp(font, code); - if (gid == 0 && font->usepua) - gid = xps_encode_font_char_imp(font, 0xF000 | code); + FT_Face face = font->ftface; + int gid = FT_Get_Char_Index(face, code); + if (gid == 0 && face->charmap->platform_id == 3 && face->charmap->encoding_id == 0) + gid = FT_Get_Char_Index(face, 0xF000 | code); return gid; } -/* - * Get glyph metrics by parsing TTF tables manually. - * XPS needs more and different metrics than postscript/ghostscript - * use so the native ghostscript functions are not adequate. - */ - void -xps_measure_font_glyph(xps_context_t *ctx, xps_font_t *font, int gid, xps_glyph_metrics_t *mtx) +xps_measure_font_glyph(xps_context_t *ctx, fz_font *font, int gid, xps_glyph_metrics_t *mtx) { - int head, format, loca, glyf; - int ofs, len; - int idx, i, n; int hadv, vadv, vorg; - int vtop, ymax, desc; int scale; - /* some insane defaults */ - scale = 1000; /* units-per-em */ hadv = 500; vadv = -1000; vorg = 1000; - /* - * Horizontal metrics are easy. - */ - - ofs = xps_find_sfnt_table(font, "hhea", &len); - if (ofs < 0 || len < 2 * 18) - { - gs_warn("hhea table is too short"); - return; - } - - vorg = s16(font->data + ofs + 4); /* ascender is default vorg */ - desc = s16(font->data + ofs + 6); /* descender */ - if (desc < 0) - desc = -desc; - n = u16(font->data + ofs + 17 * 2); - - ofs = xps_find_sfnt_table(font, "hmtx", &len); - if (ofs < 0) - { - gs_warn("cannot find hmtx table"); - return; - } - - idx = gid; - if (idx > n - 1) - idx = n - 1; - - hadv = u16(font->data + ofs + idx * 4); - vadv = 0; - - /* - * Vertical metrics are hairy (with missing tables). - */ - - head = xps_find_sfnt_table(font, "head", &len); - if (head > 0) - { - scale = u16(font->data + head + 18); /* units per em */ - } - - ofs = xps_find_sfnt_table(font, "OS/2", &len); - if (ofs > 0 && len > 70) - { - vorg = s16(font->data + ofs + 68); /* sTypoAscender */ - desc = s16(font->data + ofs + 70); /* sTypoDescender */ - if (desc < 0) - desc = -desc; - } - - ofs = xps_find_sfnt_table(font, "vhea", &len); - if (ofs > 0 && len >= 2 * 18) - { - n = u16(font->data + ofs + 17 * 2); - - ofs = xps_find_sfnt_table(font, "vmtx", &len); - if (ofs < 0) - { - gs_warn("cannot find vmtx table"); - return; - } - - idx = gid; - if (idx > n - 1) - idx = n - 1; - - vadv = u16(font->data + ofs + idx * 4); - vtop = u16(font->data + ofs + idx * 4 + 2); - - glyf = xps_find_sfnt_table(font, "glyf", &len); - loca = xps_find_sfnt_table(font, "loca", &len); - if (head > 0 && glyf > 0 && loca > 0) - { - format = u16(font->data + head + 50); /* indexToLocaFormat */ - - if (format == 0) - ofs = u16(font->data + loca + gid * 2) * 2; - else - ofs = u32(font->data + loca + gid * 4); - - ymax = u16(font->data + glyf + ofs + 8); /* yMax */ - - vorg = ymax + vtop; - } - } - - ofs = xps_find_sfnt_table(font, "VORG", &len); - if (ofs > 0) - { - vorg = u16(font->data + ofs + 6); - n = u16(font->data + ofs + 6); - for (i = 0; i < n; i++) - { - if (u16(font->data + ofs + 8 + 4 * i) == gid) - { - vorg = s16(font->data + ofs + 8 + 4 * i + 2); - break; - } - } - } - - if (vadv == 0) - vadv = vorg + desc; - mtx->hadv = hadv / (float) scale; mtx->vadv = vadv / (float) scale; mtx->vorg = vorg / (float) scale; diff --git a/xps/xpsglyphs.c b/xps/xpsglyphs.c index 4709c94b..76da97b1 100644 --- a/xps/xpsglyphs.c +++ b/xps/xpsglyphs.c @@ -1,21 +1,7 @@ -/* Copyright (C) 2006-2010 Artifex Software, Inc. - All Rights Reserved. +#include "fitz.h" +#include "muxps.h" - This software is provided AS-IS with no warranty, either express or - implied. - - This software is distributed under license and may not be copied, modified - or distributed except as expressly authorized under the terms of that - license. Refer to licensing information at http://www.artifex.com/ - or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, - San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information. -*/ - -/* XPS interpreter - text drawing support */ - -#include "ghostxps.h" - -#include <ctype.h> +#include <ctype.h> /* for tolower() */ #define XPS_TEXT_BUFFER_SIZE 300 @@ -26,7 +12,7 @@ struct xps_text_buffer_s int count; float x[XPS_TEXT_BUFFER_SIZE + 1]; float y[XPS_TEXT_BUFFER_SIZE + 1]; - gs_glyph g[XPS_TEXT_BUFFER_SIZE]; + int g[XPS_TEXT_BUFFER_SIZE]; }; static inline int unhex(int i) @@ -36,45 +22,6 @@ static inline int unhex(int i) return tolower(i) - 'a' + 10; } -void -xps_debug_path(xps_context_t *ctx) -{ - segment *seg; - curve_segment *cseg; - - seg = (segment*)ctx->pgs->path->first_subpath; - while (seg) - { - switch (seg->type) - { - case s_start: - dprintf2("%g %g moveto\n", - fixed2float(seg->pt.x) * 0.001, - fixed2float(seg->pt.y) * 0.001); - break; - case s_line: - dprintf2("%g %g lineto\n", - fixed2float(seg->pt.x) * 0.001, - fixed2float(seg->pt.y) * 0.001); - break; - case s_line_close: - dputs("closepath\n"); - break; - case s_curve: - cseg = (curve_segment*)seg; - dprintf6("%g %g %g %g %g %g curveto\n", - fixed2float(cseg->p1.x) * 0.001, - fixed2float(cseg->p1.y) * 0.001, - fixed2float(cseg->p2.x) * 0.001, - fixed2float(cseg->p2.y) * 0.001, - fixed2float(seg->pt.x) * 0.001, - fixed2float(seg->pt.y) * 0.001); - break; - } - seg = seg->next; - } -} - /* * Some fonts in XPS are obfuscated by XOR:ing the first 32 bytes of the * data with the GUID in the fontname. @@ -100,7 +47,7 @@ xps_deobfuscate_font_resource(xps_context_t *ctx, xps_part_t *part) if (i != 32) { - gs_warn("cannot extract GUID from obfuscated font part name"); + fz_warn("cannot extract GUID from obfuscated font part name"); return; } @@ -115,7 +62,7 @@ xps_deobfuscate_font_resource(xps_context_t *ctx, xps_part_t *part) } static void -xps_select_best_font_encoding(xps_font_t *font) +xps_select_best_font_encoding(fz_font *font) { static struct { int pid, eid; } xps_cmap_list[] = { @@ -147,7 +94,7 @@ xps_select_best_font_encoding(xps_font_t *font) } } - gs_warn("could not find a suitable cmap"); + fz_warn("could not find a suitable cmap"); } /* @@ -155,9 +102,10 @@ xps_select_best_font_encoding(xps_font_t *font) */ static int -xps_flush_text_buffer(xps_context_t *ctx, xps_font_t *font, +xps_flush_text_buffer(xps_context_t *ctx, fz_font *font, xps_text_buffer_t *buf, int is_charpath) { +#if 0 gs_text_params_t params; gs_text_enum_t *textenum; float x = buf->x[0]; @@ -166,7 +114,6 @@ xps_flush_text_buffer(xps_context_t *ctx, xps_font_t *font, int i; // dprintf1("flushing text buffer (%d glyphs)\n", buf->count); - gs_moveto(ctx->pgs, x, y); params.operation = TEXT_FROM_GLYPHS | TEXT_REPLACE_WIDTHS; @@ -192,15 +139,15 @@ xps_flush_text_buffer(xps_context_t *ctx, xps_font_t *font, code = gs_text_begin(ctx->pgs, ¶ms, ctx->memory, &textenum); if (code != 0) - return gs_throw1(-1, "cannot gs_text_begin() (%d)", code); + return fz_throw("cannot gs_text_begin() (%d)", code); code = gs_text_process(textenum); if (code != 0) - return gs_throw1(-1, "cannot gs_text_process() (%d)", code); + return fz_throw("cannot gs_text_process() (%d)", code); gs_text_release(textenum, "gslt font render"); - +#endif buf->count = 0; return 0; @@ -293,7 +240,7 @@ xps_parse_glyph_metrics(char *s, float *advance, float *uofs, float *vofs) * Calculate metrics for positioning. */ static int -xps_parse_glyphs_imp(xps_context_t *ctx, xps_font_t *font, float size, +xps_parse_glyphs_imp(xps_context_t *ctx, fz_font *font, float size, float originx, float originy, int is_sideways, int bidi_level, char *indices, char *unicode, int is_charpath) { @@ -309,7 +256,7 @@ xps_parse_glyphs_imp(xps_context_t *ctx, xps_font_t *font, float size, buf.count = 0; if (!unicode && !indices) - return gs_throw(-1, "no text in glyphs element"); + return fz_throw("no text in glyphs element"); if (us) { @@ -354,7 +301,7 @@ xps_parse_glyphs_imp(xps_context_t *ctx, xps_font_t *font, float size, { int t = xps_utf8_to_ucs(&char_code, us, un); if (t < 0) - return gs_rethrow(-1, "error decoding UTF-8 string"); + return fz_rethrow(-1, "error decoding UTF-8 string"); us += t; un -= t; } code_count --; @@ -379,7 +326,7 @@ xps_parse_glyphs_imp(xps_context_t *ctx, xps_font_t *font, float size, } #if 0 - dprintf6("glyph mapping (%d:%d)%d,%g,%g,%g\n", + printf("glyph mapping (%d:%d)%d,%g,%g,%g\n", code_count, glyph_count, glyph_index, advance, u_offset, v_offset); #endif @@ -394,7 +341,7 @@ xps_parse_glyphs_imp(xps_context_t *ctx, xps_font_t *font, float size, { code = xps_flush_text_buffer(ctx, font, &buf, is_charpath); if (code) - return gs_rethrow(code, "cannot flush buffered text"); + return fz_rethrow(code, "cannot flush buffered text"); } if (is_sideways) @@ -418,14 +365,14 @@ xps_parse_glyphs_imp(xps_context_t *ctx, xps_font_t *font, float size, { code = xps_flush_text_buffer(ctx, font, &buf, is_charpath); if (code) - return gs_rethrow(code, "cannot flush buffered text"); + return fz_rethrow(code, "cannot flush buffered text"); } return 0; } int -xps_parse_glyphs(xps_context_t *ctx, +xps_parse_glyphs(xps_context_t *ctx, fz_matrix ctm, char *base_uri, xps_resource_t *dict, xps_item_t *root) { xps_item_t *node; @@ -458,12 +405,12 @@ xps_parse_glyphs(xps_context_t *ctx, char *fill_opacity_att = NULL; xps_part_t *part; - xps_font_t *font; + fz_font *font; char partname[1024]; char *subfont; - gs_matrix matrix; + fz_matrix matrix; float font_size = 10.0; int subfontid = 0; int is_sideways = 0; @@ -517,7 +464,7 @@ xps_parse_glyphs(xps_context_t *ctx, */ if (!font_size_att || !font_uri_att || !origin_x_att || !origin_y_att) - return gs_throw(-1, "missing attributes in glyphs element"); + return fz_throw("missing attributes in glyphs element"); if (!indices_att && !unicode_att) return 0; /* nothing to draw */ @@ -545,7 +492,7 @@ xps_parse_glyphs(xps_context_t *ctx, { part = xps_read_part(ctx, partname); if (!part) - return gs_throw1(-1, "cannot find font resource part '%s'", partname); + return fz_throw("cannot find font resource part '%s'", partname); /* deobfuscate if necessary */ if (strstr(part->name, ".odttf")) @@ -553,9 +500,9 @@ xps_parse_glyphs(xps_context_t *ctx, if (strstr(part->name, ".ODTTF")) xps_deobfuscate_font_resource(ctx, part); - font = xps_new_font(ctx, part->data, part->size, subfontid); - if (!font) - return gs_rethrow1(-1, "cannot load font resource '%s'", partname); + code = fz_newfontfrombuffer(&font, part->data, part->size, subfontid); + if (code) + return fz_rethrow(code, "cannot load font resource '%s'", partname); xps_select_best_font_encoding(font); @@ -568,12 +515,12 @@ xps_parse_glyphs(xps_context_t *ctx, /* * Set up graphics state. */ - +#if 0 gs_gsave(ctx->pgs); if (transform_att || transform_tag) { - gs_matrix transform; + fz_matrix transform; if (transform_att) xps_parse_render_transform(ctx, transform_att, &transform); @@ -585,6 +532,7 @@ xps_parse_glyphs(xps_context_t *ctx, if (clip_att || clip_tag) { + ctx->path = fz_newpath(); if (clip_att) xps_parse_abbreviated_geometry(ctx, clip_att); if (clip_tag) @@ -597,17 +545,17 @@ xps_parse_glyphs(xps_context_t *ctx, gs_setfont(ctx->pgs, font->font); gs_make_scaling(font_size, -font_size, &matrix); if (is_sideways) - gs_matrix_rotate(&matrix, 90.0, &matrix); + fz_matrix_rotate(&matrix, 90.0, &matrix); gs_setcharmatrix(ctx->pgs, &matrix); - gs_matrix_multiply(&matrix, &font->font->orig_FontMatrix, &font->font->FontMatrix); + fz_matrix_multiply(&matrix, &font->font->orig_FontMatrix, &font->font->FontMatrix); code = xps_begin_opacity(ctx, opacity_mask_uri, dict, opacity_att, opacity_mask_tag); if (code) { gs_grestore(ctx->pgs); - return gs_rethrow(code, "cannot create transparency group"); + return fz_rethrow(code, "cannot create transparency group"); } /* @@ -624,7 +572,7 @@ xps_parse_glyphs(xps_context_t *ctx, if (fill_att) { float samples[32]; - gs_color_space *colorspace; + fz_colorspace *colorspace; xps_parse_color(ctx, base_uri, fill_att, &colorspace, samples); if (fill_opacity_att) samples[0] = atof(fill_opacity_att); @@ -637,7 +585,7 @@ xps_parse_glyphs(xps_context_t *ctx, { xps_end_opacity(ctx, opacity_mask_uri, dict, opacity_att, opacity_mask_tag); gs_grestore(ctx->pgs); - return gs_rethrow(code, "cannot parse glyphs data"); + return fz_rethrow(code, "cannot parse glyphs data"); } } @@ -655,7 +603,7 @@ xps_parse_glyphs(xps_context_t *ctx, { xps_end_opacity(ctx, opacity_mask_uri, dict, opacity_att, opacity_mask_tag); gs_grestore(ctx->pgs); - return gs_rethrow(code, "cannot parse glyphs data"); + return fz_rethrow(code, "cannot parse glyphs data"); } code = xps_parse_brush(ctx, fill_uri, dict, fill_tag); @@ -663,13 +611,13 @@ xps_parse_glyphs(xps_context_t *ctx, { xps_end_opacity(ctx, opacity_mask_uri, dict, opacity_att, opacity_mask_tag); gs_grestore(ctx->pgs); - return gs_rethrow(code, "cannot parse fill brush"); + return fz_rethrow(code, "cannot parse fill brush"); } } xps_end_opacity(ctx, opacity_mask_uri, dict, opacity_att, opacity_mask_tag); gs_grestore(ctx->pgs); - +#endif return 0; } diff --git a/xps/xpsgradient.c b/xps/xpsgradient.c index 0c6bcf60..3bb95824 100644 --- a/xps/xpsgradient.c +++ b/xps/xpsgradient.c @@ -1,19 +1,5 @@ -/* Copyright (C) 2006-2010 Artifex Software, Inc. - All Rights Reserved. - - This software is provided AS-IS with no warranty, either express or - implied. - - This software is distributed under license and may not be copied, modified - or distributed except as expressly authorized under the terms of that - license. Refer to licensing information at http://www.artifex.com/ - or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, - San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information. -*/ - -/* XPS interpreter - gradient support */ - -#include "ghostxps.h" +#include "fitz.h" +#include "muxps.h" #define MAX_STOPS 256 @@ -52,11 +38,9 @@ static int xps_parse_gradient_stops(xps_context_t *ctx, char *base_uri, xps_item_t *node, struct stop *stops, int maxcount) { - unsigned short sample_in[8], sample_out[8]; /* XPS allows up to 8 bands */ - gsicc_rendering_param_t rendering_params; - gsicc_link_t *icclink; - gs_color_space *colorspace; + fz_colorspace *colorspace; float sample[8]; + float rgb[3]; int before, after; int count; int i, k; @@ -77,53 +61,22 @@ xps_parse_gradient_stops(xps_context_t *ctx, char *base_uri, xps_item_t *node, xps_parse_color(ctx, base_uri, color, &colorspace, sample); - /* Set the rendering parameters */ - rendering_params.black_point_comp = BP_ON; - rendering_params.object_type = GS_PATH_TAG; - rendering_params.rendering_intent = gsPERCEPTUAL; - - /* Get link to map from source to sRGB */ - icclink = gsicc_get_link((gs_imager_state*) ctx->pgs, - NULL, colorspace, ctx->srgb, - &rendering_params, ctx->memory, false); - - if (icclink != NULL && !icclink->is_identity) - { - /* Transform the color */ - int num_colors = gsicc_getsrc_channel_count(colorspace->cmm_icc_profile_data); - for (i = 0; i < num_colors; i++) - { - sample_in[i] = sample[i+1]*65535; - } - gscms_transform_color(icclink, sample_in, sample_out, 2, NULL); - - stops[count].color[0] = sample[0]; /* Alpha */ - stops[count].color[1] = (float) sample_out[0] / 65535.0; /* sRGB */ - stops[count].color[2] = (float) sample_out[1] / 65535.0; - stops[count].color[3] = (float) sample_out[2] / 65535.0; - } - else - { - stops[count].color[0] = sample[0]; - stops[count].color[1] = sample[1]; - stops[count].color[2] = sample[2]; - stops[count].color[3] = sample[3]; - } + fz_convertcolor(colorspace, sample + 1, fz_devicergb, rgb); + + stops[count].color[0] = sample[0]; + stops[count].color[1] = rgb[0]; + stops[count].color[2] = rgb[1]; + stops[count].color[3] = rgb[2]; count ++; } } - - if (icclink != NULL) - gsicc_release_link(icclink); - icclink = NULL; node = xps_next(node); - } if (count == 0) { - gs_warn("gradient brush has no gradient stops"); + fz_warn("gradient brush has no gradient stops"); stops[0].offset = 0; stops[0].color[0] = 1; stops[0].color[1] = 0; @@ -138,7 +91,7 @@ xps_parse_gradient_stops(xps_context_t *ctx, char *base_uri, xps_item_t *node, } if (count == maxcount) - gs_warn("gradient brush exceeded maximum number of gradient stops"); + fz_warn("gradient brush exceeded maximum number of gradient stops"); /* Postprocess to make sure the range of offsets is 0.0 to 1.0 */ @@ -227,219 +180,6 @@ xps_gradient_has_transparent_colors(struct stop *stops, int count) } /* - * Create a Function object to map [0..1] to RGB colors - * based on the gradient stop arrays. - * - * We do this by creating a stitching function that joins - * a series of linear functions (one linear function - * for each gradient stop-pair). - */ - -static gs_function_t * -xps_create_gradient_stop_function(xps_context_t *ctx, struct stop *stops, int count, int opacity_only) -{ - gs_function_1ItSg_params_t sparams; - gs_function_ElIn_params_t lparams; - gs_function_t *sfunc; - gs_function_t *lfunc; - - float *domain, *range, *c0, *c1, *bounds, *encode; - const gs_function_t **functions; - - int code; - int k; - int i; - - k = count - 1; /* number of intervals / functions */ - - domain = xps_alloc(ctx, 2 * sizeof(float)); - domain[0] = 0.0; - domain[1] = 1.0; - sparams.m = 1; - sparams.Domain = domain; - - range = xps_alloc(ctx, 6 * sizeof(float)); - range[0] = 0.0; - range[1] = 1.0; - range[2] = 0.0; - range[3] = 1.0; - range[4] = 0.0; - range[5] = 1.0; - sparams.n = 3; - sparams.Range = range; - - functions = xps_alloc(ctx, k * sizeof(void*)); - bounds = xps_alloc(ctx, (k - 1) * sizeof(float)); - encode = xps_alloc(ctx, (k * 2) * sizeof(float)); - - sparams.k = k; - sparams.Functions = functions; - sparams.Bounds = bounds; - sparams.Encode = encode; - - for (i = 0; i < k; i++) - { - domain = xps_alloc(ctx, 2 * sizeof(float)); - domain[0] = 0.0; - domain[1] = 1.0; - lparams.m = 1; - lparams.Domain = domain; - - range = xps_alloc(ctx, 6 * sizeof(float)); - range[0] = 0.0; - range[1] = 1.0; - range[2] = 0.0; - range[3] = 1.0; - range[4] = 0.0; - range[5] = 1.0; - lparams.n = 3; - lparams.Range = range; - - c0 = xps_alloc(ctx, 3 * sizeof(float)); - lparams.C0 = c0; - - c1 = xps_alloc(ctx, 3 * sizeof(float)); - lparams.C1 = c1; - - if (opacity_only) - { - c0[0] = stops[i].color[0]; - c0[1] = stops[i].color[0]; - c0[2] = stops[i].color[0]; - - c1[0] = stops[i+1].color[0]; - c1[1] = stops[i+1].color[0]; - c1[2] = stops[i+1].color[0]; - } - else - { - c0[0] = stops[i].color[1]; - c0[1] = stops[i].color[2]; - c0[2] = stops[i].color[3]; - - c1[0] = stops[i+1].color[1]; - c1[1] = stops[i+1].color[2]; - c1[2] = stops[i+1].color[3]; - } - - lparams.N = 1; - - code = gs_function_ElIn_init(&lfunc, &lparams, ctx->memory); - if (code < 0) - { - gs_rethrow(code, "gs_function_ElIn_init failed"); - return NULL; - } - - functions[i] = lfunc; - - if (i > 0) - bounds[i - 1] = stops[i].offset; - - encode[i * 2 + 0] = 0.0; - encode[i * 2 + 1] = 1.0; - } - - code = gs_function_1ItSg_init(&sfunc, &sparams, ctx->memory); - if (code < 0) - { - gs_rethrow(code, "gs_function_1ItSg_init failed"); - return NULL; - } - - return sfunc; -} - -/* - * Shadings and functions are ghostscript type objects, - * and as such rely on the garbage collector for cleanup. - * We can't have none of that here, so we have to - * write our own destructors. - */ - -static void -xps_free_gradient_stop_function(xps_context_t *ctx, gs_function_t *func) -{ - gs_function_t *lfunc; - gs_function_1ItSg_params_t *sparams; - gs_function_ElIn_params_t *lparams; - int i; - - sparams = (gs_function_1ItSg_params_t*) &func->params; - xps_free(ctx, (void*)sparams->Domain); - xps_free(ctx, (void*)sparams->Range); - - for (i = 0; i < sparams->k; i++) - { - lfunc = (gs_function_t*) sparams->Functions[i]; /* discard const */ - lparams = (gs_function_ElIn_params_t*) &lfunc->params; - xps_free(ctx, (void*)lparams->Domain); - xps_free(ctx, (void*)lparams->Range); - xps_free(ctx, (void*)lparams->C0); - xps_free(ctx, (void*)lparams->C1); - xps_free(ctx, lfunc); - } - - xps_free(ctx, (void*)sparams->Bounds); - xps_free(ctx, (void*)sparams->Encode); - xps_free(ctx, (void*)sparams->Functions); - xps_free(ctx, func); -} - -/* - * For radial gradients that have a cone drawing we have to - * reverse the direction of the gradient because we draw - * the shading in the opposite direction with the - * big circle first. - */ -static gs_function_t * -xps_reverse_function(xps_context_t *ctx, gs_function_t *func, float *fary, void *vary) -{ - gs_function_1ItSg_params_t sparams; - gs_function_t *sfunc; - int code; - - /* take from stack allocated arrays that the caller provides */ - float *domain = fary + 0; - float *range = fary + 2; - float *encode = fary + 2 + 6; - const gs_function_t **functions = vary; - - domain[0] = 0.0; - domain[1] = 1.0; - - range[0] = 0.0; - range[1] = 1.0; - range[2] = 0.0; - range[3] = 1.0; - range[4] = 0.0; - range[5] = 1.0; - - functions[0] = func; - - encode[0] = 1.0; - encode[1] = 0.0; - - sparams.m = 1; - sparams.Domain = domain; - sparams.n = 3; - sparams.Range = range; - sparams.k = 1; - sparams.Functions = functions; - sparams.Bounds = NULL; - sparams.Encode = encode; - - code = gs_function_1ItSg_init(&sfunc, &sparams, ctx->memory); - if (code < 0) - { - gs_rethrow(code, "gs_function_1ItSg_init failed"); - return NULL; - } - - return sfunc; -} - -/* * Radial gradients map more or less to Radial shadings. * The inner circle is always a point. * The outer circle is actually an ellipse, @@ -448,10 +188,11 @@ xps_reverse_function(xps_context_t *ctx, gs_function_t *func, float *fary, void static int xps_draw_one_radial_gradient(xps_context_t *ctx, - gs_function_t *func, int extend, + int extend, float x0, float y0, float r0, float x1, float y1, float r1) { +#if 0 gs_memory_t *mem = ctx->memory; gs_shading_t *shading; gs_shading_R_params_t params; @@ -476,7 +217,7 @@ xps_draw_one_radial_gradient(xps_context_t *ctx, code = gs_shading_R_init(&shading, ¶ms, mem); if (code < 0) - return gs_rethrow(code, "gs_shading_R_init failed"); + return fz_rethrow(code, "gs_shading_R_init failed"); gs_setsmoothness(ctx->pgs, 0.02); @@ -484,11 +225,11 @@ xps_draw_one_radial_gradient(xps_context_t *ctx, if (code < 0) { gs_free_object(mem, shading, "gs_shading_R"); - return gs_rethrow(code, "gs_shfill failed"); + return fz_rethrow(code, "gs_shfill failed"); } gs_free_object(mem, shading, "gs_shading_R"); - +#endif return 0; } @@ -498,9 +239,10 @@ xps_draw_one_radial_gradient(xps_context_t *ctx, static int xps_draw_one_linear_gradient(xps_context_t *ctx, - gs_function_t *func, int extend, + int extend, float x0, float y0, float x1, float y1) { +#if 0 gs_memory_t *mem = ctx->memory; gs_shading_t *shading; gs_shading_A_params_t params; @@ -523,7 +265,7 @@ xps_draw_one_linear_gradient(xps_context_t *ctx, code = gs_shading_A_init(&shading, ¶ms, mem); if (code < 0) - return gs_rethrow(code, "gs_shading_A_init failed"); + return fz_rethrow(code, "gs_shading_A_init failed"); gs_setsmoothness(ctx->pgs, 0.02); @@ -531,11 +273,11 @@ xps_draw_one_linear_gradient(xps_context_t *ctx, if (code < 0) { gs_free_object(mem, shading, "gs_shading_A"); - return gs_rethrow(code, "gs_shfill failed"); + return fz_rethrow(code, "gs_shfill failed"); } gs_free_object(mem, shading, "gs_shading_A"); - +#endif return 0; } @@ -555,9 +297,9 @@ static inline float point_inside_circle(float px, float py, float x, float y, fl } static int -xps_draw_radial_gradient(xps_context_t *ctx, xps_item_t *root, int spread, gs_function_t *func) +xps_draw_radial_gradient(xps_context_t *ctx, xps_item_t *root, int spread) { - gs_rect bbox; + fz_rect bbox; float x0, y0, r0; float x1, y1, r1; float xrad = 1; @@ -583,8 +325,8 @@ xps_draw_radial_gradient(xps_context_t *ctx, xps_item_t *root, int spread, gs_fu yrad = atof(radius_y_att); /* scale the ctm to make ellipses */ - gs_gsave(ctx->pgs); - gs_scale(ctx->pgs, 1.0, yrad / xrad); +// gs_gsave(ctx->pgs); +// gs_scale(ctx->pgs, 1.0, yrad / xrad); invscale = xrad / yrad; y0 = y0 * invscale; @@ -602,7 +344,7 @@ xps_draw_radial_gradient(xps_context_t *ctx, xps_item_t *root, int spread, gs_fu { if (!point_inside_circle(x0, y0, x1, y1, r1)) { - gs_function_t *reverse; +#if 0 float in[1]; float out[4]; float fary[10]; @@ -612,7 +354,6 @@ xps_draw_radial_gradient(xps_context_t *ctx, xps_item_t *root, int spread, gs_fu * gradients when the radial shading is a cone. In this case * we fill the background ourselves. */ - in[0] = 1.0; out[0] = 1.0; out[1] = 0.0; @@ -637,30 +378,25 @@ xps_draw_radial_gradient(xps_context_t *ctx, xps_item_t *root, int spread, gs_fu * have to reverse the direction of the function to compensate. */ - reverse = xps_reverse_function(ctx, func, fary, vary); - if (!reverse) - { - gs_grestore(ctx->pgs); - return gs_rethrow(-1, "could not create the reversed function"); - } +// reverse = xps_reverse_function(ctx, func, fary, vary); code = xps_draw_one_radial_gradient(ctx, reverse, 1, x1, y1, r1, x0, y0, r0); if (code < 0) { xps_free(ctx, reverse); gs_grestore(ctx->pgs); - return gs_rethrow(code, "could not draw radial gradient"); + return fz_rethrow(code, "could not draw radial gradient"); } - xps_free(ctx, reverse); +#endif } else { - code = xps_draw_one_radial_gradient(ctx, func, 1, x0, y0, r0, x1, y1, r1); + code = xps_draw_one_radial_gradient(ctx, 1, x0, y0, r0, x1, y1, r1); if (code < 0) { - gs_grestore(ctx->pgs); - return gs_rethrow(code, "could not draw radial gradient"); +// gs_grestore(ctx->pgs); + return fz_rethrow(code, "could not draw radial gradient"); } } } @@ -671,25 +407,25 @@ xps_draw_radial_gradient(xps_context_t *ctx, xps_item_t *root, int spread, gs_fu /* Draw current circle */ if (!point_inside_circle(x0, y0, x1, y1, r1)) - dputs("xps: we should reverse gradient here too\n"); + printf("xps: we should reverse gradient here too\n"); if (spread == SPREAD_REFLECT && (i & 1)) - code = xps_draw_one_radial_gradient(ctx, func, 0, x1, y1, r1, x0, y0, r0); + code = xps_draw_one_radial_gradient(ctx, 0, x1, y1, r1, x0, y0, r0); else - code = xps_draw_one_radial_gradient(ctx, func, 0, x0, y0, r0, x1, y1, r1); + code = xps_draw_one_radial_gradient(ctx, 0, x0, y0, r0, x1, y1, r1); if (code < 0) { - gs_grestore(ctx->pgs); - return gs_rethrow(code, "could not draw axial gradient"); +// gs_grestore(ctx->pgs); + return fz_rethrow(code, "could not draw axial gradient"); } /* Check if circle encompassed the entire bounding box (break loop if we do) */ done = 1; - if (!point_inside_circle(bbox.p.x, bbox.p.y, x1, y1, r1)) done = 0; - if (!point_inside_circle(bbox.p.x, bbox.q.y, x1, y1, r1)) done = 0; - if (!point_inside_circle(bbox.q.x, bbox.q.y, x1, y1, r1)) done = 0; - if (!point_inside_circle(bbox.q.x, bbox.p.y, x1, y1, r1)) done = 0; + if (!point_inside_circle(bbox.x0, bbox.y0, x1, y1, r1)) done = 0; + if (!point_inside_circle(bbox.x0, bbox.y1, x1, y1, r1)) done = 0; + if (!point_inside_circle(bbox.x1, bbox.y1, x1, y1, r1)) done = 0; + if (!point_inside_circle(bbox.x1, bbox.y0, x1, y1, r1)) done = 0; if (done) break; @@ -705,7 +441,7 @@ xps_draw_radial_gradient(xps_context_t *ctx, xps_item_t *root, int spread, gs_fu } } - gs_grestore(ctx->pgs); +// gs_grestore(ctx->pgs); return 0; } @@ -716,9 +452,9 @@ xps_draw_radial_gradient(xps_context_t *ctx, xps_item_t *root, int spread, gs_fu */ static int -xps_draw_linear_gradient(xps_context_t *ctx, xps_item_t *root, int spread, gs_function_t *func) +xps_draw_linear_gradient(xps_context_t *ctx, xps_item_t *root, int spread) { - gs_rect bbox; + fz_rect bbox; float x0, y0, x1, y1; float dx, dy; int code; @@ -744,9 +480,9 @@ xps_draw_linear_gradient(xps_context_t *ctx, xps_item_t *root, int spread, gs_fu if (spread == SPREAD_PAD) { - code = xps_draw_one_linear_gradient(ctx, func, 1, x0, y0, x1, y1); + code = xps_draw_one_linear_gradient(ctx, 1, x0, y0, x1, y1); if (code < 0) - return gs_rethrow(code, "could not draw axial gradient"); + return fz_rethrow(code, "could not draw axial gradient"); } else { @@ -760,10 +496,10 @@ xps_draw_linear_gradient(xps_context_t *ctx, xps_item_t *root, int spread, gs_fu a = dx / len; b = dy / len; - dist[0] = a * (bbox.p.x - x0) + b * (bbox.p.y - y0); - dist[1] = a * (bbox.p.x - x0) + b * (bbox.q.y - y0); - dist[2] = a * (bbox.q.x - x0) + b * (bbox.q.y - y0); - dist[3] = a * (bbox.q.x - x0) + b * (bbox.p.y - y0); + dist[0] = a * (bbox.x0 - x0) + b * (bbox.y0 - y0); + dist[1] = a * (bbox.x0 - x0) + b * (bbox.y1 - y0); + dist[2] = a * (bbox.x1 - x0) + b * (bbox.y1 - y0); + dist[3] = a * (bbox.x1 - x0) + b * (bbox.y0 - y0); d0 = dist[0]; d1 = dist[0]; @@ -780,18 +516,18 @@ xps_draw_linear_gradient(xps_context_t *ctx, xps_item_t *root, int spread, gs_fu { if (spread == SPREAD_REFLECT && (i & 1)) { - code = xps_draw_one_linear_gradient(ctx, func, 0, + code = xps_draw_one_linear_gradient(ctx, 0, x1 + dx * i, y1 + dy * i, x0 + dx * i, y0 + dy * i); } else { - code = xps_draw_one_linear_gradient(ctx, func, 0, + code = xps_draw_one_linear_gradient(ctx, 0, x0 + dx * i, y0 + dy * i, x1 + dx * i, y1 + dy * i); } if (code < 0) - return gs_rethrow(code, "could not draw axial gradient"); + return fz_rethrow(code, "could not draw axial gradient"); } } @@ -804,8 +540,9 @@ xps_draw_linear_gradient(xps_context_t *ctx, xps_item_t *root, int spread, gs_fu */ static int -xps_parse_gradient_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, xps_item_t *root, - int (*draw)(xps_context_t *, xps_item_t *, int, gs_function_t *)) +xps_parse_gradient_brush(xps_context_t *ctx, fz_matrix ctm, + char *base_uri, xps_resource_t *dict, xps_item_t *root, + int (*draw)(xps_context_t *, xps_item_t *, int)) { xps_item_t *node; @@ -820,14 +557,11 @@ xps_parse_gradient_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dic struct stop stop_list[MAX_STOPS]; int stop_count; - gs_matrix transform; + fz_matrix transform; int spread_method; - int code; - gs_rect bbox; + fz_rect bbox; - gs_function_t *color_func; - gs_function_t *opacity_func; int has_opacity = 0; opacity_att = xps_att(root, "Opacity"); @@ -861,41 +595,42 @@ xps_parse_gradient_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dic spread_method = SPREAD_REPEAT; } - gs_make_identity(&transform); + xps_clip(ctx, ctm); + + transform = fz_identity; if (transform_att) xps_parse_render_transform(ctx, transform_att, &transform); if (transform_tag) xps_parse_matrix_transform(ctx, transform_tag, &transform); + ctm = fz_concat(ctm, transform); if (!stop_tag) - return gs_throw(-1, "missing gradient stops tag"); + return fz_throw("missing gradient stops tag"); stop_count = xps_parse_gradient_stops(ctx, base_uri, stop_tag, stop_list, MAX_STOPS); if (stop_count == 0) - return gs_throw(-1, "no gradient stops found"); + return fz_throw("no gradient stops found"); +/* color_func = xps_create_gradient_stop_function(ctx, stop_list, stop_count, 0); if (!color_func) - return gs_rethrow(-1, "could not create color gradient function"); + return fz_rethrow(-1, "could not create color gradient function"); opacity_func = xps_create_gradient_stop_function(ctx, stop_list, stop_count, 1); if (!opacity_func) - return gs_rethrow(-1, "could not create opacity gradient function"); + return fz_rethrow(-1, "could not create opacity gradient function"); +*/ has_opacity = xps_gradient_has_transparent_colors(stop_list, stop_count); - xps_clip(ctx); - - gs_gsave(ctx->pgs); - gs_concat(ctx->pgs, &transform); - xps_bounds_in_user_space(ctx, &bbox); +#if 0 code = xps_begin_opacity(ctx, base_uri, dict, opacity_att, NULL); if (code) { gs_grestore(ctx->pgs); - return gs_rethrow(code, "cannot create transparency group"); + return fz_rethrow(code, "cannot create transparency group"); } if (ctx->opacity_only) @@ -904,7 +639,7 @@ xps_parse_gradient_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dic if (code) { gs_grestore(ctx->pgs); - return gs_rethrow(code, "cannot draw gradient opacity"); + return fz_rethrow(code, "cannot draw gradient opacity"); } } else @@ -921,7 +656,7 @@ xps_parse_gradient_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dic { gs_end_transparency_mask(ctx->pgs, TRANSPARENCY_CHANNEL_Opacity); gs_grestore(ctx->pgs); - return gs_rethrow(code, "cannot draw gradient opacity"); + return fz_rethrow(code, "cannot draw gradient opacity"); } gs_end_transparency_mask(ctx->pgs, TRANSPARENCY_CHANNEL_Opacity); @@ -932,7 +667,7 @@ xps_parse_gradient_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dic { gs_end_transparency_group(ctx->pgs); gs_grestore(ctx->pgs); - return gs_rethrow(code, "cannot draw gradient color"); + return fz_rethrow(code, "cannot draw gradient color"); } gs_end_transparency_group(ctx->pgs); } @@ -942,37 +677,40 @@ xps_parse_gradient_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dic if (code) { gs_grestore(ctx->pgs); - return gs_rethrow(code, "cannot draw gradient color"); + return fz_rethrow(code, "cannot draw gradient color"); } } } +#endif xps_end_opacity(ctx, base_uri, dict, opacity_att, NULL); - gs_grestore(ctx->pgs); +// gs_grestore(ctx->pgs); - xps_free_gradient_stop_function(ctx, opacity_func); - xps_free_gradient_stop_function(ctx, color_func); +// xps_free_gradient_stop_function(ctx, opacity_func); +// xps_free_gradient_stop_function(ctx, color_func); return 0; } int -xps_parse_linear_gradient_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, xps_item_t *root) +xps_parse_linear_gradient_brush(xps_context_t *ctx, fz_matrix ctm, + char *base_uri, xps_resource_t *dict, xps_item_t *root) { int code; - code = xps_parse_gradient_brush(ctx, base_uri, dict, root, xps_draw_linear_gradient); + code = xps_parse_gradient_brush(ctx, ctm, base_uri, dict, root, xps_draw_linear_gradient); if (code < 0) - return gs_rethrow(code, "cannot parse linear gradient brush"); - return gs_okay; + return fz_rethrow(code, "cannot parse linear gradient brush"); + return fz_okay; } int -xps_parse_radial_gradient_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, xps_item_t *root) +xps_parse_radial_gradient_brush(xps_context_t *ctx, fz_matrix ctm, + char *base_uri, xps_resource_t *dict, xps_item_t *root) { int code; - code = xps_parse_gradient_brush(ctx, base_uri, dict, root, xps_draw_radial_gradient); + code = xps_parse_gradient_brush(ctx, ctm, base_uri, dict, root, xps_draw_radial_gradient); if (code < 0) - return gs_rethrow(code, "cannot parse radial gradient brush"); - return gs_okay; + return fz_rethrow(code, "cannot parse radial gradient brush"); + return fz_okay; } diff --git a/xps/xpshash.c b/xps/xpshash.c index 459566c9..1e562ff3 100644 --- a/xps/xpshash.c +++ b/xps/xpshash.c @@ -1,16 +1,3 @@ -/* Copyright (C) 2006-2010 Artifex Software, Inc. - All Rights Reserved. - - This software is provided AS-IS with no warranty, either express or - implied. - - This software is distributed under license and may not be copied, modified - or distributed except as expressly authorized under the terms of that - license. Refer to licensing information at http://www.artifex.com/ - or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, - San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information. -*/ - /* Linear probe hash table. * * Simple hashtable with open adressing linear probe. @@ -18,7 +5,8 @@ * Does not support deleting entries. */ -#include "ghostxps.h" +#include "fitz.h" +#include "muxps.h" static const unsigned primes[] = { @@ -67,7 +55,7 @@ xps_hash_new(xps_context_t *ctx) table = xps_alloc(ctx, sizeof(xps_hash_table_t)); if (!table) { - gs_throw(-1, "out of memory: hash table struct"); + fz_throw("out of memory: hash table struct"); return NULL; } @@ -78,7 +66,7 @@ xps_hash_new(xps_context_t *ctx) if (!table->entries) { xps_free(ctx, table); - gs_throw(-1, "out of memory: hash table entries array"); + fz_throw("out of memory: hash table entries array"); return NULL; } @@ -108,7 +96,7 @@ xps_hash_double(xps_context_t *ctx, xps_hash_table_t *table) old_entries = table->entries; new_entries = xps_alloc(ctx, sizeof(xps_hash_entry_t) * new_size); if (!new_entries) - return gs_throw(-1, "out of memory: hash table entries array"); + return fz_throw("out of memory: hash table entries array"); table->size = new_size; table->entries = new_entries; @@ -173,7 +161,7 @@ xps_hash_insert(xps_context_t *ctx, xps_hash_table_t *table, char *key, void *va if (table->load > table->size * 8 / 10) { if (xps_hash_double(ctx, table) < 0) - return gs_rethrow(-1, "cannot grow hash table"); + return fz_rethrow(-1, "cannot grow hash table"); } entries = table->entries; diff --git a/xps/xpsimage.c b/xps/xpsimage.c index 7a69ba09..15257594 100644 --- a/xps/xpsimage.c +++ b/xps/xpsimage.c @@ -1,274 +1,68 @@ -/* Copyright (C) 2006-2010 Artifex Software, Inc. - All Rights Reserved. - - This software is provided AS-IS with no warranty, either express or - implied. - - This software is distributed under license and may not be copied, modified - or distributed except as expressly authorized under the terms of that - license. Refer to licensing information at http://www.artifex.com/ - or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, - San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information. -*/ - -/* XPS interpreter - image support */ - -/* TODO: we should be smarter here and do incremental decoding - * and rendering instead of uncompressing the whole image to - * memory before drawing. - */ - -#include "ghostxps.h" - -/* - * Un-interleave the alpha channel. - */ - -static void -xps_isolate_alpha_channel_8(xps_context_t *ctx, xps_image_t *image) -{ - int n = image->comps; - int y, x, k; - byte *sp, *dp, *ap; - - image->alpha = xps_alloc(ctx, image->width * image->height); - - for (y = 0; y < image->height; y++) - { - sp = image->samples + image->width * n * y; - dp = image->samples + image->width * (n - 1) * y; - ap = image->alpha + image->width * y; - for (x = 0; x < image->width; x++) - { - for (k = 0; k < n - 1; k++) - *dp++ = *sp++; - *ap++ = *sp++; - } - } - - image->hasalpha = 0; - image->comps --; - image->stride = image->width * image->comps; -} - -static void -xps_isolate_alpha_channel_16(xps_context_t *ctx, xps_image_t *image) -{ - int n = image->comps; - int y, x, k; - unsigned short *sp, *dp, *ap; - - image->alpha = xps_alloc(ctx, image->width * image->height * 2); - - for (y = 0; y < image->height; y++) - { - sp = ((unsigned short*)image->samples) + (image->width * n * y); - dp = ((unsigned short*)image->samples) + (image->width * (n - 1) * y); - ap = ((unsigned short*)image->alpha) + (image->width * y); - for (x = 0; x < image->width; x++) - { - for (k = 0; k < n - 1; k++) - *dp++ = *sp++; - *ap++ = *sp++; - } - } - - image->hasalpha = 0; - image->comps --; - image->stride = image->width * image->comps * 2; -} - -static int -xps_image_has_alpha(xps_context_t *ctx, xps_part_t *part) -{ - byte *buf = part->data; - int len = part->size; - - if (len < 8) - { - gs_warn("unknown image file format"); - return 0; - } - - if (buf[0] == 0xff && buf[1] == 0xd8) - return 0; /* JPEG never has an alpha channel */ - else if (memcmp(buf, "\211PNG\r\n\032\n", 8) == 0) - return xps_png_has_alpha(ctx, buf, len); - else if (memcmp(buf, "II", 2) == 0 && buf[2] == 0xBC) - return xps_jpegxr_has_alpha(ctx, buf, len); - else if (memcmp(buf, "MM", 2) == 0) - return xps_tiff_has_alpha(ctx, buf, len); - else if (memcmp(buf, "II", 2) == 0) - return xps_tiff_has_alpha(ctx, buf, len); - - return 0; -} +#include "fitz.h" +#include "muxps.h" static int xps_decode_image(xps_context_t *ctx, xps_part_t *part, xps_image_t *image) { byte *buf = part->data; int len = part->size; - cmm_profile_t *profile; int error; if (len < 8) - return gs_throw(-1, "unknown image file format"); + return fz_throw("unknown image file format"); memset(image, 0, sizeof(xps_image_t)); - image->samples = NULL; - image->alpha = NULL; if (buf[0] == 0xff && buf[1] == 0xd8) { error = xps_decode_jpeg(ctx, buf, len, image); if (error) - return gs_rethrow(error, "could not decode jpeg image"); + return fz_rethrow(error, "could not decode image"); } else if (memcmp(buf, "\211PNG\r\n\032\n", 8) == 0) { error = xps_decode_png(ctx, buf, len, image); if (error) - return gs_rethrow(error, "could not decode png image"); + return fz_rethrow(error, "could not decode image"); } else if (memcmp(buf, "II", 2) == 0 && buf[2] == 0xBC) { error = xps_decode_jpegxr(ctx, buf, len, image); if (error) - return gs_rethrow(error, "could not decode jpeg-xr image"); + return fz_rethrow(error, "could not decode image"); } else if (memcmp(buf, "MM", 2) == 0 || memcmp(buf, "II", 2) == 0) { error = xps_decode_tiff(ctx, buf, len, image); if (error) - return gs_rethrow(error, "could not decode tiff image"); + return fz_rethrow(error, "could not decode image"); } else - return gs_throw(-1, "unknown image file format"); - - // TODO: refcount image->colorspace - - /* See if we need to use the embedded profile. */ - if (image->profile) - { - /* - See if we can set up to use the embedded profile. - Note these profiles are NOT added to the xps color cache. - As such, they must be destroyed when the image brush ends. - */ + return fz_throw("unknown image file format"); - /* Create the profile */ - profile = gsicc_profile_new(NULL, ctx->memory, NULL, 0); - - /* Set buffer */ - profile->buffer = image->profile; - profile->buffer_size = image->profilesize; - - /* Parse */ - gsicc_init_profile_info(profile); - - if (profile->profile_handle == NULL) - { - /* Problem with profile. Just ignore it */ - gs_warn("ignoring problem with icc profile embedded in an image"); - gsicc_profile_reference(profile, -1); - } - else - { - /* Check the profile is OK for channel data count. - * Need to be careful here since alpha is put into comps */ - if ((image->comps - image->hasalpha) == gsicc_getsrc_channel_count(profile)) - { - /* Create a new colorspace and associate with the profile */ - // TODO: refcount image->colorspace - gs_cspace_build_ICC(&image->colorspace, NULL, ctx->memory); - image->colorspace->cmm_icc_profile_data = profile; - } - else - { - /* Problem with profile. Just ignore it */ - gs_warn("ignoring icc profile embedded in an image with wrong number of components"); - gsicc_profile_reference(profile, -1); - } - } - } - - if (image->hasalpha) - { - if (image->bits < 8) - dprintf1("cannot isolate alpha channel in %d bpc images\n", image->bits); - if (image->bits == 8) - xps_isolate_alpha_channel_8(ctx, image); - if (image->bits == 16) - xps_isolate_alpha_channel_16(ctx, image); - } - - return gs_okay; + return fz_okay; } static int -xps_paint_image_brush_imp(xps_context_t *ctx, xps_image_t *image, int alpha) +xps_paint_image_brush_imp(xps_context_t *ctx, fz_matrix ctm, xps_image_t *image) { - gs_image_enum *penum; - gs_color_space *colorspace; - gs_image_t gsimage; - int code; - + fz_colorspace *colorspace; unsigned int count; - unsigned int used; byte *samples; - if (alpha) - { - colorspace = ctx->gray; - samples = image->alpha; - count = (image->width * image->bits + 7) / 8 * image->height; - used = 0; - } - else - { - colorspace = image->colorspace; - samples = image->samples; - count = image->stride * image->height; - used = 0; - } - - memset(&gsimage, 0, sizeof(gsimage)); - gs_image_t_init(&gsimage, colorspace); - gsimage.ColorSpace = colorspace; - gsimage.BitsPerComponent = image->bits; - gsimage.Width = image->width; - gsimage.Height = image->height; + colorspace = image->colorspace; + samples = image->samples; + count = image->stride * image->height; - gsimage.ImageMatrix.xx = image->xres / 96.0; - gsimage.ImageMatrix.yy = image->yres / 96.0; - - gsimage.Interpolate = 1; - - penum = gs_image_enum_alloc(ctx->memory, "xps_parse_image_brush (gs_image_enum_alloc)"); - if (!penum) - return gs_throw(-1, "gs_enum_allocate failed"); - - if ((code = gs_image_init(penum, &gsimage, false, ctx->pgs)) < 0) - return gs_throw(code, "gs_image_init failed"); - - if ((code = gs_image_next(penum, samples, count, &used)) < 0) - return gs_throw(code, "gs_image_next failed"); - - if (count < used) - return gs_throw2(-1, "not enough image data (image=%d used=%d)", count, used); - - if (count > used) - return gs_throw2(0, "too much image data (image=%d used=%d)", count, used); - - gs_image_cleanup_and_free_enum(penum, ctx->pgs); + // xxx return 0; } static int -xps_paint_image_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, xps_item_t *root, void *vimage) +xps_paint_image_brush(xps_context_t *ctx, fz_matrix ctm, char *base_uri, xps_resource_t *dict, xps_item_t *root, void *vimage) { +#if 0 xps_image_t *image = vimage; int code; @@ -278,7 +72,7 @@ xps_paint_image_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, { code = xps_paint_image_brush_imp(ctx, image, 1); if (code < 0) - return gs_rethrow(code, "cannot draw alpha channel image"); + return fz_rethrow(code, "cannot draw alpha channel image"); } return 0; } @@ -287,13 +81,13 @@ xps_paint_image_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, { gs_transparency_mask_params_t params; gs_transparency_group_params_t tgp; - gs_rect bbox; + fz_rect bbox; xps_bounds_in_user_space(ctx, &bbox); code = gs_gsave(ctx->pgs); if (code < 0) - return gs_rethrow(code, "cannot gsave before transparency group"); + return fz_rethrow(code, "cannot gsave before transparency group"); gs_setcolorspace(ctx->pgs, ctx->gray); gs_trans_mask_params_init(¶ms, TRANSPARENCY_MASK_Luminosity); @@ -303,7 +97,7 @@ xps_paint_image_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, { gs_end_transparency_mask(ctx->pgs, TRANSPARENCY_CHANNEL_Opacity); gs_grestore(ctx->pgs); - return gs_rethrow(code, "cannot draw alpha channel image"); + return fz_rethrow(code, "cannot draw alpha channel image"); } gs_end_transparency_mask(ctx->pgs, TRANSPARENCY_CHANNEL_Opacity); @@ -315,20 +109,21 @@ xps_paint_image_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, { gs_end_transparency_group(ctx->pgs); gs_grestore(ctx->pgs); - return gs_rethrow(code, "cannot draw color channel image"); + return fz_rethrow(code, "cannot draw color channel image"); } gs_end_transparency_group(ctx->pgs); code = gs_grestore(ctx->pgs); if (code < 0) - return gs_rethrow(code, "cannot grestore after transparency group"); + return fz_rethrow(code, "cannot grestore after transparency group"); } else { code = xps_paint_image_brush_imp(ctx, image, 0); if (code < 0) - return gs_rethrow(code, "cannot draw image"); + return fz_rethrow(code, "cannot draw image"); } +#endif return 0; } @@ -346,7 +141,7 @@ xps_find_image_brush_source_part(xps_context_t *ctx, char *base_uri, xps_item_t image_source_att = xps_att(root, "ImageSource"); if (!image_source_att) - return gs_throw(-1, "missing ImageSource attribute"); + return fz_throw("missing ImageSource attribute"); /* "{ColorConvertedBitmap /Resources/Image.tiff /Resources/Profile.icc}" */ if (strstr(image_source_att, "{ColorConvertedBitmap") == image_source_att) @@ -377,54 +172,59 @@ xps_find_image_brush_source_part(xps_context_t *ctx, char *base_uri, xps_item_t } if (!image_name) - return gs_throw1(-1, "cannot parse image resource name '%s'", image_source_att); + return fz_throw("cannot parse image resource name '%s'", image_source_att); xps_absolute_path(partname, base_uri, image_name, sizeof partname); part = xps_read_part(ctx, partname); if (!part) - return gs_throw1(-1, "cannot find image resource part '%s'", partname); + return fz_throw("cannot find image resource part '%s'", partname); *partp = part; - *profilep = xps_strdup(ctx, profile_name); + if (profile_name) + *profilep = xps_strdup(ctx, profile_name); return 0; } int -xps_parse_image_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, xps_item_t *root) +xps_parse_image_brush(xps_context_t *ctx, fz_matrix ctm, char *base_uri, xps_resource_t *dict, xps_item_t *root) { xps_part_t *part; xps_image_t *image; - gs_color_space *colorspace; + fz_colorspace *colorspace; char *profilename; int code; + profilename = NULL; + code = xps_find_image_brush_source_part(ctx, base_uri, root, &part, &profilename); if (code < 0) - return gs_rethrow(code, "cannot find image source"); + return fz_rethrow(code, "cannot find image source"); image = xps_alloc(ctx, sizeof(xps_image_t)); if (!image) - return gs_throw(-1, "out of memory: image struct"); + return fz_throw("out of memory: image struct"); + +return 0; code = xps_decode_image(ctx, part, image); if (code < 0) - return gs_rethrow1(code, "cannot decode image '%s'", part->name); + return fz_rethrow(-1, "cannot decode image resource"); /* Override any embedded colorspace profiles if the external one matches. */ if (profilename) { colorspace = xps_read_icc_colorspace(ctx, base_uri, profilename); - if (colorspace && cs_num_components(colorspace) == cs_num_components(image->colorspace)) + if (colorspace && colorspace->n == image->colorspace->n) { // TODO: refcount image->colorspace image->colorspace = colorspace; } } - code = xps_parse_tiling_brush(ctx, base_uri, dict, root, xps_paint_image_brush, image); + code = xps_parse_tiling_brush(ctx, ctm, base_uri, dict, root, xps_paint_image_brush, image); if (code < 0) - return gs_rethrow(-1, "cannot parse tiling brush"); + return fz_rethrow(-1, "cannot parse tiling brush"); if (profilename) xps_free(ctx, profilename); @@ -434,36 +234,12 @@ xps_parse_image_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, return 0; } -int -xps_image_brush_has_transparency(xps_context_t *ctx, char *base_uri, xps_item_t *root) -{ - xps_part_t *imagepart; - int code; - int has_alpha; - char *profilename; - - code = xps_find_image_brush_source_part(ctx, base_uri, root, &imagepart, &profilename); - if (code < 0) - { - gs_catch(code, "cannot find image source"); - return 0; - } - - has_alpha = xps_image_has_alpha(ctx, imagepart); - - xps_free_part(ctx, imagepart); - - return has_alpha; -} - void xps_free_image(xps_context_t *ctx, xps_image_t *image) { // TODO: refcount image->colorspace if (image->samples) xps_free(ctx, image->samples); - if (image->alpha) - xps_free(ctx, image->alpha); if (image->profile) xps_free(ctx, image->profile); xps_free(ctx, image); diff --git a/xps/xpsjpeg.c b/xps/xpsjpeg.c index 878fd85a..937ac4f0 100644 --- a/xps/xpsjpeg.c +++ b/xps/xpsjpeg.c @@ -1,143 +1,11 @@ -/* Copyright (C) 2006-2010 Artifex Software, Inc. - All Rights Reserved. +#include "fitz.h" +#include "muxps.h" - This software is provided AS-IS with no warranty, either express or - implied. - - This software is distributed under license and may not be copied, modified - or distributed except as expressly authorized under the terms of that - license. Refer to licensing information at http://www.artifex.com/ - or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, - San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information. -*/ - -/* XPS interpreter - JPEG image support */ - -#include "ghostxps.h" - -#include "stream.h" -#include "strimpl.h" -#include "gsstate.h" -#include "jpeglib_.h" -#include "sdct.h" -#include "sjpeg.h" - -static int -xps_report_error(stream_state * st, const char *str) -{ - (void) gs_throw1(-1, "%s", str); - return 0; -} +#include <jpeglib.h> +#include <setjmp.h> int xps_decode_jpeg(xps_context_t *ctx, byte *rbuf, int rlen, xps_image_t *image) { - jpeg_decompress_data jddp; - stream_DCT_state state; - stream_cursor_read rp; - stream_cursor_write wp; - int code; - int wlen; - byte *wbuf; - jpeg_saved_marker_ptr curr_marker; - - s_init_state((stream_state*)&state, &s_DCTD_template, ctx->memory); - state.report_error = xps_report_error; - - s_DCTD_template.set_defaults((stream_state*)&state); - - state.jpeg_memory = ctx->memory; - state.data.decompress = &jddp; - - jddp.template = s_DCTD_template; - jddp.memory = ctx->memory; - jddp.scanline_buffer = NULL; - - if ((code = gs_jpeg_create_decompress(&state)) < 0) - return gs_throw(-1, "cannot gs_jpeg_create_decompress"); - - s_DCTD_template.init((stream_state*)&state); - - rp.ptr = rbuf - 1; - rp.limit = rbuf + rlen - 1; - - /* read the header only by not having a write buffer */ - wp.ptr = 0; - wp.limit = 0; - - /* Set up to save the ICC marker APP2. - * According to the spec we should be getting APP1 APP2 and APP13. - * Library gets APP0 and APP14. */ - jpeg_save_markers(&(jddp.dinfo), 0xe2, 0xFFFF); - - code = s_DCTD_template.process((stream_state*)&state, &rp, &wp, true); - if (code != 1) - return gs_throw(-1, "premature EOF or error in jpeg"); - - /* Check if we had an ICC profile */ - curr_marker = jddp.dinfo.marker_list; - while (curr_marker != NULL) - { - if (curr_marker->marker == 0xe2) - { - /* Found ICC profile. Create a buffer and copy over now. - * Strip JPEG APP2 14 byte header */ - image->profilesize = curr_marker->data_length - 14; - image->profile = xps_alloc(ctx, image->profilesize); - if (image->profile) - { - /* If we can't create it, just ignore */ - memcpy(image->profile, &(curr_marker->data[14]), image->profilesize); - } - break; - } - curr_marker = curr_marker->next; - } - - image->width = jddp.dinfo.output_width; - image->height = jddp.dinfo.output_height; - image->comps = jddp.dinfo.output_components; - image->bits = 8; - image->stride = image->width * image->comps; - - if (image->comps == 1) - image->colorspace = ctx->gray; - if (image->comps == 3) - image->colorspace = ctx->srgb; - if (image->comps == 4) - image->colorspace = ctx->cmyk; - - if (jddp.dinfo.density_unit == 1) - { - image->xres = jddp.dinfo.X_density; - image->yres = jddp.dinfo.Y_density; - } - else if (jddp.dinfo.density_unit == 2) - { - image->xres = jddp.dinfo.X_density * 2.54; - image->yres = jddp.dinfo.Y_density * 2.54; - } - else - { - image->xres = 96; - image->yres = 96; - } - - wlen = image->stride * image->height; - wbuf = xps_alloc(ctx, wlen); - if (!wbuf) - return gs_throw1(-1, "out of memory allocating samples: %d", wlen); - - image->samples = wbuf; - - wp.ptr = wbuf - 1; - wp.limit = wbuf + wlen - 1; - - code = s_DCTD_template.process((stream_state*)&state, &rp, &wp, true); - if (code != EOFC) - return gs_throw1(-1, "error in jpeg (code = %d)", code); - - gs_jpeg_destroy(&state); - - return gs_okay; + return fz_throw("jpeg not available"); } diff --git a/xps/xpsjxr.c b/xps/xpsjxr.c index 1e9b0e73..f2f78ce0 100644 --- a/xps/xpsjxr.c +++ b/xps/xpsjxr.c @@ -1,19 +1,9 @@ -/* Copyright (C) 2006-2010 Artifex Software, Inc. - All Rights Reserved. - - This software is provided AS-IS with no warranty, either express or - implied. - - This software is distributed under license and may not be copied, modified - or distributed except as expressly authorized under the terms of that - license. Refer to licensing information at http://www.artifex.com/ - or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, - San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information. -*/ - /* JPEG-XR (formerly HD-Photo (formerly Windows Media Photo)) support */ -#include "ghostxps.h" +#include "fitz.h" +#include "muxps.h" + +#ifdef HAVE_JPEGXR #ifdef _MSC_VER #undef _MSC_VER @@ -257,3 +247,19 @@ xps_jpegxr_has_alpha(xps_context_t *ctx, byte *buf, int len) { return 1; } + +#else + +int +xps_decode_jpegxr(xps_context_t *ctx, byte *buf, int len, xps_image_t *image) +{ + return fz_throw("JPEG-XR codec is not available"); +} + +int +xps_jpegxr_has_alpha(xps_context_t *ctx, byte *buf, int len) +{ + return 0; +} + +#endif diff --git a/xps/xpsmem.c b/xps/xpsmem.c index 95199f07..3af3b3f6 100644 --- a/xps/xpsmem.c +++ b/xps/xpsmem.c @@ -1,27 +1,5 @@ -/* Copyright (C) 2006-2010 Artifex Software, Inc. - All Rights Reserved. - - This software is provided AS-IS with no warranty, either express or - implied. - - This software is distributed under license and may not be copied, modified - or distributed except as expressly authorized under the terms of that - license. Refer to licensing information at http://www.artifex.com/ - or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, - San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information. -*/ - -/* XPS interpreter - string manipulation functions */ - -#include "ghostxps.h" - -void * -xps_realloc_imp(xps_context_t *ctx, void *ptr, int size, const char *func) -{ - if (!ptr) - return gs_alloc_bytes(ctx->memory, size, func); - return gs_resize_object(ctx->memory, ptr, size, func); -} +#include "fitz.h" +#include "muxps.h" static inline int xps_tolower(int c) @@ -34,24 +12,13 @@ xps_tolower(int c) int xps_strcasecmp(char *a, char *b) { - while (xps_tolower(*a) == xps_tolower(*b)) - { - if (*a++ == 0) - return 0; - b++; - } - return xps_tolower(*a) - xps_tolower(*b); -} - -char * -xps_strdup_imp(xps_context_t *ctx, const char *str, const char *cname) -{ - char *cpy = NULL; - if (str) - cpy = (char*) gs_alloc_bytes(ctx->memory, strlen(str) + 1, cname); - if (cpy) - strcpy(cpy, str); - return cpy; + while (xps_tolower(*a) == xps_tolower(*b)) + { + if (*a++ == 0) + return 0; + b++; + } + return xps_tolower(*a) - xps_tolower(*b); } size_t diff --git a/xps/xpsopacity.c b/xps/xpsopacity.c index bd845efb..e4923f14 100644 --- a/xps/xpsopacity.c +++ b/xps/xpsopacity.c @@ -1,45 +1,31 @@ -/* Copyright (C) 2006-2010 Artifex Software, Inc. - All Rights Reserved. - - This software is provided AS-IS with no warranty, either express or - implied. - - This software is distributed under license and may not be copied, modified - or distributed except as expressly authorized under the terms of that - license. Refer to licensing information at http://www.artifex.com/ - or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, - San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information. -*/ - -/* XPS interpreter - transparency support */ - -#include "ghostxps.h" +#include "fitz.h" +#include "muxps.h" void -xps_bounds_in_user_space(xps_context_t *ctx, gs_rect *ubox) +xps_bounds_in_user_space(xps_context_t *ctx, fz_rect *ubox) { +#if 0 gx_clip_path *clip_path; - gs_rect dbox; + fz_rect dbox; int code; code = gx_effective_clip_path(ctx->pgs, &clip_path); if (code < 0) - gs_warn("gx_effective_clip_path failed"); + fz_warn("gx_effective_clip_path failed"); dbox.p.x = fixed2float(clip_path->outer_box.p.x); dbox.p.y = fixed2float(clip_path->outer_box.p.y); dbox.q.x = fixed2float(clip_path->outer_box.q.x); dbox.q.y = fixed2float(clip_path->outer_box.q.y); gs_bbox_transform_inverse(&dbox, &ctm_only(ctx->pgs), ubox); +#endif } int -xps_begin_opacity(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, +xps_begin_opacity(xps_context_t *ctx, fz_matrix ctm, char *base_uri, xps_resource_t *dict, char *opacity_att, xps_item_t *opacity_mask_tag) { - gs_transparency_group_params_t tgp; - gs_transparency_mask_params_t tmp; - gs_rect bbox; + fz_rect bbox; float opacity; int save; int code; @@ -50,44 +36,28 @@ xps_begin_opacity(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, opacity = 1.0; if (opacity_att) opacity = atof(opacity_att); - gs_setopacityalpha(ctx->pgs, opacity); +// gs_setopacityalpha(ctx->pgs, opacity); xps_bounds_in_user_space(ctx, &bbox); if (opacity_mask_tag) { - gs_trans_mask_params_init(&tmp, TRANSPARENCY_MASK_Luminosity); - gs_begin_transparency_mask(ctx->pgs, &tmp, &bbox, 0); - - gs_gsave(ctx->pgs); - - /* Need a path to fill/clip for the brush */ - gs_moveto(ctx->pgs, bbox.p.x, bbox.p.y); - gs_lineto(ctx->pgs, bbox.p.x, bbox.q.y); - gs_lineto(ctx->pgs, bbox.q.x, bbox.q.y); - gs_lineto(ctx->pgs, bbox.q.x, bbox.p.y); - gs_closepath(ctx->pgs); - /* opacity-only mode: use alpha value as gray color to create luminosity mask */ save = ctx->opacity_only; ctx->opacity_only = 1; - code = xps_parse_brush(ctx, base_uri, dict, opacity_mask_tag); + // begin mask + code = xps_parse_brush(ctx, ctm, base_uri, dict, opacity_mask_tag); if (code) { - gs_grestore(ctx->pgs); - gs_end_transparency_mask(ctx->pgs, TRANSPARENCY_CHANNEL_Opacity); ctx->opacity_only = save; - return gs_rethrow(code, "cannot parse opacity mask brush"); + return fz_rethrow(code, "cannot parse opacity mask brush"); } - gs_grestore(ctx->pgs); - gs_end_transparency_mask(ctx->pgs, TRANSPARENCY_CHANNEL_Opacity); ctx->opacity_only = save; } - gs_trans_group_params_init(&tgp); - gs_begin_transparency_group(ctx->pgs, &tgp, &bbox); + // begin group return 0; } @@ -98,5 +68,5 @@ xps_end_opacity(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, { if (!opacity_att && !opacity_mask_tag) return; - gs_end_transparency_group(ctx->pgs); + // end mask+group } diff --git a/xps/xpspage.c b/xps/xpspage.c index c6424d7c..858f327f 100644 --- a/xps/xpspage.c +++ b/xps/xpspage.c @@ -1,22 +1,8 @@ -/* Copyright (C) 2006-2010 Artifex Software, Inc. - All Rights Reserved. - - This software is provided AS-IS with no warranty, either express or - implied. - - This software is distributed under license and may not be copied, modified - or distributed except as expressly authorized under the terms of that - license. Refer to licensing information at http://www.artifex.com/ - or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, - San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information. -*/ - -/* XPS interpreter - page parsing */ - -#include "ghostxps.h" +#include "fitz.h" +#include "muxps.h" int -xps_parse_canvas(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, xps_item_t *root) +xps_parse_canvas(xps_context_t *ctx, fz_matrix ctm, char *base_uri, xps_resource_t *dict, xps_item_t *root) { xps_resource_t *new_dict = NULL; xps_item_t *node; @@ -32,7 +18,7 @@ xps_parse_canvas(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, xps_i xps_item_t *clip_tag = NULL; xps_item_t *opacity_mask_tag = NULL; - gs_matrix transform; + fz_matrix transform; transform_att = xps_att(root, "RenderTransform"); clip_att = xps_att(root, "Clip"); @@ -45,7 +31,7 @@ xps_parse_canvas(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, xps_i { code = xps_parse_resource_dictionary(ctx, &new_dict, base_uri, xps_down(node)); if (code) - return gs_rethrow(code, "cannot load Canvas.Resources"); + return fz_rethrow(code, "cannot load Canvas.Resources"); new_dict->parent = dict; dict = new_dict; } @@ -63,45 +49,46 @@ xps_parse_canvas(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, xps_i xps_resolve_resource_reference(ctx, dict, &clip_att, &clip_tag, NULL); xps_resolve_resource_reference(ctx, dict, &opacity_mask_att, &opacity_mask_tag, &opacity_mask_uri); - gs_gsave(ctx->pgs); +// gs_gsave(ctx->pgs); - gs_make_identity(&transform); + transform = fz_identity; if (transform_att) xps_parse_render_transform(ctx, transform_att, &transform); if (transform_tag) xps_parse_matrix_transform(ctx, transform_tag, &transform); - gs_concat(ctx->pgs, &transform); + ctm = fz_concat(ctm, transform); if (clip_att || clip_tag) { + ctx->path = fz_newpath(); if (clip_att) xps_parse_abbreviated_geometry(ctx, clip_att); if (clip_tag) xps_parse_path_geometry(ctx, dict, clip_tag, 0); - xps_clip(ctx); + xps_clip(ctx, ctm); } - code = xps_begin_opacity(ctx, opacity_mask_uri, dict, opacity_att, opacity_mask_tag); + code = xps_begin_opacity(ctx, ctm, opacity_mask_uri, dict, opacity_att, opacity_mask_tag); if (code) { - gs_grestore(ctx->pgs); - return gs_rethrow(code, "cannot create transparency group"); +// gs_grestore(ctx->pgs); + return fz_rethrow(code, "cannot create transparency group"); } for (node = xps_down(root); node; node = xps_next(node)) { - code = xps_parse_element(ctx, base_uri, dict, node); + code = xps_parse_element(ctx, ctm, base_uri, dict, node); if (code) { xps_end_opacity(ctx, opacity_mask_uri, dict, opacity_att, opacity_mask_tag); - gs_grestore(ctx->pgs); - return gs_rethrow(code, "cannot parse child of Canvas"); +// gs_grestore(ctx->pgs); + return fz_rethrow(code, "cannot parse child of Canvas"); } } xps_end_opacity(ctx, opacity_mask_uri, dict, opacity_att, opacity_mask_tag); - gs_grestore(ctx->pgs); +// gs_grestore(ctx->pgs); if (new_dict) xps_free_resource_dictionary(ctx, new_dict); @@ -110,172 +97,74 @@ xps_parse_canvas(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, xps_i } int -xps_parse_fixed_page(xps_context_t *ctx, xps_part_t *part) +xps_parse_fixed_page(xps_context_t *ctx, fz_matrix ctm, xps_page_t *page) { - xps_item_t *root, *node; + xps_item_t *node; xps_resource_t *dict; - char *width_att; - char *height_att; - int has_transparency; char base_uri[1024]; char *s; int code; - if_debug1('|', "doc: parsing page %s\n", part->name); - - xps_strlcpy(base_uri, part->name, sizeof base_uri); + xps_strlcpy(base_uri, page->name, sizeof base_uri); s = strrchr(base_uri, '/'); if (s) s[1] = 0; - root = xps_parse_xml(ctx, part->data, part->size); - if (!root) - return gs_rethrow(-1, "cannot parse xml"); - - if (strcmp(xps_tag(root), "FixedPage")) - return gs_throw1(-1, "expected FixedPage element (found %s)", xps_tag(root)); - - width_att = xps_att(root, "Width"); - height_att = xps_att(root, "Height"); - - if (!width_att) - return gs_throw(-1, "FixedPage missing required attribute: Width"); - if (!height_att) - return gs_throw(-1, "FixedPage missing required attribute: Height"); - dict = NULL; - /* Setup new page */ + for (node = xps_down(page->root); node; node = xps_next(node)) { - gs_memory_t *mem = ctx->memory; - gs_state *pgs = ctx->pgs; - gx_device *dev = gs_currentdevice(pgs); - gs_param_float_array fa; - float fv[2]; - gs_c_param_list list; - - gs_c_param_list_write(&list, mem); - - fv[0] = atoi(width_att) / 96.0 * 72.0; - fv[1] = atoi(height_att) / 96.0 * 72.0; - fa.persistent = false; - fa.data = fv; - fa.size = 2; - - code = param_write_float_array((gs_param_list *)&list, ".MediaSize", &fa); - if ( code >= 0 ) + if (!strcmp(xps_tag(node), "FixedPage.Resources") && xps_down(node)) { - gs_c_param_list_read(&list); - code = gs_putdeviceparams(dev, (gs_param_list *)&list); + code = xps_parse_resource_dictionary(ctx, &dict, base_uri, xps_down(node)); + if (code) + return fz_rethrow(code, "cannot load FixedPage.Resources"); } - gs_c_param_list_release(&list); - - /* nb this is for the demo it is wrong and should be removed */ - gs_initgraphics(pgs); - - /* 96 dpi default - and put the origin at the top of the page */ - - gs_initmatrix(pgs); - - code = gs_scale(pgs, 72.0/96.0, -72.0/96.0); - if (code < 0) - return gs_rethrow(code, "cannot set page transform"); - - code = gs_translate(pgs, 0.0, -atoi(height_att)); - if (code < 0) - return gs_rethrow(code, "cannot set page transform"); - - code = gs_erasepage(pgs); - if (code < 0) - return gs_rethrow(code, "cannot clear page"); + code = xps_parse_element(ctx, ctm, base_uri, dict, node); + if (code) + return fz_rethrow(code, "cannot parse child of FixedPage"); } - /* Pre-parse looking for transparency */ - - has_transparency = 0; - - for (node = xps_down(root); node; node = xps_next(node)) + if (dict) { - if (!strcmp(xps_tag(node), "FixedPage.Resources") && xps_down(node)) - if (xps_resource_dictionary_has_transparency(ctx, base_uri, xps_down(node))) - has_transparency = 1; - if (xps_element_has_transparency(ctx, base_uri, node)) - has_transparency = 1; + xps_free_resource_dictionary(ctx, dict); } - /* save the state with the original device before we push */ - gs_gsave(ctx->pgs); - - if (ctx->use_transparency && has_transparency) - { - code = gs_push_pdf14trans_device(ctx->pgs); - if (code < 0) - { - gs_grestore(ctx->pgs); - return gs_rethrow(code, "cannot install transparency device"); - } - } + return fz_okay; +} - /* Initialize the default profiles in the ctx to what is in the manager */ - ctx->gray->cmm_icc_profile_data = ctx->pgs->icc_manager->default_gray; - ctx->srgb->cmm_icc_profile_data = ctx->pgs->icc_manager->default_rgb; - /* scrgb really needs to be a bit different. - * Unless we are handling nonlinearity before conversion from float. ToDo. */ - ctx->scrgb->cmm_icc_profile_data = ctx->pgs->icc_manager->default_rgb; - ctx->cmyk->cmm_icc_profile_data = ctx->pgs->icc_manager->default_cmyk; +int +xps_load_fixed_page(xps_context_t *ctx, xps_page_t *page) +{ + xps_part_t *part; + xps_item_t *root; + char *width_att; + char *height_att; - /* Draw contents */ + part = xps_read_part(ctx, page->name); + if (!part) + return fz_rethrow(-1, "cannot read zip part '%s'", page->name); - for (node = xps_down(root); node; node = xps_next(node)) - { - if (!strcmp(xps_tag(node), "FixedPage.Resources") && xps_down(node)) - { - code = xps_parse_resource_dictionary(ctx, &dict, base_uri, xps_down(node)); - if (code) - { - gs_pop_pdf14trans_device(ctx->pgs); - gs_grestore(ctx->pgs); - return gs_rethrow(code, "cannot load FixedPage.Resources"); - } - } - code = xps_parse_element(ctx, base_uri, dict, node); - if (code) - { - gs_pop_pdf14trans_device(ctx->pgs); - gs_grestore(ctx->pgs); - return gs_rethrow(code, "cannot parse child of FixedPage"); - } - } + root = xps_parse_xml(ctx, part->data, part->size); + if (!root) + return fz_rethrow(-1, "cannot parse xml"); - if (ctx->use_transparency && has_transparency) - { - code = gs_pop_pdf14trans_device(ctx->pgs); - if (code < 0) - { - gs_grestore(ctx->pgs); - return gs_rethrow(code, "cannot uninstall transparency device"); - } - } + xps_free_part(ctx, part); - /* Flush page */ - { - code = xps_show_page(ctx, 1, true); /* copies, flush */ - if (code < 0) - { - gs_grestore(ctx->pgs); - return gs_rethrow(code, "cannot flush page"); - } - } + if (strcmp(xps_tag(root), "FixedPage")) + return fz_throw("expected FixedPage element (found %s)", xps_tag(root)); - /* restore the original device, discarding the pdf14 compositor */ - gs_grestore(ctx->pgs); + width_att = xps_att(root, "Width"); + if (!width_att) + return fz_throw("FixedPage missing required attribute: Width"); - if (dict) - { - xps_free_resource_dictionary(ctx, dict); - } + height_att = xps_att(root, "Height"); + if (!height_att) + return fz_throw("FixedPage missing required attribute: Height"); - xps_free_item(ctx, root); + page->width = atoi(width_att); + page->height = atoi(height_att); + page->root = root; return 0; } diff --git a/xps/xpspath.c b/xps/xpspath.c index 89e9716a..12377501 100644 --- a/xps/xpspath.c +++ b/xps/xpspath.c @@ -1,58 +1,88 @@ -/* Copyright (C) 2006-2010 Artifex Software, Inc. - All Rights Reserved. +#include "fitz.h" +#include "muxps.h" - This software is provided AS-IS with no warranty, either express or - implied. +static fz_point +fz_currentpoint(fz_path *path) +{ + fz_point c, m; + int i; - This software is distributed under license and may not be copied, modified - or distributed except as expressly authorized under the terms of that - license. Refer to licensing information at http://www.artifex.com/ - or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, - San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information. -*/ + c.x = c.y = m.x = m.y = 0; + i = 0; -/* XPS interpreter - path (vector drawing) support */ + while (i < path->len) + { + switch (path->els[i++].k) + { + case FZ_MOVETO: + m.x = c.x = path->els[i++].v; + m.y = c.y = path->els[i++].v; + break; + case FZ_LINETO: + c.x = path->els[i++].v; + c.y = path->els[i++].v; + break; + case FZ_CURVETO: + i += 4; + c.x = path->els[i++].v; + c.y = path->els[i++].v; + break; + case FZ_CLOSEPATH: + c = m; + } + } -#include "ghostxps.h" + return c; +} void -xps_clip(xps_context_t *ctx) +xps_clip(xps_context_t *ctx, fz_matrix ctm) { - if (ctx->fill_rule == 0) - gs_eoclip(ctx->pgs); - else - gs_clip(ctx->pgs); - gs_newpath(ctx->pgs); +printf("xps_clip\n"); + assert(ctx->path); +// ctx->dev->clippath(ctx->dev, ctx->path, ctx->fill_rule == 0, ctm); + fz_freepath(ctx->path); + ctx->path = NULL; } void -xps_fill(xps_context_t *ctx) +xps_fill(xps_context_t *ctx, fz_matrix ctm) { - if (gs_currentopacityalpha(ctx->pgs) < 0.001) - gs_newpath(ctx->pgs); - else if (ctx->fill_rule == 0) { - if (gs_eofill(ctx->pgs) == gs_error_Remap_Color) - xps_high_level_pattern(ctx); - gs_eofill(ctx->pgs); - } - else { - if (gs_fill(ctx->pgs) == gs_error_Remap_Color) - xps_high_level_pattern(ctx); - gs_fill(ctx->pgs); - } +printf("xps_fill!\n"); + ctx->dev->fillpath(ctx->dev, ctx->path, ctx->fill_rule == 0, ctm, + ctx->colorspace, ctx->color, ctx->alpha); + fz_freepath(ctx->path); + ctx->path = NULL; +} + +static void +xps_stroke(xps_context_t *ctx, fz_matrix ctm, fz_strokestate *stroke) +{ + ctx->dev->strokepath(ctx->dev, ctx->path, stroke, ctm, + ctx->colorspace, ctx->color, ctx->alpha); + fz_freepath(ctx->path); + ctx->path = NULL; +} + +static void +xps_clipstroke(xps_context_t *ctx, fz_matrix ctm, fz_strokestate *stroke) +{ + ctx->dev->clipstrokepath(ctx->dev, ctx->path, stroke, ctm); + fz_freepath(ctx->path); + ctx->path = NULL; } /* Draw an arc segment transformed by the matrix, we approximate with straight - * line segments. We cannot use the gs_arc function because they only draw + * line segments. We cannot use the fz_arc function because they only draw * circular arcs, we need to transform the line to make them elliptical but * without transforming the line width. */ static inline void -xps_draw_arc_segment(xps_context_t *ctx, gs_matrix *mtx, float th0, float th1, int iscw) +xps_draw_arc_segment(xps_context_t *ctx, fz_matrix mtx, float th0, float th1, int iscw) { float t, d; - gs_point p; - + fz_point p; +return; // XXX broken while (th1 < th0) th1 += M_PI * 2.0; @@ -60,34 +90,46 @@ xps_draw_arc_segment(xps_context_t *ctx, gs_matrix *mtx, float th0, float th1, i if (iscw) { - gs_point_transform(cos(th0), sin(th0), mtx, &p); - gs_lineto(ctx->pgs, p.x, p.y); + p.x = cos(th0); + p.y = sin(th0); + p = fz_transformpoint(mtx, p); + fz_lineto(ctx->path, p.x, p.y); for (t = th0; t < th1; t += d) { - gs_point_transform(cos(t), sin(t), mtx, &p); - gs_lineto(ctx->pgs, p.x, p.y); + p.x = cos(t); + p.y = sin(t); + p = fz_transformpoint(mtx, p); + fz_lineto(ctx->path, p.x, p.y); } - gs_point_transform(cos(th1), sin(th1), mtx, &p); - gs_lineto(ctx->pgs, p.x, p.y); + p.x = cos(th1); + p.y = sin(th1); + p = fz_transformpoint(mtx, p); + fz_lineto(ctx->path, p.x, p.y); } else { th0 += M_PI * 2; - gs_point_transform(cos(th0), sin(th0), mtx, &p); - gs_lineto(ctx->pgs, p.x, p.y); + p.x = cos(th0); + p.y = sin(th0); + p = fz_transformpoint(mtx, p); + fz_lineto(ctx->path, p.x, p.y); for (t = th0; t > th1; t -= d) { - gs_point_transform(cos(t), sin(t), mtx, &p); - gs_lineto(ctx->pgs, p.x, p.y); + p.x = cos(t); + p.y = sin(t); + p = fz_transformpoint(mtx, p); + fz_lineto(ctx->path, p.x, p.y); } - gs_point_transform(cos(th1), sin(th1), mtx, &p); - gs_lineto(ctx->pgs, p.x, p.y); + p.x = cos(th1); + p.y = sin(th1); + p = fz_transformpoint(mtx, p); + fz_lineto(ctx->path, p.x, p.y); } } /* Given two vectors find the angle between them. */ static inline double -angle_between(const gs_point u, const gs_point v) +angle_between(const fz_point u, const fz_point v) { double det = u.x * v.y - u.y * v.x; double sign = (det < 0 ? -1.0 : 1.0); @@ -107,9 +149,9 @@ xps_draw_arc(xps_context_t *ctx, int is_large_arc, int is_clockwise, float point_x, float point_y) { - gs_matrix rotmat, revmat; - gs_matrix mtx; - gs_point pt; + fz_matrix rotmat, revmat; + fz_matrix mtx; + fz_point pt; double rx, ry; double x1, y1, x2, y2; double x1t, y1t; @@ -118,7 +160,7 @@ xps_draw_arc(xps_context_t *ctx, double sign; double th1, dth; - gs_currentpoint(ctx->pgs, &pt); + pt = fz_currentpoint(ctx->path); x1 = pt.x; y1 = pt.y; x2 = point_x; @@ -131,8 +173,8 @@ xps_draw_arc(xps_context_t *ctx, else sign = -1; - gs_make_rotation(rotation_angle, &rotmat); - gs_make_rotation(-rotation_angle, &revmat); + rotmat = fz_rotate(rotation_angle); + revmat = fz_rotate(-rotation_angle); /* http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes */ /* Conversion from endpoint to center parameterization */ @@ -142,12 +184,14 @@ xps_draw_arc(xps_context_t *ctx, ry = fabsf(ry); if (rx < 0.001 || ry < 0.001) { - gs_lineto(ctx->pgs, x2, y2); + fz_lineto(ctx->path, x2, y2); return; } /* F.6.5.1 */ - gs_distance_transform((x1 - x2) / 2.0, (y1 - y2) / 2.0, &revmat, &pt); + pt.x = (x1 - x2) / 2; + pt.y = (y1 - y2) / 2; + pt = fz_transformvector(revmat, pt); x1t = pt.x; y1t = pt.y; @@ -171,13 +215,15 @@ xps_draw_arc(xps_context_t *ctx, cyt = sign * t3 * -(ry * x1t) / rx; /* F.6.5.3 */ - gs_distance_transform(cxt, cyt, &rotmat, &pt); + pt.x = cxt; + pt.y = cyt; + pt = fz_transformvector(rotmat, pt); cx = pt.x + (x1 + x2) / 2; cy = pt.y + (y1 + y2) / 2; /* F.6.5.4 */ { - gs_point coord1, coord2, coord3, coord4; + fz_point coord1, coord2, coord3, coord4; coord1.x = 1; coord1.y = 0; coord2.x = (x1t - cxt) / rx; @@ -189,18 +235,18 @@ xps_draw_arc(xps_context_t *ctx, th1 = angle_between(coord1, coord2); dth = angle_between(coord3, coord4); if (dth < 0 && !is_clockwise) - dth += (degrees_to_radians * 360); + dth += ((M_PI / 180.0) * 360); if (dth > 0 && is_clockwise) - dth -= (degrees_to_radians * 360); + dth -= ((M_PI / 180.0) * 360); } - gs_make_identity(&mtx); - gs_matrix_translate(&mtx, cx, cy, &mtx); - gs_matrix_rotate(&mtx, rotation_angle, &mtx); - gs_matrix_scale(&mtx, rx, ry, &mtx); - xps_draw_arc_segment(ctx, &mtx, th1, th1 + dth, is_clockwise); + mtx = fz_identity; + mtx = fz_concat(mtx, fz_translate(cx, cy)); + mtx = fz_concat(mtx, fz_rotate(rotation_angle)); + mtx = fz_concat(mtx, fz_scale(rx, ry)); + xps_draw_arc_segment(ctx, mtx, th1, th1 + dth, is_clockwise); - gs_lineto(ctx->pgs, point_x, point_y); + fz_lineto(ctx->path, point_x, point_y); } /* @@ -215,18 +261,17 @@ xps_parse_abbreviated_geometry(xps_context_t *ctx, char *geom) char **args; char **pargs; char *s = geom; - gs_point pt; + fz_point pt; int i, n; int cmd, old; float x1, y1, x2, y2, x3, y3; float smooth_x, smooth_y; /* saved cubic bezier control point for smooth curves */ int reset_smooth; - args = xps_alloc(ctx, sizeof(char*) * (strlen(geom) + 1)); - pargs = args; +printf("xps_parse_abbreviated_geometry: %s\n", geom); - //dprintf1("new path (%.70s)\n", geom); - gs_newpath(ctx->pgs); + args = fz_calloc(strlen(geom) + 1, sizeof(char*)); + pargs = args; while (*s) { @@ -282,48 +327,44 @@ xps_parse_abbreviated_geometry(xps_context_t *ctx, char *geom) break; case 'M': - gs_moveto(ctx->pgs, atof(args[i]), atof(args[i+1])); - //dprintf2("moveto %g %g\n", atof(args[i]), atof(args[i+1])); + fz_moveto(ctx->path, atof(args[i]), atof(args[i+1])); i += 2; break; case 'm': - gs_rmoveto(ctx->pgs, atof(args[i]), atof(args[i+1])); - //dprintf2("rmoveto %g %g\n", atof(args[i]), atof(args[i+1])); + pt = fz_currentpoint(ctx->path); + fz_moveto(ctx->path, pt.x + atof(args[i]), pt.y + atof(args[i+1])); i += 2; break; case 'L': - gs_lineto(ctx->pgs, atof(args[i]), atof(args[i+1])); - //dprintf2("lineto %g %g\n", atof(args[i]), atof(args[i+1])); + fz_lineto(ctx->path, atof(args[i]), atof(args[i+1])); i += 2; break; case 'l': - gs_rlineto(ctx->pgs, atof(args[i]), atof(args[i+1])); - //dprintf2("rlineto %g %g\n", atof(args[i]), atof(args[i+1])); + pt = fz_currentpoint(ctx->path); + fz_lineto(ctx->path, pt.x + atof(args[i]), pt.y + atof(args[i+1])); i += 2; break; case 'H': - gs_currentpoint(ctx->pgs, &pt); - gs_lineto(ctx->pgs, atof(args[i]), pt.y); - //dprintf1("hlineto %g\n", atof(args[i])); + pt = fz_currentpoint(ctx->path); + fz_lineto(ctx->path, atof(args[i]), pt.y); i += 1; break; case 'h': - gs_rlineto(ctx->pgs, atof(args[i]), 0.0); - //dprintf1("rhlineto %g\n", atof(args[i])); + pt = fz_currentpoint(ctx->path); + fz_lineto(ctx->path, pt.x + atof(args[i]), pt.y); i += 1; break; case 'V': - gs_currentpoint(ctx->pgs, &pt); - gs_lineto(ctx->pgs, pt.x, atof(args[i])); - //dprintf1("vlineto %g\n", atof(args[i])); + pt = fz_currentpoint(ctx->path); + fz_lineto(ctx->path, pt.x, atof(args[i])); i += 1; break; case 'v': - gs_rlineto(ctx->pgs, 0.0, atof(args[i])); - //dprintf1("rvlineto %g\n", atof(args[i])); + pt = fz_currentpoint(ctx->path); + fz_lineto(ctx->path, pt.x, pt.y + atof(args[i])); i += 1; break; @@ -334,7 +375,7 @@ xps_parse_abbreviated_geometry(xps_context_t *ctx, char *geom) y2 = atof(args[i+3]); x3 = atof(args[i+4]); y3 = atof(args[i+5]); - gs_curveto(ctx->pgs, x1, y1, x2, y2, x3, y3); + fz_curveto(ctx->path, x1, y1, x2, y2, x3, y3); i += 6; reset_smooth = 0; smooth_x = x3 - x2; @@ -342,14 +383,14 @@ xps_parse_abbreviated_geometry(xps_context_t *ctx, char *geom) break; case 'c': - gs_currentpoint(ctx->pgs, &pt); + pt = fz_currentpoint(ctx->path); x1 = atof(args[i+0]) + pt.x; y1 = atof(args[i+1]) + pt.y; x2 = atof(args[i+2]) + pt.x; y2 = atof(args[i+3]) + pt.y; x3 = atof(args[i+4]) + pt.x; y3 = atof(args[i+5]) + pt.y; - gs_curveto(ctx->pgs, x1, y1, x2, y2, x3, y3); + fz_curveto(ctx->path, x1, y1, x2, y2, x3, y3); i += 6; reset_smooth = 0; smooth_x = x3 - x2; @@ -357,13 +398,12 @@ xps_parse_abbreviated_geometry(xps_context_t *ctx, char *geom) break; case 'S': - gs_currentpoint(ctx->pgs, &pt); + pt = fz_currentpoint(ctx->path); x1 = atof(args[i+0]); y1 = atof(args[i+1]); x2 = atof(args[i+2]); y2 = atof(args[i+3]); - //dprintf2("smooth %g %g\n", smooth_x, smooth_y); - gs_curveto(ctx->pgs, pt.x + smooth_x, pt.y + smooth_y, x1, y1, x2, y2); + fz_curveto(ctx->path, pt.x + smooth_x, pt.y + smooth_y, x1, y1, x2, y2); i += 4; reset_smooth = 0; smooth_x = x2 - x1; @@ -371,13 +411,12 @@ xps_parse_abbreviated_geometry(xps_context_t *ctx, char *geom) break; case 's': - gs_currentpoint(ctx->pgs, &pt); + pt = fz_currentpoint(ctx->path); x1 = atof(args[i+0]) + pt.x; y1 = atof(args[i+1]) + pt.y; x2 = atof(args[i+2]) + pt.x; y2 = atof(args[i+3]) + pt.y; - //dprintf2("smooth %g %g\n", smooth_x, smooth_y); - gs_curveto(ctx->pgs, pt.x + smooth_x, pt.y + smooth_y, x1, y1, x2, y2); + fz_curveto(ctx->path, pt.x + smooth_x, pt.y + smooth_y, x1, y1, x2, y2); i += 4; reset_smooth = 0; smooth_x = x2 - x1; @@ -385,26 +424,24 @@ xps_parse_abbreviated_geometry(xps_context_t *ctx, char *geom) break; case 'Q': - gs_currentpoint(ctx->pgs, &pt); + pt = fz_currentpoint(ctx->path); x1 = atof(args[i+0]); y1 = atof(args[i+1]); x2 = atof(args[i+2]); y2 = atof(args[i+3]); - //dprintf4("conicto %g %g %g %g\n", x1, y1, x2, y2); - gs_curveto(ctx->pgs, + fz_curveto(ctx->path, (pt.x + 2 * x1) / 3, (pt.y + 2 * y1) / 3, (x2 + 2 * x1) / 3, (y2 + 2 * y1) / 3, x2, y2); i += 4; break; case 'q': - gs_currentpoint(ctx->pgs, &pt); + pt = fz_currentpoint(ctx->path); x1 = atof(args[i+0]) + pt.x; y1 = atof(args[i+1]) + pt.y; x2 = atof(args[i+2]) + pt.x; y2 = atof(args[i+3]) + pt.y; - //dprintf4("conicto %g %g %g %g\n", x1, y1, x2, y2); - gs_curveto(ctx->pgs, + fz_curveto(ctx->path, (pt.x + 2 * x1) / 3, (pt.y + 2 * y1) / 3, (x2 + 2 * x1) / 3, (y2 + 2 * y1) / 3, x2, y2); @@ -419,7 +456,7 @@ xps_parse_abbreviated_geometry(xps_context_t *ctx, char *geom) i += 7; break; case 'a': - gs_currentpoint(ctx->pgs, &pt); + pt = fz_currentpoint(ctx->path); xps_draw_arc(ctx, atof(args[i+0]), atof(args[i+1]), atof(args[i+2]), atoi(args[i+3]), atoi(args[i+4]), @@ -429,8 +466,7 @@ xps_parse_abbreviated_geometry(xps_context_t *ctx, char *geom) case 'Z': case 'z': - gs_closepath(ctx->pgs); - //dputs("closepath\n"); + fz_closepath(ctx->path); break; default: @@ -467,7 +503,7 @@ xps_parse_arc_segment(xps_context_t *ctx, xps_item_t *root, int stroking, int *s if (!point_att || !size_att || !rotation_angle_att || !is_large_arc_att || !sweep_direction_att) { - gs_warn("ArcSegment element is missing attributes"); + fz_warn("ArcSegment element is missing attributes"); return; } @@ -485,7 +521,7 @@ xps_parse_arc_segment(xps_context_t *ctx, xps_item_t *root, int stroking, int *s if (stroking && !is_stroked) { - gs_moveto(ctx->pgs, point_x, point_y); + fz_moveto(ctx->path, point_x, point_y); return; } @@ -499,13 +535,13 @@ xps_parse_poly_quadratic_bezier_segment(xps_context_t *ctx, xps_item_t *root, in char *is_stroked_att = xps_att(root, "IsStroked"); float x[2], y[2]; int is_stroked; - gs_point pt; + fz_point pt; char *s; int n; if (!points_att) { - gs_warn("PolyQuadraticBezierSegment element has no points"); + fz_warn("PolyQuadraticBezierSegment element has no points"); return; } @@ -527,12 +563,12 @@ xps_parse_poly_quadratic_bezier_segment(xps_context_t *ctx, xps_item_t *root, in { if (stroking && !is_stroked) { - gs_moveto(ctx->pgs, x[1], y[1]); + fz_moveto(ctx->path, x[1], y[1]); } else { - gs_currentpoint(ctx->pgs, &pt); - gs_curveto(ctx->pgs, + pt = fz_currentpoint(ctx->path); + fz_curveto(ctx->path, (pt.x + 2 * x[0]) / 3, (pt.y + 2 * y[0]) / 3, (x[1] + 2 * x[0]) / 3, (y[1] + 2 * y[0]) / 3, x[1], y[1]); @@ -554,7 +590,7 @@ xps_parse_poly_bezier_segment(xps_context_t *ctx, xps_item_t *root, int stroking if (!points_att) { - gs_warn("PolyBezierSegment element has no points"); + fz_warn("PolyBezierSegment element has no points"); return; } @@ -575,9 +611,9 @@ xps_parse_poly_bezier_segment(xps_context_t *ctx, xps_item_t *root, int stroking if (n == 3) { if (stroking && !is_stroked) - gs_moveto(ctx->pgs, x[2], y[2]); + fz_moveto(ctx->path, x[2], y[2]); else - gs_curveto(ctx->pgs, x[0], y[0], x[1], y[1], x[2], y[2]); + fz_curveto(ctx->path, x[0], y[0], x[1], y[1], x[2], y[2]); n = 0; } } @@ -594,7 +630,7 @@ xps_parse_poly_line_segment(xps_context_t *ctx, xps_item_t *root, int stroking, if (!points_att) { - gs_warn("PolyLineSegment element has no points"); + fz_warn("PolyLineSegment element has no points"); return; } @@ -610,9 +646,9 @@ xps_parse_poly_line_segment(xps_context_t *ctx, xps_item_t *root, int stroking, while (*s == ' ') s++; sscanf(s, "%g,%g", &x, &y); if (stroking && !is_stroked) - gs_moveto(ctx->pgs, x, y); + fz_moveto(ctx->path, x, y); else - gs_lineto(ctx->pgs, x, y); + fz_lineto(ctx->path, x, y); while (*s != ' ' && *s != 0) s++; } } @@ -647,7 +683,7 @@ xps_parse_path_figure(xps_context_t *ctx, xps_item_t *root, int stroking) if (!stroking && !is_filled) /* not filled, when filling */ return; - gs_moveto(ctx->pgs, start_x, start_y); + fz_moveto(ctx->path, start_x, start_y); for (node = xps_down(root); node; node = xps_next(node)) { @@ -664,9 +700,9 @@ xps_parse_path_figure(xps_context_t *ctx, xps_item_t *root, int stroking) if (is_closed) { if (stroking && skipped_stroke) - gs_lineto(ctx->pgs, start_x, start_y); /* we've skipped using gs_moveto... */ + fz_lineto(ctx->path, start_x, start_y); /* we've skipped using fz_moveto... */ else - gs_closepath(ctx->pgs); /* no skipped segments, safe to closepath properly */ + fz_closepath(ctx->path); /* no skipped segments, safe to closepath properly */ } } @@ -682,10 +718,7 @@ xps_parse_path_geometry(xps_context_t *ctx, xps_resource_t *dict, xps_item_t *ro xps_item_t *transform_tag = NULL; xps_item_t *figures_tag = NULL; /* only used by resource */ - gs_matrix transform; - gs_matrix saved_transform; - - gs_newpath(ctx->pgs); + fz_matrix transform; figures_att = xps_att(root, "Figures"); fill_rule_att = xps_att(root, "FillRule"); @@ -708,17 +741,12 @@ xps_parse_path_geometry(xps_context_t *ctx, xps_resource_t *dict, xps_item_t *ro ctx->fill_rule = 0; } - gs_make_identity(&transform); - if (transform_att || transform_tag) - { - if (transform_att) - xps_parse_render_transform(ctx, transform_att, &transform); - if (transform_tag) - xps_parse_matrix_transform(ctx, transform_tag, &transform); - } - - gs_currentmatrix(ctx->pgs, &saved_transform); - gs_concat(ctx->pgs, &transform); + transform = fz_identity; + if (transform_att) + xps_parse_render_transform(ctx, transform_att, &transform); + if (transform_tag) + xps_parse_matrix_transform(ctx, transform_tag, &transform); + // TODO: apply matrix if (figures_att) { @@ -735,8 +763,6 @@ xps_parse_path_geometry(xps_context_t *ctx, xps_resource_t *dict, xps_item_t *ro if (!strcmp(xps_tag(node), "PathFigure")) xps_parse_path_figure(ctx, node, stroking); } - - gs_setmatrix(ctx->pgs, &saved_transform); } static int @@ -744,12 +770,12 @@ xps_parse_line_cap(char *attr) { if (attr) { - if (!strcmp(attr, "Flat")) return gs_cap_butt; - if (!strcmp(attr, "Square")) return gs_cap_square; - if (!strcmp(attr, "Round")) return gs_cap_round; - if (!strcmp(attr, "Triangle")) return gs_cap_triangle; + if (!strcmp(attr, "Flat")) return 0; + if (!strcmp(attr, "Round")) return 1; + if (!strcmp(attr, "Square")) return 2; + if (!strcmp(attr, "Triangle")) return 3; /* FIXME add triangle caps */ } - return gs_cap_butt; + return 0; } /* @@ -758,7 +784,7 @@ xps_parse_line_cap(char *attr) */ int -xps_parse_path(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, xps_item_t *root) +xps_parse_path(xps_context_t *ctx, fz_matrix ctm, char *base_uri, xps_resource_t *dict, xps_item_t *root) { xps_item_t *node; int code; @@ -794,16 +820,15 @@ xps_parse_path(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, xps_ite char *stroke_miter_limit_att; char *stroke_thickness_att; - gs_line_join linejoin; - float linewidth; - float miterlimit; + fz_strokestate stroke; + fz_matrix transform; float samples[32]; - gs_color_space *colorspace; - - gs_gsave(ctx->pgs); + fz_colorspace *colorspace; ctx->fill_rule = 0; +printf("xps_parse_path\n"); + /* * Extract attributes and extended attributes. */ @@ -875,162 +900,145 @@ xps_parse_path(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, xps_ite stroke_tag = NULL; } - gs_setlinestartcap(ctx->pgs, xps_parse_line_cap(stroke_start_line_cap_att)); - gs_setlineendcap(ctx->pgs, xps_parse_line_cap(stroke_end_line_cap_att)); - gs_setlinedashcap(ctx->pgs, xps_parse_line_cap(stroke_dash_cap_att)); + stroke.linecap = xps_parse_line_cap(stroke_start_line_cap_att); +// fz_setlineendcap(ctx->pgs, xps_parse_line_cap(stroke_end_line_cap_att)); +// fz_setlinedashcap(ctx->pgs, xps_parse_line_cap(stroke_dash_cap_att)); - linejoin = gs_join_miter; + stroke.linejoin = 0; if (stroke_line_join_att) { - if (!strcmp(stroke_line_join_att, "Miter")) linejoin = gs_join_miter; - if (!strcmp(stroke_line_join_att, "Bevel")) linejoin = gs_join_bevel; - if (!strcmp(stroke_line_join_att, "Round")) linejoin = gs_join_round; + if (!strcmp(stroke_line_join_att, "Miter")) stroke.linejoin = 0; + if (!strcmp(stroke_line_join_att, "Round")) stroke.linejoin = 1; + if (!strcmp(stroke_line_join_att, "Bevel")) stroke.linejoin = 2; } - gs_setlinejoin(ctx->pgs, linejoin); - miterlimit = 10.0; + stroke.miterlimit = 10.0; if (stroke_miter_limit_att) - miterlimit = atof(stroke_miter_limit_att); - gs_setmiterlimit(ctx->pgs, miterlimit); + stroke.miterlimit = atof(stroke_miter_limit_att); - linewidth = 1.0; + stroke.linewidth = 1.0; if (stroke_thickness_att) - linewidth = atof(stroke_thickness_att); - gs_setlinewidth(ctx->pgs, linewidth); + stroke.linewidth = atof(stroke_thickness_att); + stroke.dashphase = 0; + stroke.dashlen = 0; if (stroke_dash_array_att) { char *s = stroke_dash_array_att; - float dash_array[100]; - float dash_offset = 0.0; - int dash_count = 0; if (stroke_dash_offset_att) - dash_offset = atof(stroke_dash_offset_att) * linewidth; + stroke.dashphase = atof(stroke_dash_offset_att) * stroke.linewidth; - while (*s) + while (*s && stroke.dashlen < nelem(stroke.dashlist)) { while (*s == ' ') s++; - dash_array[dash_count++] = atof(s) * linewidth; + stroke.dashlist[stroke.dashlen++] = atof(s) * stroke.linewidth; while (*s && *s != ' ') s++; } - - gs_setdash(ctx->pgs, dash_array, dash_count, dash_offset); - } - else - { - gs_setdash(ctx->pgs, NULL, 0, 0.0); } - if (transform_att || transform_tag) - { - gs_matrix transform; - - if (transform_att) - xps_parse_render_transform(ctx, transform_att, &transform); - if (transform_tag) - xps_parse_matrix_transform(ctx, transform_tag, &transform); - - gs_concat(ctx->pgs, &transform); - } + transform = fz_identity; + if (transform_att) + xps_parse_render_transform(ctx, transform_att, &transform); + if (transform_tag) + xps_parse_matrix_transform(ctx, transform_tag, &transform); + ctm = fz_concat(ctm, transform); if (clip_att || clip_tag) { + ctx->path = fz_newpath(); if (clip_att) xps_parse_abbreviated_geometry(ctx, clip_att); if (clip_tag) xps_parse_path_geometry(ctx, dict, clip_tag, 0); - xps_clip(ctx); - } - -#if 0 // XXX - if (opacity_att || opacity_mask_tag) - { - /* clip the bounds with the actual path */ - if (data_att) - xps_parse_abbreviated_geometry(ctx, data_att); - if (data_tag) - xps_parse_path_geometry(ctx, dict, data_tag, 0); - xps_update_bounds(ctx, &saved_bounds_opacity); - gs_newpath(ctx->pgs); + xps_clip(ctx, ctm); } -#endif - code = xps_begin_opacity(ctx, opacity_mask_uri, dict, opacity_att, opacity_mask_tag); + code = xps_begin_opacity(ctx, ctm, opacity_mask_uri, dict, opacity_att, opacity_mask_tag); if (code) { - gs_grestore(ctx->pgs); - return gs_rethrow(code, "cannot create transparency group"); +// fz_grestore(ctx->pgs); + return fz_rethrow(code, "cannot create transparency group"); } if (fill_att) { +printf(" fill-att\n"); xps_parse_color(ctx, base_uri, fill_att, &colorspace, samples); if (fill_opacity_att) samples[0] = atof(fill_opacity_att); xps_set_color(ctx, colorspace, samples); + ctx->path = fz_newpath(); if (data_att) xps_parse_abbreviated_geometry(ctx, data_att); if (data_tag) xps_parse_path_geometry(ctx, dict, data_tag, 0); - xps_fill(ctx); + xps_fill(ctx, ctm); } if (fill_tag) { +printf(" fill-tag\n"); + ctx->path = fz_newpath(); if (data_att) xps_parse_abbreviated_geometry(ctx, data_att); if (data_tag) xps_parse_path_geometry(ctx, dict, data_tag, 0); - code = xps_parse_brush(ctx, fill_uri, dict, fill_tag); + code = xps_parse_brush(ctx, ctm, fill_uri, dict, fill_tag); if (code < 0) { xps_end_opacity(ctx, opacity_mask_uri, dict, opacity_att, opacity_mask_tag); - gs_grestore(ctx->pgs); - return gs_rethrow(code, "cannot parse fill brush"); +// fz_grestore(ctx->pgs); + return fz_rethrow(code, "cannot parse fill brush"); } } if (stroke_att) { +printf(" stroke_att\n"); xps_parse_color(ctx, base_uri, stroke_att, &colorspace, samples); if (stroke_opacity_att) samples[0] = atof(stroke_opacity_att); xps_set_color(ctx, colorspace, samples); + ctx->path = fz_newpath(); if (data_att) xps_parse_abbreviated_geometry(ctx, data_att); if (data_tag) xps_parse_path_geometry(ctx, dict, data_tag, 1); - gs_stroke(ctx->pgs); + xps_stroke(ctx, ctm, &stroke); } if (stroke_tag) { +printf(" stroke_tag\n"); + ctx->path = fz_newpath(); if (data_att) xps_parse_abbreviated_geometry(ctx, data_att); if (data_tag) xps_parse_path_geometry(ctx, dict, data_tag, 1); ctx->fill_rule = 1; /* over-ride fill rule when converting outline to stroked */ - gs_strokepath2(ctx->pgs); + xps_clipstroke(ctx, ctm, &stroke); - code = xps_parse_brush(ctx, stroke_uri, dict, stroke_tag); + code = xps_parse_brush(ctx, ctm, stroke_uri, dict, stroke_tag); if (code < 0) { xps_end_opacity(ctx, opacity_mask_uri, dict, opacity_att, opacity_mask_tag); - gs_grestore(ctx->pgs); - return gs_rethrow(code, "cannot parse stroke brush"); +// fz_grestore(ctx->pgs); + return fz_rethrow(code, "cannot parse stroke brush"); } + + ctx->dev->popclip(ctx->dev); } xps_end_opacity(ctx, opacity_mask_uri, dict, opacity_att, opacity_mask_tag); - gs_grestore(ctx->pgs); +// fz_grestore(ctx->pgs); return 0; } diff --git a/xps/xpspng.c b/xps/xpspng.c index d88461cc..c7ed90bc 100644 --- a/xps/xpspng.c +++ b/xps/xpspng.c @@ -1,29 +1,7 @@ -/* Copyright (C) 2006-2010 Artifex Software, Inc. - All Rights Reserved. +#include "fitz.h" +#include "muxps.h" - This software is provided AS-IS with no warranty, either express or - implied. - - This software is distributed under license and may not be copied, modified - or distributed except as expressly authorized under the terms of that - license. Refer to licensing information at http://www.artifex.com/ - or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, - San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information. -*/ - -/* XPS interpreter - PNG image support */ - -#include "ghostxps.h" - -#include "stream.h" -#include "strimpl.h" -#include "gsstate.h" - -/* silence a warning where #if SHARE_LIBPNG is used when it's undefined */ -#ifndef SHARE_LIBPNG -#define SHARE_LIBPNG 0 -#endif -#include "png_.h" +#include "png.h" /* * PNG using libpng directly (no gs wrappers) @@ -48,15 +26,13 @@ xps_png_read(png_structp png, png_bytep data, png_size_t length) static png_voidp xps_png_malloc(png_structp png, png_size_t size) { - gs_memory_t *mem = png_get_mem_ptr(png); - return gs_alloc_bytes(mem, size, "libpng"); + return fz_malloc(size); } static void xps_png_free(png_structp png, png_voidp ptr) { - gs_memory_t *mem = png_get_mem_ptr(png); - gs_free_object(mem, ptr, "libpng"); + fz_free(ptr); } /* This only determines if we have an alpha value */ @@ -77,15 +53,15 @@ xps_png_has_alpha(xps_context_t *ctx, byte *rbuf, int rlen) png = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL, - ctx->memory, xps_png_malloc, xps_png_free); + ctx, xps_png_malloc, xps_png_free); if (!png) { - gs_warn("png_create_read_struct"); + fz_warn("png_create_read_struct"); return 0; } info = png_create_info_struct(png); if (!info) { - gs_warn("png_create_info_struct"); + fz_warn("png_create_info_struct"); return 0; } @@ -99,7 +75,7 @@ xps_png_has_alpha(xps_context_t *ctx, byte *rbuf, int rlen) if (setjmp(png_jmpbuf(png))) { png_destroy_read_struct(&png, &info, NULL); - gs_warn("png reading failed"); + fz_warn("png reading failed"); return 0; } @@ -123,7 +99,7 @@ xps_png_has_alpha(xps_context_t *ctx, byte *rbuf, int rlen) break; default: - gs_warn("cannot handle this png color type"); + fz_warn("cannot handle this png color type"); has_alpha = 0; break; } @@ -156,13 +132,13 @@ xps_decode_png(xps_context_t *ctx, byte *rbuf, int rlen, xps_image_t *image) png = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL, - ctx->memory, xps_png_malloc, xps_png_free); + ctx, xps_png_malloc, xps_png_free); if (!png) - return gs_throw(-1, "png_create_read_struct"); + return fz_throw("png_create_read_struct"); info = png_create_info_struct(png); if (!info) - return gs_throw(-1, "png_create_info_struct"); + return fz_throw("png_create_info_struct"); png_set_read_fn(png, &io, xps_png_read); png_set_crc_action(png, PNG_CRC_WARN_USE, PNG_CRC_WARN_USE); @@ -174,7 +150,7 @@ xps_decode_png(xps_context_t *ctx, byte *rbuf, int rlen, xps_image_t *image) if (setjmp(png_jmpbuf(png))) { png_destroy_read_struct(&png, &info, NULL); - return gs_throw(-1, "png reading failed"); + return fz_throw("png reading failed"); } /* @@ -225,27 +201,27 @@ xps_decode_png(xps_context_t *ctx, byte *rbuf, int rlen, xps_image_t *image) switch (png_get_color_type(png, info)) { case PNG_COLOR_TYPE_GRAY: - image->colorspace = ctx->gray; + image->colorspace = fz_devicegray; image->hasalpha = 0; break; case PNG_COLOR_TYPE_RGB: - image->colorspace = ctx->srgb; + image->colorspace = fz_devicergb; image->hasalpha = 0; break; case PNG_COLOR_TYPE_GRAY_ALPHA: - image->colorspace = ctx->gray; + image->colorspace = fz_devicegray; image->hasalpha = 1; break; case PNG_COLOR_TYPE_RGB_ALPHA: - image->colorspace = ctx->srgb; + image->colorspace = fz_devicergb; image->hasalpha = 1; break; default: - return gs_throw(-1, "cannot handle this png color type"); + return fz_throw("cannot handle this png color type"); } /* @@ -289,5 +265,5 @@ xps_decode_png(xps_context_t *ctx, byte *rbuf, int rlen, xps_image_t *image) png_destroy_read_struct(&png, &info, NULL); - return gs_okay; + return fz_okay; } diff --git a/xps/xpsresource.c b/xps/xpsresource.c index a21d6bed..399c067a 100644 --- a/xps/xpsresource.c +++ b/xps/xpsresource.c @@ -1,19 +1,5 @@ -/* Copyright (C) 2006-2010 Artifex Software, Inc. - All Rights Reserved. - - This software is provided AS-IS with no warranty, either express or - implied. - - This software is distributed under license and may not be copied, modified - or distributed except as expressly authorized under the terms of that - license. Refer to licensing information at http://www.artifex.com/ - or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, - San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information. -*/ - -/* XPS interpreter - resource functions */ - -#include "ghostxps.h" +#include "fitz.h" +#include "muxps.h" static xps_item_t * xps_find_resource(xps_context_t *ctx, xps_resource_t *dict, char *name, char **urip) @@ -82,21 +68,21 @@ xps_parse_remote_resource_dictionary(xps_context_t *ctx, xps_resource_t **dictp, part = xps_read_part(ctx, part_name); if (!part) { - return gs_throw1(-1, "cannot find remote resource part '%s'", part_name); + return fz_throw("cannot find remote resource part '%s'", part_name); } xml = xps_parse_xml(ctx, part->data, part->size); if (!xml) { xps_free_part(ctx, part); - return gs_rethrow(-1, "cannot parse xml"); + return fz_rethrow(-1, "cannot parse xml"); } if (strcmp(xps_tag(xml), "ResourceDictionary")) { xps_free_item(ctx, xml); xps_free_part(ctx, part); - return gs_throw1(-1, "expected ResourceDictionary element (found %s)", xps_tag(xml)); + return fz_throw("expected ResourceDictionary element (found %s)", xps_tag(xml)); } xps_strlcpy(part_uri, part_name, sizeof part_uri); @@ -109,7 +95,7 @@ xps_parse_remote_resource_dictionary(xps_context_t *ctx, xps_resource_t **dictp, { xps_free_item(ctx, xml); xps_free_part(ctx, part); - return gs_rethrow1(code, "cannot parse remote resource dictionary: %s", part_uri); + return fz_rethrow(code, "cannot parse remote resource dictionary: %s", part_uri); } dict->base_xml = xml; /* pass on ownership */ @@ -117,7 +103,7 @@ xps_parse_remote_resource_dictionary(xps_context_t *ctx, xps_resource_t **dictp, xps_free_part(ctx, part); *dictp = dict; - return gs_okay; + return fz_okay; } int @@ -135,8 +121,8 @@ xps_parse_resource_dictionary(xps_context_t *ctx, xps_resource_t **dictp, char * { code = xps_parse_remote_resource_dictionary(ctx, dictp, base_uri, source); if (code) - return gs_rethrow(code, "cannot parse remote resource dictionary"); - return gs_okay; + return fz_rethrow(code, "cannot parse remote resource dictionary"); + return fz_okay; } head = NULL; @@ -149,7 +135,7 @@ xps_parse_resource_dictionary(xps_context_t *ctx, xps_resource_t **dictp, char * { entry = xps_alloc(ctx, sizeof(xps_resource_t)); if (!entry) - return gs_throw(-1, "cannot allocate resource entry"); + return fz_throw("cannot allocate resource entry"); entry->name = key; entry->base_uri = NULL; entry->base_xml = NULL; @@ -166,7 +152,7 @@ xps_parse_resource_dictionary(xps_context_t *ctx, xps_resource_t **dictp, char * } *dictp = head; - return gs_okay; + return fz_okay; } void @@ -191,13 +177,13 @@ xps_debug_resource_dictionary(xps_resource_t *dict) while (dict) { if (dict->base_uri) - dprintf1("URI = '%s'\n", dict->base_uri); - dprintf2("KEY = '%s' VAL = %p\n", dict->name, dict->data); + printf("URI = '%s'\n", dict->base_uri); + printf("KEY = '%s' VAL = %p\n", dict->name, dict->data); if (dict->parent) { - dputs("PARENT = {\n"); + printf("PARENT = {\n"); xps_debug_resource_dictionary(dict->parent); - dputs("}\n"); + printf("}\n"); } dict = dict->next; } diff --git a/xps/xpstiff.c b/xps/xpstiff.c index 3e2627ef..27e5ac2b 100644 --- a/xps/xpstiff.c +++ b/xps/xpstiff.c @@ -1,19 +1,13 @@ -/* Copyright (C) 2006-2010 Artifex Software, Inc. - All Rights Reserved. +#include "fitz.h" +#include "muxps.h" - This software is provided AS-IS with no warranty, either express or - implied. - - This software is distributed under license and may not be copied, modified - or distributed except as expressly authorized under the terms of that - license. Refer to licensing information at http://www.artifex.com/ - or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, - San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information. -*/ - -/* XPS interpreter - TIFF image support */ +int +xps_decode_tiff(xps_context_t *ctx, byte *buf, int len, xps_image_t *image) +{ + return fz_throw("TIFF codec is not available"); +} -#include "ghostxps.h" +#if 0 #include "stream.h" #include "strimpl.h" @@ -159,7 +153,7 @@ static const byte bitrev[256] = static int xps_report_error(stream_state * st, const char *str) { - (void) gs_throw1(-1, "%s", str); + (void) fz_throw("%s", str); return 0; } @@ -221,7 +215,7 @@ xps_decode_tiff_packbits(xps_context_t *ctx, xps_tiff_t *tiff, byte *rp, byte *r code = s_RLD_template.process((stream_state*)&state, &scr, &scw, true); if (code == ERRC) - return gs_throw1(-1, "error in packbits data (code = %d)", code); + return fz_throw("error in packbits data (code = %d)", code); return gs_okay; } @@ -264,7 +258,7 @@ xps_decode_tiff_lzw(xps_context_t *ctx, xps_tiff_t *tiff, byte *rp, byte *rl, by if (code == ERRC) { s_LZWD_template.release((stream_state*)&state); - return gs_throw1(-1, "error in lzw data (code = %d)", code); + return fz_throw("error in lzw data (code = %d)", code); } s_LZWD_template.release((stream_state*)&state); @@ -296,7 +290,7 @@ xps_decode_tiff_flate(xps_context_t *ctx, xps_tiff_t *tiff, byte *rp, byte *rl, if (code == ERRC) { s_zlibD_template.release((stream_state*)&state); - return gs_throw1(-1, "error in flate data (code = %d)", code); + return fz_throw("error in flate data (code = %d)", code); } s_zlibD_template.release((stream_state*)&state); @@ -339,7 +333,7 @@ xps_decode_tiff_fax(xps_context_t *ctx, xps_tiff_t *tiff, int comp, byte *rp, by if (code == ERRC) { s_CFD_template.release((stream_state*)&state); - return gs_throw1(-1, "error in fax data (code = %d)", code); + return fz_throw("error in fax data (code = %d)", code); } s_CFD_template.release((stream_state*)&state); @@ -380,7 +374,7 @@ xps_decode_tiff_jpeg(xps_context_t *ctx, xps_tiff_t *tiff, byte *rp, byte *rl, b jddp.scanline_buffer = NULL; if ((code = gs_jpeg_create_decompress(&state)) < 0) - return gs_throw(-1, "error in gs_jpeg_create_decompress"); + return fz_throw("error in gs_jpeg_create_decompress"); s_DCTD_template.init((stream_state*)&state); @@ -397,7 +391,7 @@ xps_decode_tiff_jpeg(xps_context_t *ctx, xps_tiff_t *tiff, byte *rp, byte *rl, b code = gs_jpeg_read_header(&state, FALSE); if (code != JPEG_HEADER_TABLES_ONLY) - return gs_throw(-1, "error in jpeg table data"); + return fz_throw("error in jpeg table data"); } /* @@ -408,7 +402,7 @@ xps_decode_tiff_jpeg(xps_context_t *ctx, xps_tiff_t *tiff, byte *rp, byte *rl, b srcmgr->bytes_in_buffer = rl - rp; if ((code = gs_jpeg_read_header(&state, TRUE)) < 0) - return gs_throw(-1, "error in jpeg_read_header"); + return fz_throw("error in jpeg_read_header"); /* when TIFF says RGB and libjpeg says YCbCr, libjpeg is wrong */ if (tiff->photometric == 2 && jddp.dinfo.jpeg_color_space == JCS_YCbCr) @@ -421,7 +415,7 @@ xps_decode_tiff_jpeg(xps_context_t *ctx, xps_tiff_t *tiff, byte *rp, byte *rl, b */ if ((code = gs_jpeg_start_decompress(&state)) < 0) - return gs_throw(-1, "error in jpeg_start_decompress"); + return fz_throw("error in jpeg_start_decompress"); stride = jddp.dinfo.output_width * jddp.dinfo.output_components; @@ -439,7 +433,7 @@ xps_decode_tiff_jpeg(xps_context_t *ctx, xps_tiff_t *tiff, byte *rp, byte *rl, b */ if ((code = gs_jpeg_finish_decompress(&state)) < 0) - return gs_throw(-1, "error in jpeg_finish_decompress"); + return fz_throw("error in jpeg_finish_decompress"); gs_jpeg_destroy(&state); @@ -537,16 +531,16 @@ xps_expand_colormap(xps_context_t *ctx, xps_tiff_t *tiff, xps_image_t *image) /* image can be with or without extrasamples: comps is 1 or 2 */ if (image->comps != 1 && image->comps != 2) - return gs_throw(-1, "invalid number of samples for RGBPal"); + return fz_throw("invalid number of samples for RGBPal"); if (image->bits != 4 && image->bits != 8) - return gs_throw(-1, "invalid number of bits for RGBPal"); + return fz_throw("invalid number of bits for RGBPal"); stride = image->width * (image->comps + 2); samples = xps_alloc(ctx, stride * image->height); if (!samples) - return gs_throw(-1, "out of memory: samples"); + return fz_throw("out of memory: samples"); for (y = 0; y < image->height; y++) { @@ -601,10 +595,10 @@ xps_decode_tiff_strips(xps_context_t *ctx, xps_tiff_t *tiff, xps_image_t *image) unsigned i; if (!tiff->rowsperstrip || !tiff->stripoffsets || !tiff->rowsperstrip) - return gs_throw(-1, "no image data in tiff; maybe it is tiled"); + return fz_throw("no image data in tiff; maybe it is tiled"); if (tiff->planar != 1) - return gs_throw(-1, "image data is not in chunky format"); + return fz_throw("image data is not in chunky format"); image->width = tiff->imagewidth; image->height = tiff->imagelength; @@ -634,7 +628,7 @@ xps_decode_tiff_strips(xps_context_t *ctx, xps_tiff_t *tiff, xps_image_t *image) image->colorspace = ctx->srgb; break; default: - return gs_throw1(-1, "unknown photometric: %d", tiff->photometric); + return fz_throw("unknown photometric: %d", tiff->photometric); } switch (tiff->resolutionunit) @@ -663,7 +657,7 @@ xps_decode_tiff_strips(xps_context_t *ctx, xps_tiff_t *tiff, xps_image_t *image) image->samples = xps_alloc(ctx, image->stride * image->height); if (!image->samples) - return gs_throw(-1, "could not allocate image samples"); + return fz_throw("could not allocate image samples"); memset(image->samples, 0x55, image->stride * image->height); @@ -681,7 +675,7 @@ xps_decode_tiff_strips(xps_context_t *ctx, xps_tiff_t *tiff, xps_image_t *image) wlen = image->samples + image->stride * image->height - wp; if (rp + rlen > tiff->ep) - return gs_throw(-1, "strip extends beyond the end of the file"); + return fz_throw("strip extends beyond the end of the file"); /* the bits are in un-natural order */ if (tiff->fillorder == 2) @@ -706,7 +700,7 @@ xps_decode_tiff_strips(xps_context_t *ctx, xps_tiff_t *tiff, xps_image_t *image) error = xps_decode_tiff_lzw(ctx, tiff, rp, rp + rlen, wp, wp + wlen); break; case 6: - error = gs_throw(-1, "deprecated JPEG in TIFF compression not supported"); + error = fz_throw("deprecated JPEG in TIFF compression not supported"); break; case 7: error = xps_decode_tiff_jpeg(ctx, tiff, rp, rp + rlen, wp, wp + wlen); @@ -718,11 +712,11 @@ xps_decode_tiff_strips(xps_context_t *ctx, xps_tiff_t *tiff, xps_image_t *image) error = xps_decode_tiff_packbits(ctx, tiff, rp, rp + rlen, wp, wp + wlen); break; default: - error = gs_throw1(-1, "unknown TIFF compression: %d", tiff->compression); + error = fz_throw("unknown TIFF compression: %d", tiff->compression); } if (error) - return gs_rethrow1(error, "could not decode strip %d", row / tiff->rowsperstrip); + return fz_rethrow(error, "could not decode strip %d", row / tiff->rowsperstrip); /* scramble the bits back into original order */ if (tiff->fillorder == 2) @@ -749,7 +743,7 @@ xps_decode_tiff_strips(xps_context_t *ctx, xps_tiff_t *tiff, xps_image_t *image) { error = xps_expand_colormap(ctx, tiff, image); if (error) - return gs_rethrow(error, "could not expand colormap"); + return fz_rethrow(error, "could not expand colormap"); } /* WhiteIsZero .. invert */ @@ -895,7 +889,7 @@ xps_read_tiff_tag(xps_context_t *ctx, xps_tiff_t *tiff, unsigned offset) case ICCProfile: tiff->profile = xps_alloc(ctx, count); if (!tiff->profile) - return gs_throw(-1, "could not allocate embedded icc profile"); + return fz_throw("could not allocate embedded icc profile"); /* ICC profile data type is set to UNDEFINED. * TBYTE reading not correct in xps_read_tiff_tag_value */ xps_read_tiff_bytes(tiff->profile, tiff, value, count); @@ -910,21 +904,21 @@ xps_read_tiff_tag(xps_context_t *ctx, xps_tiff_t *tiff, unsigned offset) case StripOffsets: tiff->stripoffsets = (unsigned*) xps_alloc(ctx, count * sizeof(unsigned)); if (!tiff->stripoffsets) - return gs_throw(-1, "could not allocate strip offsets"); + return fz_throw("could not allocate strip offsets"); xps_read_tiff_tag_value(tiff->stripoffsets, tiff, type, value, count); break; case StripByteCounts: tiff->stripbytecounts = (unsigned*) xps_alloc(ctx, count * sizeof(unsigned)); if (!tiff->stripbytecounts) - return gs_throw(-1, "could not allocate strip byte counts"); + return fz_throw("could not allocate strip byte counts"); xps_read_tiff_tag_value(tiff->stripbytecounts, tiff, type, value, count); break; case ColorMap: tiff->colormap = (unsigned*) xps_alloc(ctx, count * sizeof(unsigned)); if (!tiff->colormap) - return gs_throw(-1, "could not allocate color map"); + return fz_throw("could not allocate color map"); xps_read_tiff_tag_value(tiff->colormap, tiff, type, value, count); break; @@ -932,7 +926,7 @@ xps_read_tiff_tag(xps_context_t *ctx, xps_tiff_t *tiff, unsigned offset) case TileLength: case TileOffsets: case TileByteCounts: - return gs_throw(-1, "tiled tiffs not supported"); + return fz_throw("tiled tiffs not supported"); default: /* printf("unknown tag: %d t=%d n=%d\n", tag, type, count); */ @@ -990,12 +984,12 @@ xps_decode_tiff_header(xps_context_t *ctx, xps_tiff_t *tiff, byte *buf, int len) tiff->order = TII; tiff->order = readshort(tiff); if (tiff->order != TII && tiff->order != TMM) - return gs_throw(-1, "not a TIFF file, wrong magic marker"); + return fz_throw("not a TIFF file, wrong magic marker"); /* check version */ version = readshort(tiff); if (version != 42) - return gs_throw(-1, "not a TIFF file, wrong version marker"); + return fz_throw("not a TIFF file, wrong version marker"); /* get offset of IFD */ offset = readlong(tiff); @@ -1013,7 +1007,7 @@ xps_decode_tiff_header(xps_context_t *ctx, xps_tiff_t *tiff, byte *buf, int len) { error = xps_read_tiff_tag(ctx, tiff, offset); if (error) - return gs_rethrow(error, "could not read TIFF header tag"); + return fz_rethrow(error, "could not read TIFF header tag"); offset += 12; } @@ -1029,7 +1023,7 @@ xps_decode_tiff(xps_context_t *ctx, byte *buf, int len, xps_image_t *image) error = xps_decode_tiff_header(ctx, tiff, buf, len); if (error) - return gs_rethrow(error, "cannot decode tiff header"); + return fz_rethrow(error, "cannot decode tiff header"); /* * Decode the image strips @@ -1040,7 +1034,7 @@ xps_decode_tiff(xps_context_t *ctx, byte *buf, int len, xps_image_t *image) error = xps_decode_tiff_strips(ctx, tiff, image); if (error) - return gs_rethrow(error, "could not decode image data"); + return fz_rethrow(error, "could not decode image data"); /* * Byte swap 16-bit images to big endian if necessary. @@ -1089,3 +1083,4 @@ xps_tiff_has_alpha(xps_context_t *ctx, byte *buf, int len) return tiff->extrasamples == 2 || tiff->extrasamples == 1; } +#endif diff --git a/xps/xpstile.c b/xps/xpstile.c index d7118b52..4f2f57ec 100644 --- a/xps/xpstile.c +++ b/xps/xpstile.c @@ -1,19 +1,5 @@ -/* Copyright (C) 2006-2010 Artifex Software, Inc. - All Rights Reserved. - - This software is provided AS-IS with no warranty, either express or - implied. - - This software is distributed under license and may not be copied, modified - or distributed except as expressly authorized under the terms of that - license. Refer to licensing information at http://www.artifex.com/ - or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, - San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information. -*/ - -/* XPS interpreter - tiles for pattern rendering */ - -#include "ghostxps.h" +#include "fitz.h" +#include "muxps.h" /* * Parse a tiling brush (visual and image brushes at this time) common @@ -28,7 +14,7 @@ struct tile_closure_s char *base_uri; xps_resource_t *dict; xps_item_t *tag; - gs_rect viewbox; + fz_rect viewbox; int tile_mode; void *user; int (*func)(xps_context_t*, char*, xps_resource_t*, xps_item_t*, void*); @@ -40,6 +26,7 @@ xps_paint_tiling_brush_clipped(struct tile_closure_s *c) xps_context_t *ctx = c->ctx; int code; +#if 0 gs_moveto(ctx->pgs, c->viewbox.p.x, c->viewbox.p.y); gs_lineto(ctx->pgs, c->viewbox.p.x, c->viewbox.q.y); gs_lineto(ctx->pgs, c->viewbox.q.x, c->viewbox.q.y); @@ -47,14 +34,16 @@ xps_paint_tiling_brush_clipped(struct tile_closure_s *c) gs_closepath(ctx->pgs); gs_clip(ctx->pgs); gs_newpath(ctx->pgs); +#endif code = c->func(c->ctx, c->base_uri, c->dict, c->tag, c->user); if (code < 0) - return gs_rethrow(code, "cannot draw clipped tile"); + return fz_rethrow(code, "cannot draw clipped tile"); return 0; } +#if 0 static int xps_paint_tiling_brush(const gs_client_color *pcc, gs_state *pgs) { @@ -113,103 +102,14 @@ xps_paint_tiling_brush(const gs_client_color *pcc, gs_state *pgs) cleanup: gs_grestore(ctx->pgs); ctx->pgs = saved_pgs; - return gs_rethrow(code, "cannot draw tile"); -} - -int -xps_high_level_pattern(xps_context_t *ctx) -{ - gs_matrix m; - gs_rect bbox; - gs_fixed_rect clip_box; - int code; - gx_device_color *pdc = gs_currentdevicecolor_inline(ctx->pgs); - const gs_client_pattern *ppat = gs_getpattern(&pdc->ccolor); - gs_pattern1_instance_t *pinst = - (gs_pattern1_instance_t *)gs_currentcolor(ctx->pgs)->pattern; - - code = gx_pattern_cache_add_dummy_entry((gs_imager_state *)ctx->pgs, - pinst, ctx->pgs->device->color_info.depth); - if (code < 0) - return code; - - code = gs_gsave(ctx->pgs); - if (code < 0) - return code; - - dev_proc(ctx->pgs->device, get_initial_matrix)(ctx->pgs->device, &m); - gs_setmatrix(ctx->pgs, &m); - code = gs_bbox_transform(&ppat->BBox, &ctm_only(ctx->pgs), &bbox); - if (code < 0) { - gs_grestore(ctx->pgs); - return code; - } - clip_box.p.x = float2fixed(bbox.p.x); - clip_box.p.y = float2fixed(bbox.p.y); - clip_box.q.x = float2fixed(bbox.q.x); - clip_box.q.y = float2fixed(bbox.q.y); - code = gx_clip_to_rectangle(ctx->pgs, &clip_box); - if (code < 0) { - gs_grestore(ctx->pgs); - return code; - } - code = dev_proc(ctx->pgs->device, pattern_manage)(ctx->pgs->device, pinst->id, pinst, - pattern_manage__start_accum); - if (code < 0) { - gs_grestore(ctx->pgs); - return code; - } - - code = xps_paint_tiling_brush(&pdc->ccolor, ctx->pgs); - if (code) { - gs_grestore(ctx->pgs); - return gs_rethrow(code, "high level pattern brush function failed"); - } - - code = gs_grestore(ctx->pgs); - if (code < 0) - return code; - - code = dev_proc(ctx->pgs->device, pattern_manage)(ctx->pgs->device, gx_no_bitmap_id, NULL, - pattern_manage__finish_accum); - - return code; -} - -static int -xps_remap_pattern(const gs_client_color *pcc, gs_state *pgs) -{ - const gs_client_pattern *ppat = gs_getpattern(pcc); - struct tile_closure_s *c = ppat->client_data; - xps_context_t *ctx = c->ctx; - int code; - - /* pgs->device is the newly created pattern accumulator, but we want to test the device - * that is 'behind' that, the actual output device, so we use the one from - * the saved XPS graphics state. - */ - code = dev_proc(ctx->pgs->device, pattern_manage)(ctx->pgs->device, ppat->uid.id, ppat, - pattern_manage__can_accum); - - if (code == 1) { - /* Device handles high-level patterns, so return 'remap'. - * This closes the internal accumulator device, as we no longer need - * it, and the error trickles back up to the PDL client. The client - * must then take action to start the device's accumulator, draw the - * pattern, close the device's accumulator and generate a cache entry. - */ - return gs_error_Remap_Color; - } else { - code = xps_paint_tiling_brush(pcc, pgs); - if (code) - return gs_rethrow(code, "remap pattern brush function failed"); - return 0; - } + return fz_rethrow(code, "cannot draw tile"); } +#endif int -xps_parse_tiling_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, xps_item_t *root, - int (*func)(xps_context_t*, char*, xps_resource_t*, xps_item_t*, void*), void *user) +xps_parse_tiling_brush(xps_context_t *ctx, fz_matrix ctm, + char *base_uri, xps_resource_t *dict, xps_item_t *root, + int (*func)(xps_context_t*, fz_matrix, char*, xps_resource_t*, xps_item_t*, void*), void *user) { xps_item_t *node; int code; @@ -224,9 +124,9 @@ xps_parse_tiling_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, xps_item_t *transform_tag = NULL; - gs_matrix transform; - gs_rect viewbox; - gs_rect viewport; + fz_matrix transform; + fz_rect viewbox; + fz_rect viewport; float scalex, scaley; int tile_mode; @@ -248,30 +148,28 @@ xps_parse_tiling_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, xps_resolve_resource_reference(ctx, dict, &transform_att, &transform_tag, NULL); - gs_make_identity(&transform); + transform = fz_identity; if (transform_att) xps_parse_render_transform(ctx, transform_att, &transform); if (transform_tag) xps_parse_matrix_transform(ctx, transform_tag, &transform); - viewbox.p.x = 0.0; viewbox.p.y = 0.0; - viewbox.q.x = 1.0; viewbox.q.y = 1.0; + viewbox = fz_unitrect; if (viewbox_att) xps_parse_rectangle(ctx, viewbox_att, &viewbox); - viewport.p.x = 0.0; viewport.p.y = 0.0; - viewport.q.x = 1.0; viewport.q.y = 1.0; + viewport = fz_unitrect; if (viewport_att) xps_parse_rectangle(ctx, viewport_att, &viewport); /* some sanity checks on the viewport/viewbox size */ - if (fabs(viewport.q.x - viewport.p.x) < 0.01) return 0; - if (fabs(viewport.q.y - viewport.p.y) < 0.01) return 0; - if (fabs(viewbox.q.x - viewbox.p.x) < 0.01) return 0; - if (fabs(viewbox.q.y - viewbox.p.y) < 0.01) return 0; + if (fabs(viewport.x1 - viewport.x0) < 0.01) return 0; + if (fabs(viewport.y1 - viewport.y0) < 0.01) return 0; + if (fabs(viewbox.x1 - viewbox.x0) < 0.01) return 0; + if (fabs(viewbox.y1 - viewbox.y0) < 0.01) return 0; - scalex = (viewport.q.x - viewport.p.x) / (viewbox.q.x - viewbox.p.x); - scaley = (viewport.q.y - viewport.p.y) / (viewbox.q.y - viewbox.p.y); + scalex = (viewport.x1 - viewport.x0) / (viewbox.x1 - viewbox.x0); + scaley = (viewport.y1 - viewport.y0) / (viewbox.y1 - viewbox.y0); tile_mode = TILE_NONE; if (tile_mode_att) @@ -288,24 +186,25 @@ xps_parse_tiling_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, tile_mode = TILE_FLIP_X_Y; } - gs_gsave(ctx->pgs); +// gs_gsave(ctx->pgs); - code = xps_begin_opacity(ctx, base_uri, dict, opacity_att, NULL); + code = xps_begin_opacity(ctx, ctm, base_uri, dict, opacity_att, NULL); if (code) { - gs_grestore(ctx->pgs); - return gs_rethrow(code, "cannot create transparency group"); +// gs_grestore(ctx->pgs); + return fz_rethrow(code, "cannot create transparency group"); } /* TODO(tor): check viewport and tiling to see if we can set it to TILE_NONE */ +#if 0 if (tile_mode != TILE_NONE) { struct tile_closure_s closure; gs_client_pattern gspat; gs_client_color gscolor; - gs_color_space *cs; + fz_colorspace *cs; closure.ctx = ctx; closure.base_uri = base_uri; @@ -346,9 +245,9 @@ xps_parse_tiling_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, gspat.YStep *= 2; } - gs_matrix_translate(&transform, viewport.p.x, viewport.p.y, &transform); - gs_matrix_scale(&transform, scalex, scaley, &transform); - gs_matrix_translate(&transform, -viewbox.p.x, -viewbox.p.y, &transform); + fz_matrix_translate(&transform, viewport.p.x, viewport.p.y, &transform); + fz_matrix_scale(&transform, scalex, scaley, &transform); + fz_matrix_translate(&transform, -viewbox.p.x, -viewbox.p.y, &transform); cs = ctx->srgb; gs_setcolorspace(ctx->pgs, cs); @@ -387,13 +286,14 @@ xps_parse_tiling_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, { xps_end_opacity(ctx, base_uri, dict, opacity_att, NULL); gs_grestore(ctx->pgs); - return gs_rethrow(code, "cannot draw tile"); + return fz_rethrow(code, "cannot draw tile"); } } +#endif xps_end_opacity(ctx, base_uri, dict, opacity_att, NULL); - gs_grestore(ctx->pgs); +// gs_grestore(ctx->pgs); return 0; } diff --git a/xps/xpstop.c b/xps/xpstop.c index 13149da6..afc64569 100644 --- a/xps/xpstop.c +++ b/xps/xpstop.c @@ -1,576 +1,384 @@ -/* Copyright (C) 2006-2010 Artifex Software, Inc. - All Rights Reserved. +#include "fitz.h" +#include "muxps.h" - This software is provided AS-IS with no warranty, either express or - implied. - - This software is distributed under license and may not be copied, modified - or distributed except as expressly authorized under the terms of that - license. Refer to licensing information at http://www.artifex.com/ - or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, - San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information. -*/ - -/* Top-level API implementation of XML Paper Specification */ - -/* Language wrapper implementation (see pltop.h) */ - -#include "ghostxps.h" - -#include "pltop.h" -#include "plparse.h" /* for e_ExitLanguage */ - -#include "gxdevice.h" /* so we can include gxht.h below */ -#include "gxht.h" /* gsht1.h is incomplete, we need storage size of gs_halftone */ -#include "gsht1.h" - -int xps_zip_trace = 0; -int xps_doc_trace = 0; - -static int xps_install_halftone(xps_context_t *ctx, gx_device *pdevice); +#ifdef _MSC_VER +#include <winsock2.h> +#else +#include <sys/time.h> +#endif -#define XPS_PARSER_MIN_INPUT_SIZE (8192 * 4) +char *output = NULL; +float resolution = 72; -/* - * The XPS interpeter is identical to pl_interp_t. - * The XPS interpreter instance is derived from pl_interp_instance_t. - */ +int showxml = 0; +int showtext = 0; +int showtime = 0; +int showmd5 = 0; +int savealpha = 0; +int uselist = 1; -typedef struct xps_interp_instance_s xps_interp_instance_t; +fz_colorspace *colorspace; +fz_glyphcache *glyphcache; +char *filename; -struct xps_interp_instance_s +/* stub function for automatic resolution of indirect objects in obj_simple.c */ +int pdf_cacheobject(struct pdf_xref_s *xref, int num, int gen) { - pl_interp_instance_t pl; /* common part: must be first */ - - pl_page_action_t pre_page_action; /* action before page out */ - void *pre_page_closure; /* closure to call pre_page_action with */ - pl_page_action_t post_page_action; /* action before page out */ - void *post_page_closure; /* closure to call post_page_action with */ - - xps_context_t *ctx; - FILE *scratch_file; - char scratch_name[gp_file_name_sizeof]; -}; + return fz_throw("not a pdf"); +} -/* version and build date are not currently used */ -#define XPS_VERSION NULL -#define XPS_BUILD_DATE NULL +struct { + int count, total; + int min, max; + int minpage, maxpage; +} timing; -static const pl_interp_characteristics_t * -xps_imp_characteristics(const pl_interp_implementation_t *pimpl) +static void die(fz_error error) { - static pl_interp_characteristics_t xps_characteristics = - { - "XPS", - "PK", /* string to recognize XPS files */ - "Artifex", - XPS_VERSION, - XPS_BUILD_DATE, - XPS_PARSER_MIN_INPUT_SIZE, /* Minimum input size */ - }; - return &xps_characteristics; + fz_catch(error, "aborting"); + exit(1); } -static int -xps_imp_allocate_interp(pl_interp_t **ppinterp, - const pl_interp_implementation_t *pimpl, - gs_memory_t *pmem) +static void usage(void) { - static pl_interp_t interp; /* there's only one interpreter */ - *ppinterp = &interp; - return 0; + fprintf(stderr, + "usage: xpsdraw [options] input.xps [pages]\n" + "\t-o -\toutput filename (%%d for page number)\n" + "\t\tsupported formats: pgm, ppm, pam, png\n" + "\t-r -\tresolution in dpi (default: 72)\n" + "\t-a\tsave alpha channel (only pam and png)\n" + "\t-g\trender in grayscale\n" + "\t-m\tshow timing information\n" + "\t-t\tshow text (-tt for xml)\n" + "\t-x\tshow display list\n" + "\t-d\tdisable use of display list\n" + "\t-5\tshow md5 checksums\n" + "\tpages\tcomma separated list of ranges\n"); + exit(1); } -/* Do per-instance interpreter allocation/init. No device is set yet */ -static int -xps_imp_allocate_interp_instance(pl_interp_instance_t **ppinstance, - pl_interp_t *pinterp, - gs_memory_t *pmem) +static int gettime(void) { - xps_interp_instance_t *instance; - xps_context_t *ctx; - gs_state *pgs; - int code; - - instance = (xps_interp_instance_t *) gs_alloc_bytes(pmem, - sizeof(xps_interp_instance_t), "xps_imp_allocate_interp_instance"); - - ctx = (xps_context_t *) gs_alloc_bytes(pmem, - sizeof(xps_context_t), "xps_imp_allocate_interp_instance"); - - pgs = gs_state_alloc(pmem); -#ifdef ICCBRANCH - gsicc_init_iccmanager(pgs); -#endif - memset(ctx, 0, sizeof(xps_context_t)); - - if (!instance || !ctx || !pgs) + static struct timeval first; + static int once = 1; + struct timeval now; + if (once) { - if (instance) - gs_free_object(pmem, instance, "xps_imp_allocate_interp_instance"); - if (ctx) - gs_free_object(pmem, ctx, "xps_imp_allocate_interp_instance"); - if (pgs) - gs_state_free(pgs); - return gs_error_VMerror; + gettimeofday(&first, NULL); + once = 0; } - - ctx->instance = instance; - ctx->memory = pmem; - ctx->pgs = pgs; - /* Declare PDL client support for high level patterns, for the benefit - * of pdfwrite and other high-level devices - */ - ctx->pgs->have_pattern_streams = true; - ctx->fontdir = NULL; - ctx->file = NULL; - ctx->zip_count = 0; - ctx->zip_table = NULL; - - /* Gray, RGB and CMYK profiles set when color spaces installed in graphics lib */ - ctx->gray = gs_cspace_new_DeviceGray(ctx->memory); - ctx->cmyk = gs_cspace_new_DeviceCMYK(ctx->memory); - ctx->srgb = gs_cspace_new_DeviceRGB(ctx->memory); - ctx->scrgb = gs_cspace_new_DeviceRGB(ctx->memory); /* This needs a different profile */ - - instance->pre_page_action = 0; - instance->pre_page_closure = 0; - instance->post_page_action = 0; - instance->post_page_closure = 0; - - instance->ctx = ctx; - instance->scratch_file = NULL; - instance->scratch_name[0] = 0; - - ctx->fontdir = gs_font_dir_alloc(ctx->memory); - gs_setaligntopixels(ctx->fontdir, 1); /* no subpixels */ - gs_setgridfittt(ctx->fontdir, 1); /* see gx_ttf_outline in gxttfn.c for values */ - - *ppinstance = (pl_interp_instance_t *)instance; - - return 0; -} - -/* Set a client language into an interperter instance */ -static int -xps_imp_set_client_instance(pl_interp_instance_t *pinstance, - pl_interp_instance_t *pclient, - pl_interp_instance_clients_t which_client) -{ - /* ignore */ - return 0; + gettimeofday(&now, NULL); + return (now.tv_sec - first.tv_sec) * 1000 + (now.tv_usec - first.tv_usec) / 1000; } -static int -xps_imp_set_pre_page_action(pl_interp_instance_t *pinstance, - pl_page_action_t action, void *closure) +static int isrange(char *s) { - xps_interp_instance_t *instance = (xps_interp_instance_t *)pinstance; - instance->pre_page_action = action; - instance->pre_page_closure = closure; - return 0; -} - -static int -xps_imp_set_post_page_action(pl_interp_instance_t *pinstance, - pl_page_action_t action, void *closure) -{ - xps_interp_instance_t *instance = (xps_interp_instance_t *)pinstance; - instance->post_page_action = action; - instance->post_page_closure = closure; - return 0; + while (*s) + { + if ((*s < '0' || *s > '9') && *s != '-' && *s != ',') + return 0; + s++; + } + return 1; } static int -xps_imp_set_device(pl_interp_instance_t *pinstance, gx_device *pdevice) +xps_run_page(xps_context_t *ctx, xps_page_t *page, fz_device *dev, fz_matrix ctm) { - xps_interp_instance_t *instance = (xps_interp_instance_t *)pinstance; - xps_context_t *ctx = instance->ctx; int code; - gs_opendevice(pdevice); - -#ifdef ICCBRANCH - code = gsicc_init_device_profile(ctx->pgs, pdevice); - if (code < 0) - return code; -#endif - - code = gs_setdevice_no_erase(ctx->pgs, pdevice); - if (code < 0) - goto cleanup_setdevice; - - gs_setaccuratecurves(ctx->pgs, true); /* NB not sure */ - gs_setfilladjust(ctx->pgs, 0, 0); - - /* gsave and grestore (among other places) assume that */ - /* there are at least 2 gstates on the graphics stack. */ - /* Ensure that now. */ - code = gs_gsave(ctx->pgs); - if (code < 0) - goto cleanup_gsave; + ctx->dev = dev; - code = gs_erasepage(ctx->pgs); - if (code < 0) - goto cleanup_erase; - - code = xps_install_halftone(ctx, pdevice); - if (code < 0) - goto cleanup_halftone; - - return 0; - -cleanup_halftone: -cleanup_erase: - /* undo gsave */ - gs_grestore_only(ctx->pgs); /* destroys gs_save stack */ - -cleanup_gsave: - /* undo setdevice */ - gs_nulldevice(ctx->pgs); + code = xps_parse_fixed_page(ctx, ctm, page); + if (code) + return fz_rethrow(code, "cannot draw page part %s", page->name); -cleanup_setdevice: - /* nothing to undo */ - return code; -} + ctx->dev = nil; -static int -xps_imp_get_device_memory(pl_interp_instance_t *pinstance, gs_memory_t **ppmem) -{ - /* huh? we do nothing here */ - return 0; + return fz_okay; } -/* Parse an entire random access file */ -static int -xps_imp_process_file(pl_interp_instance_t *pinstance, char *filename) +static void drawpage(xps_context_t *ctx, int pagenum) { - xps_interp_instance_t *instance = (xps_interp_instance_t *)pinstance; - xps_context_t *ctx = instance->ctx; - int code; + fz_error error; + xps_page_t *page; + fz_displaylist *list; + fz_device *dev; + int start; - code = xps_process_file(ctx, filename); - if (code) - gs_catch1(code, "cannot process xps file '%s'", filename); + if (showtime) + { + start = gettime(); + } - return code; -} + page = xps_load_page(ctx, pagenum - 1); + if (!page) + die(fz_throw("cannot load page %d in file '%s'", pagenum, filename)); -/* Parse a cursor-full of data */ -static int -xps_imp_process(pl_interp_instance_t *pinstance, stream_cursor_read *cursor) -{ - xps_interp_instance_t *instance = (xps_interp_instance_t *)pinstance; - xps_context_t *ctx = instance->ctx; - int avail, n; + list = nil; - if (!instance->scratch_file) + if (uselist) { - instance->scratch_file = gp_open_scratch_file(ctx->memory, - "ghostxps-scratch-", instance->scratch_name, "wb"); - if (!instance->scratch_file) - { - gs_catch(gs_error_invalidfileaccess, "cannot open scratch file"); - return e_ExitLanguage; - } - if_debug1('|', "xps: open scratch file '%s'\n", instance->scratch_name); + list = fz_newdisplaylist(); + dev = fz_newlistdevice(list); + error = xps_run_page(ctx, page, dev, fz_identity); + if (error) + die(fz_rethrow(error, "cannot draw page %d in file '%s'", pagenum, filename)); + fz_freedevice(dev); } - avail = cursor->limit - cursor->ptr; - n = fwrite(cursor->ptr + 1, 1, avail, instance->scratch_file); - if (n != avail) + if (showxml) { - gs_catch(gs_error_invalidfileaccess, "cannot write to scratch file"); - return e_ExitLanguage; + dev = fz_newtracedevice(); + printf("<page number=\"%d\">\n", pagenum); + if (list) + fz_executedisplaylist(list, dev, fz_identity); + else + xps_run_page(ctx, page, dev, fz_identity); + printf("</page>\n"); + fz_freedevice(dev); } - cursor->ptr = cursor->limit; - - return 0; -} -/* Skip to end of job. - * Return 1 if done, 0 ok but EOJ not found, else negative error code. - */ -static int -xps_imp_flush_to_eoj(pl_interp_instance_t *pinstance, stream_cursor_read *pcursor) -{ - /* assume XPS cannot be pjl embedded */ - pcursor->ptr = pcursor->limit; - return 0; -} + if (showtext) + { + fz_textspan *text = fz_newtextspan(); + dev = fz_newtextdevice(text); + if (list) + fz_executedisplaylist(list, dev, fz_identity); + else + xps_run_page(ctx, page, dev, fz_identity); + fz_freedevice(dev); + printf("[Page %d]\n", pagenum); + if (showtext > 1) + fz_debugtextspanxml(text); + else + fz_debugtextspan(text); + printf("\n"); + fz_freetextspan(text); + } -/* Parser action for end-of-file */ -static int -xps_imp_process_eof(pl_interp_instance_t *pinstance) -{ - xps_interp_instance_t *instance = (xps_interp_instance_t *)pinstance; - xps_context_t *ctx = instance->ctx; - int code; + if (showmd5 || showtime) + printf("page %s %d", filename, pagenum); - if (instance->scratch_file) + if (output || showmd5 || showtime) { - if_debug0('|', "xps: executing scratch file\n"); - fclose(instance->scratch_file); - instance->scratch_file = NULL; - code = xps_process_file(ctx, instance->scratch_name); - unlink(instance->scratch_name); - if (code < 0) + float zoom; + fz_matrix ctm; + fz_rect rect; + fz_bbox bbox; + fz_pixmap *pix; + + rect.x0 = rect.y0 = 0; + rect.x1 = page->width; + rect.y1 = page->height; + + zoom = resolution / 72; + ctm = fz_translate(0, -page->height); + ctm = fz_concat(ctm, fz_scale(zoom, -zoom)); + bbox = fz_roundrect(fz_transformrect(ctm, rect)); + + /* TODO: banded rendering and multi-page ppm */ + + pix = fz_newpixmapwithrect(colorspace, bbox); + + if (savealpha) + fz_clearpixmap(pix); + else + fz_clearpixmapwithcolor(pix, 255); + + dev = fz_newdrawdevice(glyphcache, pix); + if (list) + fz_executedisplaylist(list, dev, ctm); + else + xps_run_page(ctx, page, dev, ctm); + fz_freedevice(dev); + + if (output) { - gs_catch(code, "cannot process XPS file"); - return e_ExitLanguage; + char buf[512]; + sprintf(buf, output, pagenum); + if (strstr(output, ".pgm") || strstr(output, ".ppm") || strstr(output, ".pnm")) + fz_writepnm(pix, buf); + else if (strstr(output, ".pam")) + fz_writepam(pix, buf, savealpha); + else if (strstr(output, ".png")) + fz_writepng(pix, buf, savealpha); } - } - - return 0; -} -/* Report any errors after running a job */ -static int -xps_imp_report_errors(pl_interp_instance_t *pinstance, - int code, /* prev termination status */ - long file_position, /* file position of error, -1 if unknown */ - bool force_to_cout /* force errors to cout */ - ) -{ - return 0; -} + if (showmd5) + { + fz_md5 md5; + unsigned char digest[16]; + int i; -/* Prepare interp instance for the next "job" */ -static int -xps_imp_init_job(pl_interp_instance_t *pinstance) -{ - xps_interp_instance_t *instance = (xps_interp_instance_t *)pinstance; - xps_context_t *ctx = instance->ctx; + fz_md5init(&md5); + fz_md5update(&md5, pix->samples, pix->w * pix->h * pix->n); + fz_md5final(&md5, digest); - if (gs_debug_c('|')) - xps_zip_trace = 1; - if (gs_debug_c('|')) - xps_doc_trace = 1; + printf(" "); + for (i = 0; i < 16; i++) + printf("%02x", digest[i]); + } - ctx->font_table = xps_hash_new(ctx); - ctx->colorspace_table = xps_hash_new(ctx); + fz_droppixmap(pix); + } - ctx->start_part = NULL; + if (list) + fz_freedisplaylist(list); - ctx->use_transparency = 1; - if (getenv("XPS_DISABLE_TRANSPARENCY")) - ctx->use_transparency = 0; + if (showtime) + { + int end = gettime(); + int diff = end - start; - ctx->opacity_only = 0; - ctx->fill_rule = 0; + if (diff < timing.min) + { + timing.min = diff; + timing.minpage = pagenum; + } + if (diff > timing.max) + { + timing.max = diff; + timing.maxpage = pagenum; + } + timing.total += diff; + timing.count ++; - return 0; -} + printf(" %dms", diff); + } -static void xps_free_key_func(xps_context_t *ctx, void *ptr) -{ - xps_free(ctx, ptr); + if (showmd5 || showtime) + printf("\n"); } -static void xps_free_font_func(xps_context_t *ctx, void *ptr) -{ - xps_free_font(ctx, ptr); -} -/* Wrap up interp instance after a "job" */ -static int -xps_imp_dnit_job(pl_interp_instance_t *pinstance) +static void drawrange(xps_context_t *ctx, char *range) { - xps_interp_instance_t *instance = (xps_interp_instance_t *)pinstance; - xps_context_t *ctx = instance->ctx; - int i; - - if (gs_debug_c('|')) - xps_debug_fixdocseq(ctx); - - for (i = 0; i < ctx->zip_count; i++) - xps_free(ctx, ctx->zip_table[i].name); - xps_free(ctx, ctx->zip_table); + int page, spage, epage; + char *spec, *dash; - /* TODO: free resources too */ - xps_hash_free(ctx, ctx->font_table, xps_free_key_func, xps_free_font_func); - xps_hash_free(ctx, ctx->colorspace_table, xps_free_key_func, NULL); - - xps_free_fixed_pages(ctx); - xps_free_fixed_documents(ctx); - - return 0; -} + spec = fz_strsep(&range, ","); + while (spec) + { + dash = strchr(spec, '-'); -/* Remove a device from an interperter instance */ -static int -xps_imp_remove_device(pl_interp_instance_t *pinstance) -{ - xps_interp_instance_t *instance = (xps_interp_instance_t *)pinstance; - xps_context_t *ctx = instance->ctx; + if (dash == spec) + spage = epage = xps_count_pages(ctx); + else + spage = epage = atoi(spec); - int code = 0; /* first error status encountered */ - int error; + if (dash) + { + if (strlen(dash) > 1) + epage = atoi(dash + 1); + else + epage = xps_count_pages(ctx); + } - /* return to original gstate */ - gs_grestore_only(ctx->pgs); /* destroys gs_save stack */ + spage = CLAMP(spage, 1, xps_count_pages(ctx)); + epage = CLAMP(epage, 1, xps_count_pages(ctx)); - /* Deselect device */ - /* NB */ - error = gs_nulldevice(ctx->pgs); - if (code >= 0) - code = error; + if (spage < epage) + for (page = spage; page <= epage; page++) + drawpage(ctx, page); + else + for (page = spage; page >= epage; page--) + drawpage(ctx, page); - return code; + spec = fz_strsep(&range, ","); + } } -/* Deallocate a interpreter instance */ -static int -xps_imp_deallocate_interp_instance(pl_interp_instance_t *pinstance) +int main(int argc, char **argv) { - xps_interp_instance_t *instance = (xps_interp_instance_t *)pinstance; - xps_context_t *ctx = instance->ctx; - gs_memory_t *mem = ctx->memory; + int grayscale = 0; + int accelerate = 1; + xps_context_t *ctx; + int code; + int c; - /* language clients don't free the font cache machinery */ + while ((c = fz_getopt(argc, argv, "o:p:r:Aadgmtx5")) != -1) + { + switch (c) + { + case 'o': output = fz_optarg; break; + case 'r': resolution = atof(fz_optarg); break; + case 'A': accelerate = 0; break; + case 'a': savealpha = 1; break; + case 'm': showtime++; break; + case 't': showtext++; break; + case 'x': showxml++; break; + case '5': showmd5++; break; + case 'g': grayscale++; break; + case 'd': uselist = 0; break; + default: usage(); break; + } + } - // free gstate? - gs_free_object(mem, ctx, "xps_imp_deallocate_interp_instance"); - gs_free_object(mem, instance, "xps_imp_deallocate_interp_instance"); + if (fz_optind == argc) + usage(); - return 0; -} + if (!showtext && !showxml && !showtime && !showmd5 && !output) + { + printf("nothing to do\n"); + exit(0); + } -/* Do static deinit of XPS interpreter */ -static int -xps_imp_deallocate_interp(pl_interp_t *pinterp) -{ - /* nothing to do */ - return 0; -} + if (accelerate) + fz_accelerate(); -/* Parser implementation descriptor */ -const pl_interp_implementation_t xps_implementation = -{ - xps_imp_characteristics, - xps_imp_allocate_interp, - xps_imp_allocate_interp_instance, - xps_imp_set_client_instance, - xps_imp_set_pre_page_action, - xps_imp_set_post_page_action, - xps_imp_set_device, - xps_imp_init_job, - xps_imp_process_file, - xps_imp_process, - xps_imp_flush_to_eoj, - xps_imp_process_eof, - xps_imp_report_errors, - xps_imp_dnit_job, - xps_imp_remove_device, - xps_imp_deallocate_interp_instance, - xps_imp_deallocate_interp, - xps_imp_get_device_memory, -}; - -/* - * End-of-page function called by XPS parser. - */ -int -xps_show_page(xps_context_t *ctx, int num_copies, int flush) -{ - pl_interp_instance_t *pinstance = ctx->instance; - xps_interp_instance_t *instance = ctx->instance; + glyphcache = fz_newglyphcache(); - int code = 0; + colorspace = fz_devicergb; + if (grayscale) + colorspace = fz_devicegray; + if (output && strstr(output, ".pgm")) + colorspace = fz_devicegray; + if (output && strstr(output, ".ppm")) + colorspace = fz_devicergb; - /* do pre-page action */ - if (instance->pre_page_action) - { - code = instance->pre_page_action(pinstance, instance->pre_page_closure); - if (code < 0) - return code; - if (code != 0) - return 0; /* code > 0 means abort w/no error */ - } + timing.count = 0; + timing.total = 0; + timing.min = 1 << 30; + timing.max = 0; + timing.minpage = 0; + timing.maxpage = 0; - /* output the page */ - code = gs_output_page(ctx->pgs, num_copies, flush); - if (code < 0) - return code; + if (showxml) + printf("<?xml version=\"1.0\"?>\n"); - /* do post-page action */ - if (instance->post_page_action) + while (fz_optind < argc) { - code = instance->post_page_action(pinstance, instance->post_page_closure); - if (code < 0) - return code; - } - - return 0; -} + filename = argv[fz_optind++]; -/* - * We need to install a halftone ourselves, this is not - * done automatically. - */ + ctx = xps_new_context(); + code = xps_open_file(ctx, filename); + if (code) + die(fz_rethrow(code, "cannot open document: %s", filename)); -static float -identity_transfer(floatp tint, const gx_transfer_map *ignore_map) -{ - return tint; -} + if (showxml) + printf("<document name=\"%s\">\n", filename); -/* The following is a 45 degree spot screen with the spots enumerated - * in a defined order. */ -static byte order16x16[256] = { - 38, 11, 14, 32, 165, 105, 90, 171, 38, 12, 14, 33, 161, 101, 88, 167, - 30, 6, 0, 16, 61, 225, 231, 125, 30, 6, 1, 17, 63, 222, 227, 122, - 27, 3, 8, 19, 71, 242, 205, 110, 28, 4, 9, 20, 74, 246, 208, 106, - 35, 24, 22, 40, 182, 46, 56, 144, 36, 25, 22, 41, 186, 48, 58, 148, - 152, 91, 81, 174, 39, 12, 15, 34, 156, 95, 84, 178, 40, 13, 16, 34, - 69, 212, 235, 129, 31, 7, 2, 18, 66, 216, 239, 133, 32, 8, 2, 18, - 79, 254, 203, 114, 28, 4, 10, 20, 76, 250, 199, 118, 29, 5, 10, 21, - 193, 44, 54, 142, 36, 26, 23, 42, 189, 43, 52, 139, 37, 26, 24, 42, - 39, 12, 15, 33, 159, 99, 87, 169, 38, 11, 14, 33, 163, 103, 89, 172, - 31, 7, 1, 17, 65, 220, 229, 123, 30, 6, 1, 17, 62, 223, 233, 127, - 28, 4, 9, 20, 75, 248, 210, 108, 27, 3, 9, 19, 72, 244, 206, 112, - 36, 25, 23, 41, 188, 49, 60, 150, 35, 25, 22, 41, 184, 47, 57, 146, - 157, 97, 85, 180, 40, 13, 16, 35, 154, 93, 83, 176, 39, 13, 15, 34, - 67, 218, 240, 135, 32, 8, 3, 19, 70, 214, 237, 131, 31, 7, 2, 18, - 78, 252, 197, 120, 29, 5, 11, 21, 80, 255, 201, 116, 29, 5, 10, 21, - 191, 43, 51, 137, 37, 27, 24, 43, 195, 44, 53, 140, 37, 26, 23, 42 -}; - -#define source_phase_x 4 -#define source_phase_y 0 + if (fz_optind == argc || !isrange(argv[fz_optind])) + drawrange(ctx, "1-"); + if (fz_optind < argc && isrange(argv[fz_optind])) + drawrange(ctx, argv[fz_optind++]); -static int -xps_install_halftone(xps_context_t *ctx, gx_device *pdevice) -{ - gs_halftone ht; - gs_string thresh; - int code; + if (showxml) + printf("</document>\n"); - int width = 16; - int height = 16; - thresh.data = order16x16; - thresh.size = width * height; + xps_free_context(ctx); + } - if (gx_device_must_halftone(pdevice)) + if (showtime) { - ht.type = ht_type_threshold; - ht.params.threshold.width = width; - ht.params.threshold.height = height; - ht.params.threshold.thresholds.data = thresh.data; - ht.params.threshold.thresholds.size = thresh.size; - ht.params.threshold.transfer = 0; - ht.params.threshold.transfer_closure.proc = 0; - - gs_settransfer(ctx->pgs, identity_transfer); - - code = gs_sethalftone(ctx->pgs, &ht); - if (code < 0) - return gs_throw(code, "could not install halftone"); - - code = gs_sethalftonephase(ctx->pgs, 0, 0); - if (code < 0) - return gs_throw(code, "could not set halftone phase"); + printf("total %dms / %d pages for an average of %dms\n", + timing.total, timing.count, timing.total / timing.count); + printf("fastest page %d: %dms\n", timing.minpage, timing.min); + printf("slowest page %d: %dms\n", timing.maxpage, timing.max); } + fz_freeglyphcache(glyphcache); + return 0; } diff --git a/xps/xpsutf.c b/xps/xpsutf.c index 3e1c05c9..d5c1974e 100644 --- a/xps/xpsutf.c +++ b/xps/xpsutf.c @@ -1,19 +1,5 @@ -/* Copyright (C) 2006-2010 Artifex Software, Inc. - All Rights Reserved. - - This software is provided AS-IS with no warranty, either express or - implied. - - This software is distributed under license and may not be copied, modified - or distributed except as expressly authorized under the terms of that - license. Refer to licensing information at http://www.artifex.com/ - or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, - San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information. -*/ - -/* XPS interpreter - unicode text functions */ - -#include "ghostxps.h" +#include "fitz.h" +#include "muxps.h" /* * http://tools.ietf.org/html/rfc3629 diff --git a/xps/xpsvisual.c b/xps/xpsvisual.c index f23ef991..0b6fb4da 100644 --- a/xps/xpsvisual.c +++ b/xps/xpsvisual.c @@ -1,19 +1,5 @@ -/* Copyright (C) 2006-2010 Artifex Software, Inc. - All Rights Reserved. - - This software is provided AS-IS with no warranty, either express or - implied. - - This software is distributed under license and may not be copied, modified - or distributed except as expressly authorized under the terms of that - license. Refer to licensing information at http://www.artifex.com/ - or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, - San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information. -*/ - -/* XPS interpreter - visual brush functions */ - -#include "ghostxps.h" +#include "fitz.h" +#include "muxps.h" enum { TILE_NONE, TILE_TILE, TILE_FLIP_X, TILE_FLIP_Y, TILE_FLIP_X_Y }; @@ -25,13 +11,14 @@ struct userdata }; static int -xps_paint_visual_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, xps_item_t *root, void *visual_tag) +xps_paint_visual_brush(xps_context_t *ctx, fz_matrix ctm, + char *base_uri, xps_resource_t *dict, xps_item_t *root, void *visual_tag) { - return xps_parse_element(ctx, base_uri, dict, (xps_item_t *)visual_tag); + return xps_parse_element(ctx, ctm, base_uri, dict, (xps_item_t *)visual_tag); } int -xps_parse_visual_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, xps_item_t *root) +xps_parse_visual_brush(xps_context_t *ctx, fz_matrix ctm, char *base_uri, xps_resource_t *dict, xps_item_t *root) { xps_item_t *node; int code; @@ -53,9 +40,9 @@ xps_parse_visual_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, if (visual_tag) { - code = xps_parse_tiling_brush(ctx, visual_uri, dict, root, xps_paint_visual_brush, visual_tag); + code = xps_parse_tiling_brush(ctx, ctm, visual_uri, dict, root, xps_paint_visual_brush, visual_tag); if (code) - return gs_rethrow(code, "cannot parse tiling brush"); + return fz_rethrow(code, "cannot parse tiling brush"); } return 0; diff --git a/xps/xpsxml.c b/xps/xpsxml.c index ce93bcfe..2295e08c 100644 --- a/xps/xpsxml.c +++ b/xps/xpsxml.c @@ -1,19 +1,7 @@ -/* Copyright (C) 2006-2010 Artifex Software, Inc. - All Rights Reserved. - - This software is provided AS-IS with no warranty, either express or - implied. - - This software is distributed under license and may not be copied, modified - or distributed except as expressly authorized under the terms of that - license. Refer to licensing information at http://www.artifex.com/ - or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, - San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information. -*/ - /* Simple XML document object model on top of Expat. */ -#include "ghostxps.h" +#include "fitz.h" +#include "muxps.h" #include <expat.h> @@ -87,7 +75,7 @@ on_open_tag(void *zp, char *ns_name, char **atts) if (!name) { - dprintf1("unknown namespace: %s\n", ns_name); + fz_warn("unknown namespace: %s", ns_name); name = ns_name; } @@ -214,7 +202,7 @@ on_text(void *zp, char *buf, int len) static xps_item_t * xps_process_compatibility(xps_context_t *ctx, xps_item_t *root) { - gs_warn("XPS document uses markup compatibility tags"); + fz_warn("XPS document uses markup compatibility tags"); return root; } @@ -234,7 +222,7 @@ xps_parse_xml(xps_context_t *ctx, byte *buf, int len) xp = XML_ParserCreateNS(NULL, ' '); if (!xp) { - gs_throw(-1, "xml error: could not create expat parser"); + fz_throw("xml error: could not create expat parser"); return NULL; } @@ -250,7 +238,7 @@ xps_parse_xml(xps_context_t *ctx, byte *buf, int len) if (parser.root) xps_free_item(ctx, parser.root); XML_ParserFree(xp); - gs_throw1(-1, "xml error: %s", XML_ErrorString(XML_GetErrorCode(xp))); + fz_throw("xml error: %s", XML_ErrorString(XML_GetErrorCode(xp))); return NULL; } diff --git a/xps/xpszip.c b/xps/xpszip.c index 1aac7349..639134cf 100644 --- a/xps/xpszip.c +++ b/xps/xpszip.c @@ -1,30 +1,7 @@ -/* Copyright (C) 2006-2010 Artifex Software, Inc. - All Rights Reserved. +#include "fitz.h" +#include "muxps.h" - This software is provided AS-IS with no warranty, either express or - implied. - - This software is distributed under license and may not be copied, modified - or distributed except as expressly authorized under the terms of that - license. Refer to licensing information at http://www.artifex.com/ - or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, - San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information. -*/ - -/* XPS interpreter - zip container parsing */ - -#include "ghostxps.h" - -static int isfile(char *path) -{ - FILE *file = fopen(path, "rb"); - if (file) - { - fclose(file); - return 1; - } - return 0; -} +#include <zlib.h> static inline int getshort(FILE *file) { @@ -95,13 +72,11 @@ xps_read_zip_entry(xps_context_t *ctx, xps_entry_t *ent, unsigned char *outbuf) int namelength, extralength; int code; - if_debug1('|', "zip: inflating entry '%s'\n", ent->name); - fseek(ctx->file, ent->offset, 0); sig = getlong(ctx->file); if (sig != ZIP_LOCAL_FILE_SIG) - return gs_throw1(-1, "wrong zip local file signature (0x%x)", sig); + return fz_throw("wrong zip local file signature (0x%x)", sig); version = getshort(ctx->file); general = getshort(ctx->file); @@ -137,25 +112,25 @@ xps_read_zip_entry(xps_context_t *ctx, xps_entry_t *ent, unsigned char *outbuf) code = inflateInit2(&stream, -15); if (code != Z_OK) - return gs_throw1(-1, "zlib inflateInit2 error: %s", stream.msg); + return fz_throw("zlib inflateInit2 error: %s", stream.msg); code = inflate(&stream, Z_FINISH); if (code != Z_STREAM_END) { inflateEnd(&stream); - return gs_throw1(-1, "zlib inflate error: %s", stream.msg); + return fz_throw("zlib inflate error: %s", stream.msg); } code = inflateEnd(&stream); if (code != Z_OK) - return gs_throw1(-1, "zlib inflateEnd error: %s", stream.msg); + return fz_throw("zlib inflateEnd error: %s", stream.msg); xps_free(ctx, inbuf); } else { - return gs_throw1(-1, "unknown compression method (%d)", method); + return fz_throw("unknown compression method (%d)", method); } - return gs_okay; + return fz_okay; } /* @@ -174,7 +149,7 @@ xps_read_zip_dir(xps_context_t *ctx, int start_offset) sig = getlong(ctx->file); if (sig != ZIP_END_OF_CENTRAL_DIRECTORY_SIG) - return gs_throw1(-1, "wrong zip end of central directory signature (0x%x)", sig); + return fz_throw("wrong zip end of central directory signature (0x%x)", sig); (void) getshort(ctx->file); /* this disk */ (void) getshort(ctx->file); /* start disk */ @@ -186,7 +161,7 @@ xps_read_zip_dir(xps_context_t *ctx, int start_offset) ctx->zip_count = count; ctx->zip_table = xps_alloc(ctx, sizeof(xps_entry_t) * count); if (!ctx->zip_table) - return gs_throw(-1, "cannot allocate zip entry table"); + return fz_throw("cannot allocate zip entry table"); memset(ctx->zip_table, 0, sizeof(xps_entry_t) * count); @@ -196,7 +171,7 @@ xps_read_zip_dir(xps_context_t *ctx, int start_offset) { sig = getlong(ctx->file); if (sig != ZIP_CENTRAL_DIRECTORY_SIG) - return gs_throw1(-1, "wrong zip central directory signature (0x%x)", sig); + return fz_throw("wrong zip central directory signature (0x%x)", sig); (void) getshort(ctx->file); /* version made by */ (void) getshort(ctx->file); /* version to extract */ @@ -217,7 +192,7 @@ xps_read_zip_dir(xps_context_t *ctx, int start_offset) ctx->zip_table[i].name = xps_alloc(ctx, namesize + 1); if (!ctx->zip_table[i].name) - return gs_throw(-1, "cannot allocate zip entry name"); + return fz_throw("cannot allocate zip entry name"); fread(ctx->zip_table[i].name, 1, namesize, ctx->file); ctx->zip_table[i].name[namesize] = 0; @@ -228,15 +203,7 @@ xps_read_zip_dir(xps_context_t *ctx, int start_offset) qsort(ctx->zip_table, count, sizeof(xps_entry_t), xps_compare_entries); - for (i = 0; i < ctx->zip_count; i++) - { - if_debug3('|', "zip entry '%s' csize=%d usize=%d\n", - ctx->zip_table[i].name, - ctx->zip_table[i].csize, - ctx->zip_table[i].usize); - } - - return gs_okay; + return fz_okay; } static int @@ -258,7 +225,7 @@ xps_find_and_read_zip_dir(xps_context_t *ctx) n = fread(buf, 1, sizeof buf, ctx->file); if (n < 0) - return gs_throw(-1, "cannot read end of central directory"); + return fz_throw("cannot read end of central directory"); for (i = n - 4; i > 0; i--) if (!memcmp(buf + i, "PK\5\6", 4)) @@ -267,7 +234,7 @@ xps_find_and_read_zip_dir(xps_context_t *ctx) back += sizeof buf - 4; } - return gs_throw(-1, "cannot find end of central directory"); + return fz_throw("cannot find end of central directory"); } /* @@ -425,34 +392,15 @@ xps_read_and_process_metadata_part(xps_context_t *ctx, char *name) part = xps_read_part(ctx, name); if (!part) - return gs_rethrow1(-1, "cannot read zip part '%s'", name); + return fz_rethrow(-1, "cannot read zip part '%s'", name); code = xps_parse_metadata(ctx, part); if (code) - return gs_rethrow1(code, "cannot process metadata part '%s'", name); - - xps_free_part(ctx, part); - - return gs_okay; -} - -static int -xps_read_and_process_page_part(xps_context_t *ctx, char *name) -{ - xps_part_t *part; - int code; - - part = xps_read_part(ctx, name); - if (!part) - return gs_rethrow1(-1, "cannot read zip part '%s'", name); - - code = xps_parse_fixed_page(ctx, part); - if (code) - return gs_rethrow1(code, "cannot parse fixed page part '%s'", name); + return fz_rethrow(code, "cannot process metadata part '%s'", name); xps_free_part(ctx, part); - return gs_okay; + return fz_okay; } /* @@ -460,62 +408,16 @@ xps_read_and_process_page_part(xps_context_t *ctx, char *name) */ int -xps_process_file(xps_context_t *ctx, char *filename) +xps_open_file(xps_context_t *ctx, char *filename) { char buf[2048]; xps_document_t *doc; - xps_page_t *page; int code; char *p; ctx->file = fopen(filename, "rb"); if (!ctx->file) - return gs_throw1(-1, "cannot open file: '%s'", filename); - - if (strstr(filename, ".fpage")) - { - xps_part_t *part; - int size; - - if_debug0('|', "zip: single page mode\n"); - xps_strlcpy(buf, filename, sizeof buf); - while (1) - { - p = strrchr(buf, '/'); - if (!p) - p = strrchr(buf, '\\'); - if (!p) - break; - xps_strlcpy(p, "/_rels/.rels", buf + sizeof buf - p); - if_debug1('|', "zip: testing if '%s' exists\n", buf); - if (isfile(buf)) - { - *p = 0; - ctx->directory = xps_strdup(ctx, buf); - if_debug1('|', "zip: using '%s' as root directory\n", ctx->directory); - break; - } - *p = 0; - } - if (!ctx->directory) - { - if_debug0('|', "zip: no /_rels/.rels found; assuming absolute paths\n"); - ctx->directory = xps_strdup(ctx, ""); - } - - fseek(ctx->file, 0, SEEK_END); - size = ftell(ctx->file); - fseek(ctx->file, 0, SEEK_SET); - part = xps_new_part(ctx, filename, size); - fread(part->data, 1, size, ctx->file); - - code = xps_parse_fixed_page(ctx, part); - if (code) - return gs_rethrow1(code, "cannot parse fixed page part '%s'", part->name); - - xps_free_part(ctx, part); - return gs_okay; - } + return fz_throw("cannot open file: '%s'", filename); if (strstr(filename, "/_rels/.rels") || strstr(filename, "\\_rels\\.rels")) { @@ -525,44 +427,122 @@ xps_process_file(xps_context_t *ctx, char *filename) p = strstr(buf, "\\_rels\\.rels"); *p = 0; ctx->directory = xps_strdup(ctx, buf); - if_debug1('|', "zip: using '%s' as root directory\n", ctx->directory); } else { code = xps_find_and_read_zip_dir(ctx); if (code < 0) - return gs_rethrow(code, "cannot read zip central directory"); + return fz_rethrow(code, "cannot read zip central directory"); } code = xps_read_and_process_metadata_part(ctx, "/_rels/.rels"); if (code) - return gs_rethrow(code, "cannot process root relationship part"); + return fz_rethrow(code, "cannot process root relationship part"); if (!ctx->start_part) - return gs_throw(-1, "cannot find fixed document sequence start part"); + return fz_throw("cannot find fixed document sequence start part"); code = xps_read_and_process_metadata_part(ctx, ctx->start_part); if (code) - return gs_rethrow(code, "cannot process FixedDocumentSequence part"); + return fz_rethrow(code, "cannot process FixedDocumentSequence part"); for (doc = ctx->first_fixdoc; doc; doc = doc->next) { code = xps_read_and_process_metadata_part(ctx, doc->name); if (code) - return gs_rethrow(code, "cannot process FixedDocument part"); + return fz_rethrow(code, "cannot process FixedDocument part"); } + return fz_okay; +} + +int +xps_count_pages(xps_context_t *ctx) +{ + xps_page_t *page; + int n = 0; + for (page = ctx->first_page; page; page = page->next) + n ++; + return n; +} + +xps_page_t * +xps_load_page(xps_context_t *ctx, int number) +{ + xps_page_t *page; + int code; + int n = 0; + for (page = ctx->first_page; page; page = page->next) { - code = xps_read_and_process_page_part(ctx, page->name); - if (code) - return gs_rethrow(code, "cannot process FixedPage part"); + if (n == number) + { + if (!page->root) + { + code = xps_load_fixed_page(ctx, page); + if (code) + fz_catch(code, "ignoring errors on page"); + } + return page; + } + n ++; } + return nil; +} + +xps_context_t * +xps_new_context(void) +{ + xps_context_t *ctx; + + ctx = fz_malloc(sizeof(xps_context_t)); + + memset(ctx, 0, sizeof(xps_context_t)); + + ctx->font_table = xps_hash_new(ctx); + ctx->colorspace_table = xps_hash_new(ctx); + + ctx->start_part = NULL; + + ctx->use_transparency = 1; + if (getenv("XPS_DISABLE_TRANSPARENCY")) + ctx->use_transparency = 0; + + ctx->opacity_only = 0; + ctx->fill_rule = 0; + + return ctx; +} + +static void xps_free_key_func(xps_context_t *ctx, void *ptr) +{ + xps_free(ctx, ptr); +} + +static void xps_free_font_func(xps_context_t *ctx, void *ptr) +{ + fz_dropfont(ptr); +} + +/* Wrap up interp instance after a "job" */ +int +xps_free_context(xps_context_t *ctx) +{ + int i; - if (ctx->directory) - xps_free(ctx, ctx->directory); if (ctx->file) fclose(ctx->file); - return gs_okay; + for (i = 0; i < ctx->zip_count; i++) + xps_free(ctx, ctx->zip_table[i].name); + xps_free(ctx, ctx->zip_table); + + /* TODO: free resources too */ + xps_hash_free(ctx, ctx->font_table, xps_free_key_func, xps_free_font_func); + xps_hash_free(ctx, ctx->colorspace_table, xps_free_key_func, NULL); + + xps_free_fixed_pages(ctx); + xps_free_fixed_documents(ctx); + + return 0; } |