diff --git a/contrib/media/updf/Makefile b/contrib/media/updf/Makefile index 9556372979..30bb918a93 100644 --- a/contrib/media/updf/Makefile +++ b/contrib/media/updf/Makefile @@ -7,7 +7,7 @@ GEN := generated default: all LDFLAGS = -Tinclude/scripts/menuetos_app_v01.ld -nostdlib -L include/lib -CFLAGS += -Ifitz -Ipdf -Ixps -Iscripts -fno-stack-protector -nostdinc -fno-builtin -m32 -I include -fno-pic -w +CFLAGS += -Ifitz -Ipdf -Iscripts -fno-stack-protector -nostdinc -fno-builtin -m32 -I include -fno-pic -w LIBS += -lfreetype2 -lpng -ljbig2dec -ljpeg -lopenjpeg -lz -lm -lc #include Makerules @@ -49,31 +49,26 @@ $(OUT)/%.o : draw/%.c fitz/fitz.h | $(OUT) $(CC_CMD) $(OUT)/%.o : pdf/%.c fitz/fitz.h pdf/mupdf.h | $(OUT) $(CC_CMD) -$(OUT)/%.o : xps/%.c fitz/fitz.h xps/muxps.h | $(OUT) - $(CC_CMD) -$(OUT)/%.o : apps/%.c fitz/fitz.h pdf/mupdf.h xps/muxps.h | $(OUT) +$(OUT)/%.o : apps/%.c fitz/fitz.h pdf/mupdf.h | $(OUT) $(CC_CMD) $(OUT)/%.o : scripts/%.c | $(OUT) $(CC_CMD) .PRECIOUS : $(OUT)/%.o # Keep intermediates from chained rules -# --- Fitz, MuPDF and MuXPS libraries --- +# --- Fitz and MuPDF libraries --- FITZ_LIB := $(OUT)/libfitz.a MUPDF_LIB := $(OUT)/libmupdf.a -MUXPS_LIB := $(OUT)/libmuxps.a FITZ_SRC := $(notdir $(wildcard fitz/*.c draw/*.c)) MUPDF_SRC := $(notdir $(wildcard pdf/*.c)) -MUXPS_SRC := $(notdir $(wildcard xps/*.c)) $(FITZ_LIB) : $(addprefix $(OUT)/, $(FITZ_SRC:%.c=%.o)) $(MUPDF_LIB) : $(addprefix $(OUT)/, $(MUPDF_SRC:%.c=%.o)) -$(MUXPS_LIB) : $(addprefix $(OUT)/, $(MUXPS_SRC:%.c=%.o)) -libs: $(MUXPS_LIB) $(MUPDF_LIB) $(FITZ_LIB) $(THIRD_LIBS) - @ echo MuPDF/XPS and underlying libraries built +libs: $(MUPDF_LIB) $(FITZ_LIB) $(THIRD_LIBS) + @ echo MuPDF and underlying libraries built # --- Generated CMAP and FONT files --- @@ -121,40 +116,14 @@ $(OUT)/cmapdump.o : pdf/pdf_cmap.c pdf/pdf_cmap_parse.c # --- Tools and Apps --- PDF_APPS := $(addprefix $(OUT)/, pdfdraw pdfclean pdfextract pdfinfo pdfshow) -XPS_APPS := $(addprefix $(OUT)/, xpsdraw) $(PDF_APPS) : $(MUPDF_LIB) $(FITZ_LIB) $(THIRD_LIBS) -$(XPS_APPS) : $(MUXPS_LIB) $(FITZ_LIB) $(THIRD_LIBS) MUPDF := $(OUT)/mupdf -$(MUPDF) : $(MUXPS_LIB) $(MUPDF_LIB) $(FITZ_LIB) $(THIRD_LIBS) +$(MUPDF) : $(MUPDF_LIB) $(FITZ_LIB) $(THIRD_LIBS) ifeq "$(NOX11)" "" $(MUPDF) : $(addprefix $(OUT)/, kos_main.o pdfapp.o) $(LINK_CMD) endif -# --- Install --- - -prefix ?= /usr/local -bindir ?= $(prefix)/bin -libdir ?= $(prefix)/lib -incdir ?= $(prefix)/include -mandir ?= $(prefix)/share/man - -install: $(MUXPS_LIB) $(MUPDF_LIB) $(FITZ_LIB) $(PDF_APPS) $(XPS_APPS) $(MUPDF) - install -d $(bindir) $(libdir) $(incdir) $(mandir)/man1 - install $(MUXPS_LIB) $(MUPDF_LIB) $(FITZ_LIB) $(libdir) - install fitz/fitz.h pdf/mupdf.h xps/muxps.h $(incdir) - install $(PDF_APPS) $(XPS_APPS) $(MUPDF) $(bindir) - install $(wildcard apps/man/*.1) $(mandir)/man1 - -# --- Clean and Default --- - -all: $(THIRD_LIBS) $(FITZ_LIB) $(PDF_APPS) $(XPS_APPS) $(MUPDF) - -clean: - rm -rf $(OUT) -nuke: - rm -rf build/* $(GEN) - -.PHONY: all clean nuke install +all: $(THIRD_LIBS) $(FITZ_LIB) $(PDF_APPS) $(MUPDF) diff --git a/contrib/media/updf/Makerules b/contrib/media/updf/Makerules deleted file mode 100644 index 63a75d6a53..0000000000 --- a/contrib/media/updf/Makerules +++ /dev/null @@ -1,84 +0,0 @@ -# Configuration for the Makefile - -OS ?= $(shell uname) -OS := $(OS:MINGW%=MINGW) - -CFLAGS += -Wall - -ifeq "$(build)" "debug" -CFLAGS += -pipe -g -else ifeq "$(build)" "profile" -CFLAGS += -pipe -O2 -DNDEBUG -pg -LDFLAGS += -pg -else ifeq "$(build)" "release" -CFLAGS += -pipe -O2 -DNDEBUG -fomit-frame-pointer -else ifeq "$(build)" "native" -CFLAGS += -pipe -O2 -DNDEBUG -fomit-frame-pointer -march=native -mfpmath=sse -else -$(error unknown build setting: '$(build)') -endif - -ifeq "$(OS)" "Linux" -SYS_FREETYPE_INC := `pkg-config --cflags freetype2` -X11_LIBS := -lX11 -lXext -endif - -ifeq "$(OS)" "FreeBSD" -SYS_FREETYPE_INC := `pkg-config --cflags freetype2` -LDFLAGS += -L/usr/local/lib -X11_LIBS := -lX11 -lXext -endif - -# Mac OS X build depends on some thirdparty libs -ifeq "$(OS)" "Darwin" -SYS_FREETYPE_INC := -I/usr/X11R6/include/freetype2 -CFLAGS += -I/usr/X11R6/include -LDFLAGS += -L/usr/X11R6/lib -X11_LIBS := -lX11 -lXext -ifeq "$(arch)" "amd64" -CFLAGS += -m64 -LDFLAGS += -m64 -else -CFLAGS += -m32 -LDFLAGS += -m32 -endif -endif - -# The following section is an example of how to simply do cross-compilation -# using these Makefiles. It builds for a beagleboard running ARM linux, -# compiling on windows with the CodeSourcery G++ compilers. -# Invoke this as: -# make OS=beagle-cross build=release -# This does rely on the generated directory being populated with the cmap -# files etc first. Either: -# 1) do 'make generate' first (this relies on you having an appropriate host -# base C compiler set up - such as you would have on unix or in windows -# cygwin) -# 2) do a non cross compile build (e.g. windows in MSVC) first. -# 3) download the generated files from mupdf.com. -ifeq "$(OS)" "beagle-cross" -CC = arm-none-linux-gnueabi-gcc -LD = arm-none-linux-gnueabi-gcc -AR = arm-none-linux-gnueabi-ar -CFLAGS += -O3 -mfpu=neon -mcpu=cortex-a8 -mfloat-abi=softfp -ftree-vectorize -ffast-math -fsingle-precision-constant -CROSSCOMPILE=yes -NOX11=yes -endif - -ifeq "$(OS)" "webos-pre-cross" -CC = arm-none-linux-gnueabi-gcc -LD = arm-none-linux-gnueabi-gcc -AR = arm-none-linux-gnueabi-ar -CFLAGS += -O3 -mcpu=cortex-a8 -mfpu=neon -mfloat-abi=softfp -ftree-vectorize -ffast-math -fsingle-precision-constant -CROSSCOMPILE=yes -NOX11=yes -endif - -ifeq "$(OS)" "webos-pixi-cross" -CC = arm-none-linux-gnueabi-gcc -LD = arm-none-linux-gnueabi-gcc -AR = arm-none-linux-gnueabi-ar -CFLAGS += -O3 -mcpu=arm1136jf-s -mfpu=vfp -mfloat-abi=softfp -ffast-math -fsingle-precision-constant -CROSSCOMPILE=yes -NOX11=yes -endif diff --git a/contrib/media/updf/Makethird b/contrib/media/updf/Makethird deleted file mode 100644 index 62b6e0bb0e..0000000000 --- a/contrib/media/updf/Makethird +++ /dev/null @@ -1,203 +0,0 @@ -# GNU Makefile for third party libraries used by MuPDF -# -# If thirdparty libraries are supplied, they will be built as -# static libraries. Download and unzip the the mupdf-thirdparty.zip -# archive in the source directory. - -FREETYPE_DIR := $(wildcard thirdparty/freetype*) -JBIG2DEC_DIR := $(wildcard thirdparty/jbig2dec*) -JPEG_DIR := $(wildcard thirdparty/jpeg*) -OPENJPEG_DIR := $(wildcard thirdparty/openjpeg*/libopenjpeg) -ZLIB_DIR := $(wildcard thirdparty/zlib*) - -# --- FreeType 2 --- - -ifneq "$(FREETYPE_DIR)" "" -CFLAGS += -I$(FREETYPE_DIR)/include -LIBS := $(filter-out -lfreetype, $(LIBS)) -FREETYPE_LIB := $(OUT)/libfreetype.a - -FREETYPE_SRC := \ - ftbase.c \ - ftbbox.c \ - ftbitmap.c \ - ftgasp.c \ - ftglyph.c \ - ftinit.c \ - ftstroke.c \ - ftsynth.c \ - ftsystem.c \ - fttype1.c \ - ftxf86.c \ - cff.c \ - psaux.c \ - pshinter.c \ - psnames.c \ - raster.c \ - sfnt.c \ - smooth.c \ - truetype.c \ - type1.c \ - type1cid.c \ - -$(FREETYPE_LIB): $(addprefix $(OUT)/ft_, $(FREETYPE_SRC:%.c=%.o)) - -FT_CFLAGS := -DFT2_BUILD_LIBRARY -DDARWIN_NO_CARBON \ - '-DFT_CONFIG_MODULES_H="slimftmodules.h"' \ - '-DFT_CONFIG_OPTIONS_H="slimftoptions.h"' - -$(OUT)/ft_%.o: $(FREETYPE_DIR)/src/base/%.c | $(OUT) - $(CC_CMD) $(FT_CFLAGS) -$(OUT)/ft_%.o: $(FREETYPE_DIR)/src/cff/%.c | $(OUT) - $(CC_CMD) $(FT_CFLAGS) -$(OUT)/ft_%.o: $(FREETYPE_DIR)/src/cid/%.c | $(OUT) - $(CC_CMD) $(FT_CFLAGS) -$(OUT)/ft_%.o: $(FREETYPE_DIR)/src/psaux/%.c | $(OUT) - $(CC_CMD) $(FT_CFLAGS) -$(OUT)/ft_%.o: $(FREETYPE_DIR)/src/pshinter/%.c | $(OUT) - $(CC_CMD) $(FT_CFLAGS) -$(OUT)/ft_%.o: $(FREETYPE_DIR)/src/psnames/%.c | $(OUT) - $(CC_CMD) $(FT_CFLAGS) -$(OUT)/ft_%.o: $(FREETYPE_DIR)/src/raster/%.c | $(OUT) - $(CC_CMD) $(FT_CFLAGS) -$(OUT)/ft_%.o: $(FREETYPE_DIR)/src/smooth/%.c | $(OUT) - $(CC_CMD) $(FT_CFLAGS) -$(OUT)/ft_%.o: $(FREETYPE_DIR)/src/sfnt/%.c | $(OUT) - $(CC_CMD) $(FT_CFLAGS) -$(OUT)/ft_%.o: $(FREETYPE_DIR)/src/truetype/%.c | $(OUT) - $(CC_CMD) $(FT_CFLAGS) -$(OUT)/ft_%.o: $(FREETYPE_DIR)/src/type1/%.c | $(OUT) - $(CC_CMD) $(FT_CFLAGS) - -else -CFLAGS += $(SYS_FREETYPE_INC) -endif - -# --- JBIG2DEC --- - -ifneq "$(JBIG2DEC_DIR)" "" -CFLAGS += -I$(JBIG2DEC_DIR) -LIBS := $(filter-out -ljbig2dec, $(LIBS)) -JBIG2DEC_LIB := $(OUT)/libjbig2dec.a - -JBIG2DEC_SRC := \ - jbig2.c \ - jbig2_arith.c \ - jbig2_arith_iaid.c \ - jbig2_arith_int.c \ - jbig2_generic.c \ - jbig2_huffman.c \ - jbig2_image.c \ - jbig2_metadata.c \ - jbig2_mmr.c \ - jbig2_page.c \ - jbig2_refinement.c \ - jbig2_segment.c \ - jbig2_symbol_dict.c \ - jbig2_text.c \ - -$(JBIG2DEC_LIB): $(addprefix $(OUT)/, $(JBIG2DEC_SRC:%.c=%.o)) -$(OUT)/%.o: $(JBIG2DEC_DIR)/%.c | $(OUT) - $(CC_CMD) -DHAVE_STDINT_H -endif - -# --- JPEG library from IJG --- - -ifneq "$(JPEG_DIR)" "" -CFLAGS += -I$(JPEG_DIR) -LIBS := $(filter-out -ljpeg, $(LIBS)) -JPEG_LIB := $(OUT)/libjpeg.a - -JPEG_SRC := \ - jaricom.c \ - jcomapi.c \ - jdapimin.c \ - jdapistd.c \ - jdarith.c \ - jdatadst.c \ - jdatasrc.c \ - jdcoefct.c \ - jdcolor.c \ - jddctmgr.c \ - jdhuff.c \ - jdinput.c \ - jdmainct.c \ - jdmarker.c \ - jdmaster.c \ - jdmerge.c \ - jdpostct.c \ - jdsample.c \ - jdtrans.c \ - jerror.c \ - jfdctflt.c \ - jfdctfst.c \ - jfdctint.c \ - jidctflt.c \ - jidctfst.c \ - jidctint.c \ - jmemansi.c \ - jmemmgr.c \ - jquant1.c \ - jquant2.c \ - jutils.c \ - -$(JPEG_LIB): $(addprefix $(OUT)/jpeg_, $(JPEG_SRC:%.c=%.o)) -$(OUT)/jpeg_%.o: $(JPEG_DIR)/%.c | $(OUT) - $(CC_CMD) -Dmain=xxxmain -endif - -# --- OpenJPEG --- - -ifneq "$(OPENJPEG_DIR)" "" -CFLAGS += -I$(OPENJPEG_DIR) -LIBS := $(filter-out -lopenjpeg, $(LIBS)) -OPENJPEG_LIB := $(OUT)/libopenjpeg.a - -OPENJPEG_SRC := \ - bio.c \ - cio.c \ - dwt.c \ - event.c \ - image.c \ - j2k.c \ - j2k_lib.c \ - jp2.c \ - jpt.c \ - mct.c \ - mqc.c \ - openjpeg.c \ - pi.c \ - raw.c \ - t1.c \ - t2.c \ - tcd.c \ - tgt.c \ - -$(OPENJPEG_LIB): $(addprefix $(OUT)/opj_, $(OPENJPEG_SRC:%.c=%.o)) -$(OUT)/opj_%.o: $(OPENJPEG_DIR)/%.c | $(OUT) - $(CC_CMD) -DOPJ_STATIC -endif - -# --- ZLIB --- - -ifneq "$(ZLIB_DIR)" "" -CFLAGS += -I$(ZLIB_DIR) -LIBS := $(filter-out -lz, $(LIBS)) -ZLIB_LIB := $(OUT)/libz.a - -ZLIB_SRC := \ - adler32.c \ - compress.c \ - crc32.c \ - deflate.c \ - inffast.c \ - inflate.c \ - inftrees.c \ - trees.c \ - uncompr.c \ - zutil.c \ - -$(ZLIB_LIB): $(addprefix $(OUT)/zlib_, $(ZLIB_SRC:%.c=%.o)) -$(OUT)/zlib_%.o: $(ZLIB_DIR)/%.c | $(OUT) - $(CC_CMD) -endif diff --git a/contrib/media/updf/apps/kos_main.c b/contrib/media/updf/apps/kos_main.c index 34a934ecd4..b4aa2f987b 100644 --- a/contrib/media/updf/apps/kos_main.c +++ b/contrib/media/updf/apps/kos_main.c @@ -2,7 +2,6 @@ #define _WIN32 #include "fitz.h" #include "mupdf.h" -#include "muxps.h" #include "pdfapp.h" #include "icons/allbtns.h" #include "kolibri.c" diff --git a/contrib/media/updf/apps/pdfapp.c b/contrib/media/updf/apps/pdfapp.c index 68b81513ca..5e2b88be1f 100644 --- a/contrib/media/updf/apps/pdfapp.c +++ b/contrib/media/updf/apps/pdfapp.c @@ -1,6 +1,5 @@ #include "fitz.h" #include "mupdf.h" -#include "muxps.h" #include "pdfapp.h" #include /* for tolower() */ @@ -66,7 +65,8 @@ char *pdfapp_usage(pdfapp_t *app) "n\t\t-- find next search result\n" "N\t\t-- find previous search result\n" "c\t\t-- toggle between color and grayscale\n" - ; */ + ; + */ } void pdfapp_init(pdfapp_t *app) @@ -172,28 +172,9 @@ __menuet__debug_out("Page counter\n"); __menuet__debug_out("All is set!\n"); } -static void pdfapp_open_xps(pdfapp_t *app, char *filename, int fd) -{ - fz_error error; - fz_stream *file; - - file = fz_open_fd(fd); - error = xps_open_stream(&app->xps, file); - if (error) - pdfapp_error(app, fz_rethrow(error, "cannot open document '%s'", filename)); - fz_close(file); - - app->doctitle = filename; - - app->pagecount = xps_count_pages(app->xps); -} - void pdfapp_open(pdfapp_t *app, char *filename, int fd, int reload) { - if (strstr(filename, ".xps") || strstr(filename, ".XPS") || strstr(filename, ".rels")) - pdfapp_open_xps(app, filename, fd); - else - pdfapp_open_pdf(app, filename, fd); + pdfapp_open_pdf(app, filename, fd); app->cache = fz_new_glyph_cache(); @@ -241,12 +222,6 @@ void pdfapp_close(pdfapp_t *app) app->xref = NULL; } - if (app->xps) - { - xps_free_context(app->xps); - app->xps = NULL; - } - fz_flush_warnings(); } @@ -333,34 +308,6 @@ static void pdfapp_loadpage_pdf(pdfapp_t *app) pdf_age_store(app->xref->store, 3); } -static void pdfapp_loadpage_xps(pdfapp_t *app) -{ - xps_page *page; - fz_device *mdev; - fz_error error; - - error = xps_load_page(&page, app->xps, app->pageno - 1); - if (error) - pdfapp_error(app, fz_rethrow(error, "cannot load page %d in file '%s'", app->pageno, app->doctitle)); - - app->page_bbox.x0 = 0; - app->page_bbox.y0 = 0; - app->page_bbox.x1 = page->width; - app->page_bbox.y1 = page->height; - app->page_rotate = 0; - app->page_links = NULL; - - /* Create display list */ - app->page_list = fz_new_display_list(); - mdev = fz_new_list_device(app->page_list); - app->xps->dev = mdev; - xps_parse_fixed_page(app->xps, fz_identity, page); - app->xps->dev = NULL; - fz_free_device(mdev); - - xps_free_page(app->xps, page); -} - static void pdfapp_showpage(pdfapp_t *app, int loadpage, int drawpage, int repaint) { char buf[256]; @@ -383,8 +330,6 @@ static void pdfapp_showpage(pdfapp_t *app, int loadpage, int drawpage, int repai if (app->xref) pdfapp_loadpage_pdf(app); - if (app->xps) - pdfapp_loadpage_xps(app); /* Zero search hit position */ app->hit = -1; @@ -399,9 +344,9 @@ static void pdfapp_showpage(pdfapp_t *app, int loadpage, int drawpage, int repai if (drawpage) { - // sprintf(buf, "%s - %d/%d (%d dpi)", app->doctitle, - // app->pageno, app->pagecount, app->resolution); - // wintitle(app, buf); + sprintf(buf, "%s - %d/%d (%d dpi)", app->doctitle, + app->pageno, app->pagecount, app->resolution); + wintitle(app, buf); ctm = pdfapp_viewctm(app); bbox = fz_round_rect(fz_transform_rect(ctm, app->page_bbox)); @@ -430,7 +375,7 @@ static void pdfapp_showpage(pdfapp_t *app, int loadpage, int drawpage, int repai if (app->shrinkwrap) { - //__menuet__debug_out ("SHRINK\n"); + __menuet__debug_out ("SHRINK\n"); int w = app->image->w; int h = app->image->h; if (app->winw == w) diff --git a/contrib/media/updf/apps/pdfapp.h b/contrib/media/updf/apps/pdfapp.h index 732d637cba..8efb4d3872 100644 --- a/contrib/media/updf/apps/pdfapp.h +++ b/contrib/media/updf/apps/pdfapp.h @@ -32,7 +32,6 @@ struct pdfapp_s char *doctitle; pdf_xref *xref; pdf_outline *outline; - xps_context *xps; int pagecount; fz_glyph_cache *cache; diff --git a/contrib/media/updf/apps/xpsdraw.c b/contrib/media/updf/apps/xpsdraw.c deleted file mode 100644 index 29738e6bf7..0000000000 --- a/contrib/media/updf/apps/xpsdraw.c +++ /dev/null @@ -1,366 +0,0 @@ -#include "fitz.h" -#include "muxps.h" - -#ifdef _MSC_VER -#include -#else -#include -#endif - -char *output = NULL; -float resolution = 72; - -int showxml = 0; -int showtext = 0; -int showtime = 0; -int showmd5 = 0; -int savealpha = 0; -int uselist = 1; - -fz_colorspace *colorspace; -fz_glyph_cache *glyphcache; -char *filename; - -struct { - int count, total; - int min, max; - int minpage, maxpage; -} timing; - -static void die(fz_error error) -{ - fz_catch(error, "aborting"); - exit(1); -} - -static void usage(void) -{ - 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); -} - -static int gettime(void) -{ - static struct timeval first; - static int once = 1; - struct timeval now; - if (once) - { - gettimeofday(&first, NULL); - once = 0; - } - gettimeofday(&now, NULL); - return (now.tv_sec - first.tv_sec) * 1000 + (now.tv_usec - first.tv_usec) / 1000; -} - -static int isrange(char *s) -{ - while (*s) - { - if ((*s < '0' || *s > '9') && *s != '-' && *s != ',') - return 0; - s++; - } - return 1; -} - -static void -xps_run_page(xps_context *ctx, xps_page *page, fz_device *dev, fz_matrix ctm) -{ - ctx->dev = dev; - xps_parse_fixed_page(ctx, ctm, page); - ctx->dev = NULL; -} - -static void drawpage(xps_context *ctx, int pagenum) -{ - xps_page *page; - fz_display_list *list; - fz_device *dev; - int start; - int code; - - if (showtime) - { - start = gettime(); - } - - code = xps_load_page(&page, ctx, pagenum - 1); - if (code) - die(fz_rethrow(code, "cannot load page %d in file '%s'", pagenum, filename)); - - list = NULL; - - if (uselist) - { - list = fz_new_display_list(); - dev = fz_new_list_device(list); - xps_run_page(ctx, page, dev, fz_identity); - fz_free_device(dev); - } - - if (showxml) - { - dev = fz_new_trace_device(); - printf("\n", pagenum); - if (list) - fz_execute_display_list(list, dev, fz_identity, fz_infinite_bbox); - else - xps_run_page(ctx, page, dev, fz_identity); - printf("\n"); - fz_free_device(dev); - } - - if (showtext) - { - fz_text_span *text = fz_new_text_span(); - dev = fz_new_text_device(text); - if (list) - fz_execute_display_list(list, dev, fz_identity, fz_infinite_bbox); - else - xps_run_page(ctx, page, dev, fz_identity); - fz_free_device(dev); - printf("[Page %d]\n", pagenum); - if (showtext > 1) - fz_debug_text_span_xml(text); - else - fz_debug_text_span(text); - printf("\n"); - fz_free_text_span(text); - } - - if (showmd5 || showtime) - printf("page %s %d", filename, pagenum); - - if (output || showmd5 || showtime) - { - 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 / 96; - ctm = fz_translate(0, -page->height); - ctm = fz_concat(ctm, fz_scale(zoom, zoom)); - bbox = fz_round_rect(fz_transform_rect(ctm, rect)); - - /* TODO: banded rendering and multi-page ppm */ - - pix = fz_new_pixmap_with_rect(colorspace, bbox); - - if (savealpha) - fz_clear_pixmap(pix); - else - fz_clear_pixmap_with_color(pix, 255); - - dev = fz_new_draw_device(glyphcache, pix); - if (list) - fz_execute_display_list(list, dev, ctm, bbox); - else - xps_run_page(ctx, page, dev, ctm); - fz_free_device(dev); - - if (output) - { - char buf[512]; - sprintf(buf, output, pagenum); - if (strstr(output, ".pgm") || strstr(output, ".ppm") || strstr(output, ".pnm")) - fz_write_pnm(pix, buf); - else if (strstr(output, ".pam")) - fz_write_pam(pix, buf, savealpha); - else if (strstr(output, ".png")) - fz_write_png(pix, buf, savealpha); - } - - if (showmd5) - { - fz_md5 md5; - unsigned char digest[16]; - int i; - - fz_md5_init(&md5); - fz_md5_update(&md5, pix->samples, pix->w * pix->h * pix->n); - fz_md5_final(&md5, digest); - - printf(" "); - for (i = 0; i < 16; i++) - printf("%02x", digest[i]); - } - - fz_drop_pixmap(pix); - } - - if (list) - fz_free_display_list(list); - - if (showtime) - { - int end = gettime(); - int diff = end - start; - - 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 ++; - - printf(" %dms", diff); - } - - if (showmd5 || showtime) - printf("\n"); -} - -static void drawrange(xps_context *ctx, char *range) -{ - int page, spage, epage; - char *spec, *dash; - - spec = fz_strsep(&range, ","); - while (spec) - { - dash = strchr(spec, '-'); - - if (dash == spec) - spage = epage = xps_count_pages(ctx); - else - spage = epage = atoi(spec); - - if (dash) - { - if (strlen(dash) > 1) - epage = atoi(dash + 1); - else - epage = xps_count_pages(ctx); - } - - spage = CLAMP(spage, 1, xps_count_pages(ctx)); - epage = CLAMP(epage, 1, xps_count_pages(ctx)); - - if (spage < epage) - for (page = spage; page <= epage; page++) - drawpage(ctx, page); - else - for (page = spage; page >= epage; page--) - drawpage(ctx, page); - - spec = fz_strsep(&range, ","); - } -} - -int main(int argc, char **argv) -{ - int grayscale = 0; - int accelerate = 1; - xps_context *ctx; - int code; - int c; - - 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; - } - } - - if (fz_optind == argc) - usage(); - - if (!showtext && !showxml && !showtime && !showmd5 && !output) - { - printf("nothing to do\n"); - exit(0); - } - - if (accelerate) - fz_accelerate(); - - glyphcache = fz_new_glyph_cache(); - - colorspace = fz_device_rgb; - if (grayscale) - colorspace = fz_device_gray; - if (output && strstr(output, ".pgm")) - colorspace = fz_device_gray; - if (output && strstr(output, ".ppm")) - colorspace = fz_device_rgb; - - timing.count = 0; - timing.total = 0; - timing.min = 1 << 30; - timing.max = 0; - timing.minpage = 0; - timing.maxpage = 0; - - if (showxml) - printf("\n"); - - while (fz_optind < argc) - { - filename = argv[fz_optind++]; - - code = xps_open_file(&ctx, filename); - if (code) - die(fz_rethrow(code, "cannot open document: %s", filename)); - - if (showxml) - printf("\n", filename); - - if (fz_optind == argc || !isrange(argv[fz_optind])) - drawrange(ctx, "1-"); - if (fz_optind < argc && isrange(argv[fz_optind])) - drawrange(ctx, argv[fz_optind++]); - - if (showxml) - printf("\n"); - - xps_free_context(ctx); - } - - if (showtime) - { - 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_free_glyph_cache(glyphcache); - - return 0; -} diff --git a/contrib/media/updf/include/freetype/ttnameid.h b/contrib/media/updf/include/freetype/ttnameid.h index 66aef0432e..4b12868bb9 100644 --- a/contrib/media/updf/include/freetype/ttnameid.h +++ b/contrib/media/updf/include/freetype/ttnameid.h @@ -619,7 +619,7 @@ FT_BEGIN_HEADER #else /* current sources say */ #define TT_MS_LANGID_CROATIAN_BOSNIA_HERZEGOVINA 0x101a #define TT_MS_LANGID_BOSNIAN_BOSNIA_HERZEGOVINA 0x141a - /* and XPsp2 Platform SDK added (2004-07-26) */ + /* and XP_sp2 Platform SDK added (2004-07-26) */ /* Names are shortened to be significant within 40 chars. */ #define TT_MS_LANGID_SERBIAN_BOSNIA_HERZ_LATIN 0x181a #define TT_MS_LANGID_SERBIAN_BOSNIA_HERZ_CYRILLIC 0x181a @@ -661,7 +661,7 @@ FT_BEGIN_HEADER #define TT_MS_LANGID_FAEROESE_FAEROE_ISLANDS 0x0438 #define TT_MS_LANGID_HINDI_INDIA 0x0439 #define TT_MS_LANGID_MALTESE_MALTA 0x043a - /* Added by XPsp2 Platform SDK (2004-07-26) */ + /* Added by XP_sp2 Platform SDK (2004-07-26) */ #define TT_MS_LANGID_SAMI_NORTHERN_NORWAY 0x043b #define TT_MS_LANGID_SAMI_NORTHERN_SWEDEN 0x083b #define TT_MS_LANGID_SAMI_NORTHERN_FINLAND 0x0C3b @@ -751,7 +751,7 @@ FT_BEGIN_HEADER #define TT_MS_LANGID_TAMAZIGHT_MOROCCO_LATIN 0x085f /* Missing a LCID for Tifinagh script */ #define TT_MS_LANGID_KASHMIRI_PAKISTAN /* Arabic */ 0x0460 - /* Spelled this way by XPsp2 Platform SDK (2004-07-26) */ + /* Spelled this way by XP_sp2 Platform SDK (2004-07-26) */ /* script is yet unclear... might be Arabic, Nagari or Sharada */ #define TT_MS_LANGID_KASHMIRI_SASIA 0x0860 /* ... and aliased (by MS) for compatibility reasons. */ @@ -773,7 +773,7 @@ FT_BEGIN_HEADER #define TT_MS_LANGID_QUECHUA_ECUADOR 0x086b #define TT_MS_LANGID_QUECHUA_PERU 0x0c6b #define TT_MS_LANGID_SEPEDI_SOUTH_AFRICA 0x046c - /* Also spelled by XPsp2 Platform SDK (2004-07-26) */ + /* Also spelled by XP_sp2 Platform SDK (2004-07-26) */ #define TT_MS_LANGID_SOTHO_SOUTHERN_SOUTH_AFRICA \ TT_MS_LANGID_SEPEDI_SOUTH_AFRICA /* language codes 0x046d, 0x046e and 0x046f are (still) unknown. */ diff --git a/contrib/media/updf/lrintf.c b/contrib/media/updf/lrintf.c deleted file mode 100644 index be089dc8db..0000000000 --- a/contrib/media/updf/lrintf.c +++ /dev/null @@ -1,5 +0,0 @@ -#include - -long long int lrintf(float x) { - return floor(x); -} diff --git a/contrib/media/updf/strtoll.c b/contrib/media/updf/strtoll.c deleted file mode 100644 index fc410f2ef7..0000000000 --- a/contrib/media/updf/strtoll.c +++ /dev/null @@ -1,28 +0,0 @@ -#include -#include -#include -#include -#include - -long long int strtoll(const char *nptr, char **endptr, int base) -{ - int neg=0; - unsigned long long int v; - const char*orig=nptr; - - while(isspace(*nptr)) nptr++; - - if (*nptr == '-' && isalnum(nptr[1])) { neg=-1; nptr++; } - v=strtoull(nptr,endptr,base); - if (endptr && *endptr==nptr) *endptr=(char *)orig; - if (v>LLONG_MAX) { - if (v==0x8000000000000000ull && neg) { - errno=0; - return v; - } - errno=ERANGE; - return (neg?LLONG_MIN:LLONG_MAX); - } - return (neg?-v:v); -} - diff --git a/contrib/media/updf/xps/muxps.h b/contrib/media/updf/xps/muxps.h deleted file mode 100644 index 28603aea9b..0000000000 --- a/contrib/media/updf/xps/muxps.h +++ /dev/null @@ -1,233 +0,0 @@ -#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 constants. - */ - -typedef struct xps_context_s xps_context; - -#define REL_START_PART \ - "http://schemas.microsoft.com/xps/2005/06/fixedrepresentation" -#define REL_REQUIRED_RESOURCE \ - "http://schemas.microsoft.com/xps/2005/06/required-resource" -#define REL_REQUIRED_RESOURCE_RECURSIVE \ - "http://schemas.microsoft.com/xps/2005/06/required-resource#recursive" - -#define ZIP_LOCAL_FILE_SIG 0x04034b50 -#define ZIP_DATA_DESC_SIG 0x08074b50 -#define ZIP_CENTRAL_DIRECTORY_SIG 0x02014b50 -#define ZIP_END_OF_CENTRAL_DIRECTORY_SIG 0x06054b50 - -/* - * Memory, and string functions. - */ - -int xps_strcasecmp(char *a, char *b); -void xps_absolute_path(char *output, char *base_uri, char *path, int output_size); - -/* - * XML document model - */ - -typedef struct element xml_element; - -xml_element *xml_parse_document(byte *buf, int len); -xml_element *xml_next(xml_element *item); -xml_element *xml_down(xml_element *item); -char *xml_tag(xml_element *item); -char *xml_att(xml_element *item, const char *att); -void xml_free_element(xml_element *item); -void xml_print_element(xml_element *item, int level); - -/* - * Container parts. - */ - -typedef struct xps_part_s xps_part; - -struct xps_part_s -{ - char *name; - int size; - int cap; - byte *data; -}; - -xps_part *xps_new_part(xps_context *ctx, char *name, int size); -xps_part *xps_read_part(xps_context *ctx, char *partname); -void xps_free_part(xps_context *ctx, xps_part *part); - -/* - * Document structure. - */ - -typedef struct xps_document_s xps_document; -typedef struct xps_page_s xps_page; - -struct xps_document_s -{ - char *name; - xps_document *next; -}; - -struct xps_page_s -{ - char *name; - int width; - int height; - xml_element *root; - xps_page *next; -}; - -int xps_read_page_list(xps_context *ctx); -void xps_debug_page_list(xps_context *ctx); -void xps_free_page_list(xps_context *ctx); - -int xps_count_pages(xps_context *ctx); -int xps_load_page(xps_page **page, xps_context *ctx, int number); -void xps_free_page(xps_context *ctx, xps_page *page); - -/* - * Images, fonts, and colorspaces. - */ - -int xps_decode_jpeg(fz_pixmap **imagep, byte *rbuf, int rlen); -int xps_decode_png(fz_pixmap **imagep, byte *rbuf, int rlen); -int xps_decode_tiff(fz_pixmap **imagep, byte *rbuf, int rlen); - -typedef struct xps_font_cache_s xps_font_cache; - -struct xps_font_cache_s -{ - char *name; - fz_font *font; - xps_font_cache *next; -}; - -typedef struct xps_glyph_metrics_s xps_glyph_metrics; - -struct xps_glyph_metrics_s -{ - float hadv, vadv, vorg; -}; - -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); - -void xps_measure_font_glyph(xps_context *ctx, fz_font *font, int gid, xps_glyph_metrics *mtx); - -void xps_debug_path(xps_context *ctx); - -void xps_parse_color(xps_context *ctx, char *base_uri, char *hexstring, fz_colorspace **csp, float *samples); -void xps_set_color(xps_context *ctx, fz_colorspace *colorspace, float *samples); - -/* - * Resource dictionaries. - */ - -typedef struct xps_resource_s xps_resource; - -struct xps_resource_s -{ - char *name; - char *base_uri; /* only used in the head nodes */ - xml_element *base_xml; /* only used in the head nodes, to free the xml document */ - xml_element *data; - xps_resource *next; - xps_resource *parent; /* up to the previous dict in the stack */ -}; - -int xps_parse_resource_dictionary(xps_context *ctx, xps_resource **dictp, char *base_uri, xml_element *root); -void xps_free_resource_dictionary(xps_context *ctx, xps_resource *dict); -void xps_resolve_resource_reference(xps_context *ctx, xps_resource *dict, char **attp, xml_element **tagp, char **urip); - -void xps_debug_resource_dictionary(xps_resource *dict); - -/* - * Fixed page/graphics parsing. - */ - -void xps_parse_fixed_page(xps_context *ctx, fz_matrix ctm, xps_page *page); -void xps_parse_canvas(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *node); -void xps_parse_path(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *dict, xml_element *node); -void xps_parse_glyphs(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *dict, xml_element *node); -void xps_parse_solid_color_brush(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *dict, xml_element *node); -void xps_parse_image_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *node); -void xps_parse_visual_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *node); -void xps_parse_linear_gradient_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *node); -void xps_parse_radial_gradient_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *node); - -void xps_parse_tiling_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *root, void(*func)(xps_context*, fz_matrix, fz_rect, char*, xps_resource*, xml_element*, void*), void *user); - -void xps_parse_matrix_transform(xps_context *ctx, xml_element *root, fz_matrix *matrix); -void xps_parse_render_transform(xps_context *ctx, char *text, fz_matrix *matrix); -void xps_parse_rectangle(xps_context *ctx, char *text, fz_rect *rect); - -void xps_begin_opacity(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, char *opacity_att, xml_element *opacity_mask_tag); -void xps_end_opacity(xps_context *ctx, char *base_uri, xps_resource *dict, char *opacity_att, xml_element *opacity_mask_tag); - -void xps_parse_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *node); -void xps_parse_element(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *node); - -void xps_clip(xps_context *ctx, fz_matrix ctm, xps_resource *dict, char *clip_att, xml_element *clip_tag); - -/* - * The interpreter context. - */ - -typedef struct xps_entry_s xps_entry; - -struct xps_entry_s -{ - char *name; - int offset; - int csize; - int usize; -}; - -struct xps_context_s -{ - char *directory; - fz_stream *file; - int zip_count; - xps_entry *zip_table; - - char *start_part; /* fixed document sequence */ - xps_document *first_fixdoc; /* first fixed document */ - xps_document *last_fixdoc; /* last fixed document */ - xps_page *first_page; /* first page of document */ - xps_page *last_page; /* last page of document */ - - char *base_uri; /* base uri for parsing XML and resolving relative paths */ - char *part_uri; /* part uri for parsing metadata relations */ - - /* We cache font resources */ - xps_font_cache *font_table; - - /* Opacity attribute stack */ - float opacity[64]; - int opacity_top; - - /* Current color */ - fz_colorspace *colorspace; - float color[8]; - float alpha; - - /* Current device */ - fz_device *dev; -}; - -int xps_open_file(xps_context **ctxp, char *filename); -int xps_open_stream(xps_context **ctxp, fz_stream *file); -void xps_free_context(xps_context *ctx); - -#endif diff --git a/contrib/media/updf/xps/xps_common.c b/contrib/media/updf/xps/xps_common.c deleted file mode 100644 index 894a49416a..0000000000 --- a/contrib/media/updf/xps/xps_common.c +++ /dev/null @@ -1,282 +0,0 @@ -#include "fitz.h" -#include "muxps.h" - -static inline int unhex(int a) -{ - if (a >= 'A' && a <= 'F') return a - 'A' + 0xA; - if (a >= 'a' && a <= 'f') return a - 'a' + 0xA; - if (a >= '0' && a <= '9') return a - '0'; - return 0; -} - -void -xps_parse_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *node) -{ - /* SolidColorBrushes are handled in a special case and will never show up here */ - if (!strcmp(xml_tag(node), "ImageBrush")) - xps_parse_image_brush(ctx, ctm, area, base_uri, dict, node); - else if (!strcmp(xml_tag(node), "VisualBrush")) - xps_parse_visual_brush(ctx, ctm, area, base_uri, dict, node); - else if (!strcmp(xml_tag(node), "LinearGradientBrush")) - xps_parse_linear_gradient_brush(ctx, ctm, area, base_uri, dict, node); - else if (!strcmp(xml_tag(node), "RadialGradientBrush")) - xps_parse_radial_gradient_brush(ctx, ctm, area, base_uri, dict, node); - else - fz_warn("unknown brush tag: %s", xml_tag(node)); -} - -void -xps_parse_element(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *node) -{ - if (!strcmp(xml_tag(node), "Path")) - xps_parse_path(ctx, ctm, base_uri, dict, node); - if (!strcmp(xml_tag(node), "Glyphs")) - xps_parse_glyphs(ctx, ctm, base_uri, dict, node); - if (!strcmp(xml_tag(node), "Canvas")) - xps_parse_canvas(ctx, ctm, area, base_uri, dict, node); - /* skip unknown tags (like Foo.Resources and similar) */ -} - -void -xps_begin_opacity(xps_context *ctx, fz_matrix ctm, fz_rect area, - char *base_uri, xps_resource *dict, - char *opacity_att, xml_element *opacity_mask_tag) -{ - float opacity; - - if (!opacity_att && !opacity_mask_tag) - return; - - opacity = 1; - if (opacity_att) - opacity = fz_atof(opacity_att); - - if (opacity_mask_tag && !strcmp(xml_tag(opacity_mask_tag), "SolidColorBrush")) - { - char *scb_opacity_att = xml_att(opacity_mask_tag, "Opacity"); - char *scb_color_att = xml_att(opacity_mask_tag, "Color"); - if (scb_opacity_att) - opacity = opacity * fz_atof(scb_opacity_att); - if (scb_color_att) - { - fz_colorspace *colorspace; - float samples[32]; - xps_parse_color(ctx, base_uri, scb_color_att, &colorspace, samples); - opacity = opacity * samples[0]; - } - opacity_mask_tag = NULL; - } - - if (ctx->opacity_top + 1 < nelem(ctx->opacity)) - { - ctx->opacity[ctx->opacity_top + 1] = ctx->opacity[ctx->opacity_top] * opacity; - ctx->opacity_top++; - } - - if (opacity_mask_tag) - { - fz_begin_mask(ctx->dev, area, 0, NULL, NULL); - xps_parse_brush(ctx, ctm, area, base_uri, dict, opacity_mask_tag); - fz_end_mask(ctx->dev); - } -} - -void -xps_end_opacity(xps_context *ctx, char *base_uri, xps_resource *dict, - char *opacity_att, xml_element *opacity_mask_tag) -{ - if (!opacity_att && !opacity_mask_tag) - return; - - if (ctx->opacity_top > 0) - ctx->opacity_top--; - - if (opacity_mask_tag) - { - if (strcmp(xml_tag(opacity_mask_tag), "SolidColorBrush")) - fz_pop_clip(ctx->dev); - } -} - -void -xps_parse_render_transform(xps_context *ctx, char *transform, fz_matrix *matrix) -{ - float args[6]; - char *s = transform; - int i; - - args[0] = 1; args[1] = 0; - args[2] = 0; args[3] = 1; - args[4] = 0; args[5] = 0; - - for (i = 0; i < 6 && *s; i++) - { - args[i] = fz_atof(s); - while (*s && *s != ',') - s++; - if (*s == ',') - s++; - } - - 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 *ctx, xml_element *root, fz_matrix *matrix) -{ - char *transform; - - *matrix = fz_identity; - - if (!strcmp(xml_tag(root), "MatrixTransform")) - { - transform = xml_att(root, "Matrix"); - if (transform) - xps_parse_render_transform(ctx, transform, matrix); - } -} - -void -xps_parse_rectangle(xps_context *ctx, char *text, fz_rect *rect) -{ - float args[4]; - char *s = text; - int i; - - args[0] = 0; args[1] = 0; - args[2] = 1; args[3] = 1; - - for (i = 0; i < 4 && *s; i++) - { - args[i] = fz_atof(s); - while (*s && *s != ',') - s++; - if (*s == ',') - s++; - } - - rect->x0 = args[0]; - rect->y0 = args[1]; - rect->x1 = args[0] + args[2]; - rect->y1 = args[1] + args[3]; -} - -static int count_commas(char *s) -{ - int n = 0; - while (*s) - { - if (*s == ',') - n ++; - s ++; - } - return n; -} - -void -xps_parse_color(xps_context *ctx, char *base_uri, char *string, - fz_colorspace **csp, float *samples) -{ - char *p; - int i, n; - char buf[1024]; - char *profile; - - *csp = fz_device_rgb; - - samples[0] = 1; - samples[1] = 0; - samples[2] = 0; - samples[3] = 0; - - if (string[0] == '#') - { - if (strlen(string) == 9) - { - samples[0] = unhex(string[1]) * 16 + unhex(string[2]); - samples[1] = unhex(string[3]) * 16 + unhex(string[4]); - samples[2] = unhex(string[5]) * 16 + unhex(string[6]); - samples[3] = unhex(string[7]) * 16 + unhex(string[8]); - } - else - { - samples[0] = 255; - samples[1] = unhex(string[1]) * 16 + unhex(string[2]); - samples[2] = unhex(string[3]) * 16 + unhex(string[4]); - samples[3] = unhex(string[5]) * 16 + unhex(string[6]); - } - - samples[0] /= 255; - samples[1] /= 255; - samples[2] /= 255; - samples[3] /= 255; - } - - else if (string[0] == 's' && string[1] == 'c' && string[2] == '#') - { - if (count_commas(string) == 2) - sscanf(string, "sc#%g,%g,%g", samples + 1, samples + 2, samples + 3); - if (count_commas(string) == 3) - sscanf(string, "sc#%g,%g,%g,%g", samples, samples + 1, samples + 2, samples + 3); - } - - else if (strstr(string, "ContextColor ") == string) - { - /* Crack the string for profile name and sample values */ - fz_strlcpy(buf, string, sizeof buf); - - profile = strchr(buf, ' '); - if (!profile) - { - fz_warn("cannot find icc profile uri in '%s'", string); - return; - } - - *profile++ = 0; - p = strchr(profile, ' '); - if (!p) - { - fz_warn("cannot find component values in '%s'", profile); - return; - } - - *p++ = 0; - n = count_commas(p) + 1; - i = 0; - while (i < n) - { - samples[i++] = fz_atof(p); - p = strchr(p, ','); - if (!p) - break; - p ++; - if (*p == ' ') - p ++; - } - while (i < n) - { - samples[i++] = 0; - } - - /* TODO: load ICC profile */ - switch (n) - { - case 2: *csp = fz_device_gray; break; - case 4: *csp = fz_device_rgb; break; - case 5: *csp = fz_device_cmyk; break; - default: *csp = fz_device_gray; break; - } - } -} - -void -xps_set_color(xps_context *ctx, fz_colorspace *colorspace, float *samples) -{ - int i; - ctx->colorspace = colorspace; - for (i = 0; i < colorspace->n; i++) - ctx->color[i] = samples[i + 1]; - ctx->alpha = samples[0] * ctx->opacity[ctx->opacity_top]; -} diff --git a/contrib/media/updf/xps/xps_doc.c b/contrib/media/updf/xps/xps_doc.c deleted file mode 100644 index 5719e7f87d..0000000000 --- a/contrib/media/updf/xps/xps_doc.c +++ /dev/null @@ -1,341 +0,0 @@ -#include "fitz.h" -#include "muxps.h" - -/* - * The FixedDocumentSequence and FixedDocument parts determine - * which parts correspond to actual pages, and the page order. - */ - -void -xps_debug_page_list(xps_context *ctx) -{ - xps_document *fixdoc = ctx->first_fixdoc; - xps_page *page = ctx->first_page; - - if (ctx->start_part) - printf("start part %s\n", ctx->start_part); - - while (fixdoc) - { - printf("fixdoc %s\n", fixdoc->name); - fixdoc = fixdoc->next; - } - - while (page) - { - printf("page %s w=%d h=%d\n", page->name, page->width, page->height); - page = page->next; - } -} - -static void -xps_add_fixed_document(xps_context *ctx, char *name) -{ - xps_document *fixdoc; - - /* Check for duplicates first */ - for (fixdoc = ctx->first_fixdoc; fixdoc; fixdoc = fixdoc->next) - if (!strcmp(fixdoc->name, name)) - return; - - fixdoc = fz_malloc(sizeof(xps_document)); - fixdoc->name = fz_strdup(name); - fixdoc->next = NULL; - - if (!ctx->first_fixdoc) - { - ctx->first_fixdoc = fixdoc; - ctx->last_fixdoc = fixdoc; - } - else - { - ctx->last_fixdoc->next = fixdoc; - ctx->last_fixdoc = fixdoc; - } -} - -static void -xps_add_fixed_page(xps_context *ctx, char *name, int width, int height) -{ - xps_page *page; - - /* Check for duplicates first */ - for (page = ctx->first_page; page; page = page->next) - if (!strcmp(page->name, name)) - return; - - page = fz_malloc(sizeof(xps_page)); - page->name = fz_strdup(name); - page->width = width; - page->height = height; - page->root = NULL; - page->next = NULL; - - if (!ctx->first_page) - { - ctx->first_page = page; - ctx->last_page = page; - } - else - { - ctx->last_page->next = page; - ctx->last_page = page; - } -} - -static void -xps_free_fixed_pages(xps_context *ctx) -{ - xps_page *page = ctx->first_page; - while (page) - { - xps_page *next = page->next; - xps_free_page(ctx, page); - fz_free(page->name); - fz_free(page); - page = next; - } - ctx->first_page = NULL; - ctx->last_page = NULL; -} - -static void -xps_free_fixed_documents(xps_context *ctx) -{ - xps_document *doc = ctx->first_fixdoc; - while (doc) - { - xps_document *next = doc->next; - fz_free(doc->name); - fz_free(doc); - doc = next; - } - ctx->first_fixdoc = NULL; - ctx->last_fixdoc = NULL; -} - -void -xps_free_page_list(xps_context *ctx) -{ - xps_free_fixed_documents(ctx); - xps_free_fixed_pages(ctx); -} - -/* - * Parse the fixed document sequence structure and _rels/.rels to find the start part. - */ - -static void -xps_parse_metadata_imp(xps_context *ctx, xml_element *item) -{ - while (item) - { - xps_parse_metadata_imp(ctx, xml_down(item)); - - if (!strcmp(xml_tag(item), "Relationship")) - { - char *target = xml_att(item, "Target"); - char *type = xml_att(item, "Type"); - if (target && type) - { - char tgtbuf[1024]; - xps_absolute_path(tgtbuf, ctx->base_uri, target, sizeof tgtbuf); - if (!strcmp(type, REL_START_PART)) - ctx->start_part = fz_strdup(tgtbuf); - } - } - - if (!strcmp(xml_tag(item), "DocumentReference")) - { - char *source = xml_att(item, "Source"); - if (source) - { - char srcbuf[1024]; - xps_absolute_path(srcbuf, ctx->base_uri, source, sizeof srcbuf); - xps_add_fixed_document(ctx, srcbuf); - } - } - - if (!strcmp(xml_tag(item), "PageContent")) - { - char *source = xml_att(item, "Source"); - char *width_att = xml_att(item, "Width"); - char *height_att = xml_att(item, "Height"); - int width = width_att ? atoi(width_att) : 0; - int height = height_att ? atoi(height_att) : 0; - if (source) - { - char srcbuf[1024]; - xps_absolute_path(srcbuf, ctx->base_uri, source, sizeof srcbuf); - xps_add_fixed_page(ctx, srcbuf, width, height); - } - } - - item = xml_next(item); - } -} - -static int -xps_parse_metadata(xps_context *ctx, xps_part *part) -{ - xml_element *root; - char buf[1024]; - char *s; - - /* Save directory name part */ - fz_strlcpy(buf, part->name, sizeof buf); - s = strrchr(buf, '/'); - if (s) - s[0] = 0; - - /* _rels parts are voodoo: their URI references are from - * the part they are associated with, not the actual _rels - * part being parsed. - */ - s = strstr(buf, "/_rels"); - if (s) - *s = 0; - - ctx->base_uri = buf; - ctx->part_uri = part->name; - - root = xml_parse_document(part->data, part->size); - if (!root) - return fz_rethrow(-1, "cannot parse metadata part '%s'", part->name); - - xps_parse_metadata_imp(ctx, root); - - xml_free_element(root); - - ctx->base_uri = NULL; - ctx->part_uri = NULL; - - return fz_okay; -} - -static int -xps_read_and_process_metadata_part(xps_context *ctx, char *name) -{ - xps_part *part; - int code; - - part = xps_read_part(ctx, name); - if (!part) - return fz_rethrow(-1, "cannot read zip part '%s'", name); - - code = xps_parse_metadata(ctx, part); - if (code) - return fz_rethrow(code, "cannot process metadata part '%s'", name); - - xps_free_part(ctx, part); - - return fz_okay; -} - -int -xps_read_page_list(xps_context *ctx) -{ - xps_document *doc; - int code; - - code = xps_read_and_process_metadata_part(ctx, "/_rels/.rels"); - if (code) - return fz_rethrow(code, "cannot process root relationship part"); - - if (!ctx->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 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 fz_rethrow(code, "cannot process FixedDocument part"); - } - - return fz_okay; -} - -int -xps_count_pages(xps_context *ctx) -{ - xps_page *page; - int n = 0; - for (page = ctx->first_page; page; page = page->next) - n ++; - return n; -} - -static int -xps_load_fixed_page(xps_context *ctx, xps_page *page) -{ - xps_part *part; - xml_element *root; - char *width_att; - char *height_att; - - part = xps_read_part(ctx, page->name); - if (!part) - return fz_rethrow(-1, "cannot read zip part '%s'", page->name); - - root = xml_parse_document(part->data, part->size); - if (!root) - return fz_rethrow(-1, "cannot parse xml part '%s'", page->name); - - xps_free_part(ctx, part); - - if (strcmp(xml_tag(root), "FixedPage")) - return fz_throw("expected FixedPage element (found %s)", xml_tag(root)); - - width_att = xml_att(root, "Width"); - if (!width_att) - return fz_throw("FixedPage missing required attribute: Width"); - - height_att = xml_att(root, "Height"); - if (!height_att) - return fz_throw("FixedPage missing required attribute: Height"); - - page->width = atoi(width_att); - page->height = atoi(height_att); - page->root = root; - - return 0; -} - -int -xps_load_page(xps_page **pagep, xps_context *ctx, int number) -{ - xps_page *page; - int code; - int n = 0; - - for (page = ctx->first_page; page; page = page->next) - { - if (n == number) - { - if (!page->root) - { - code = xps_load_fixed_page(ctx, page); - if (code) - return fz_rethrow(code, "cannot load page %d", number + 1); - } - *pagep = page; - return fz_okay; - } - n ++; - } - - return fz_throw("cannot find page %d", number + 1); -} - -void -xps_free_page(xps_context *ctx, xps_page *page) -{ - /* only free the XML contents */ - if (page->root) - xml_free_element(page->root); - page->root = NULL; -} diff --git a/contrib/media/updf/xps/xps_glyphs.c b/contrib/media/updf/xps/xps_glyphs.c deleted file mode 100644 index 4b7a8cebc2..0000000000 --- a/contrib/media/updf/xps/xps_glyphs.c +++ /dev/null @@ -1,584 +0,0 @@ -#include "fitz.h" -#include "muxps.h" - -#include -#include FT_FREETYPE_H -#include FT_ADVANCES_H - -static inline int ishex(int a) -{ - return (a >= 'A' && a <= 'F') || - (a >= 'a' && a <= 'f') || - (a >= '0' && a <= '9'); -} - -static inline int unhex(int a) -{ - if (a >= 'A' && a <= 'F') return a - 'A' + 0xA; - if (a >= 'a' && a <= 'f') return a - 'a' + 0xA; - if (a >= '0' && a <= '9') return a - '0'; - return 0; -} - -int -xps_count_font_encodings(fz_font *font) -{ - FT_Face face = font->ft_face; - return face->num_charmaps; -} - -void -xps_identify_font_encoding(fz_font *font, int idx, int *pid, int *eid) -{ - FT_Face face = font->ft_face; - *pid = face->charmaps[idx]->platform_id; - *eid = face->charmaps[idx]->encoding_id; -} - -void -xps_select_font_encoding(fz_font *font, int idx) -{ - FT_Face face = font->ft_face; - FT_Set_Charmap(face, face->charmaps[idx]); -} - -int -xps_encode_font_char(fz_font *font, int code) -{ - FT_Face face = font->ft_face; - 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; -} - -void -xps_measure_font_glyph(xps_context *ctx, fz_font *font, int gid, xps_glyph_metrics *mtx) -{ - int mask = FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING | FT_LOAD_IGNORE_TRANSFORM; - FT_Face face = font->ft_face; - FT_Fixed hadv, vadv; - - FT_Set_Char_Size(face, 64, 64, 72, 72); - FT_Get_Advance(face, gid, mask, &hadv); - FT_Get_Advance(face, gid, mask | FT_LOAD_VERTICAL_LAYOUT, &vadv); - - mtx->hadv = hadv / 65536.0f; - mtx->vadv = vadv / 65536.0f; - mtx->vorg = face->ascender / (float) face->units_per_EM; -} - -static fz_font * -xps_lookup_font(xps_context *ctx, char *name) -{ - xps_font_cache *cache; - for (cache = ctx->font_table; cache; cache = cache->next) - if (!xps_strcasecmp(cache->name, name)) - return fz_keep_font(cache->font); - return NULL; -} - -static void -xps_insert_font(xps_context *ctx, char *name, fz_font *font) -{ - xps_font_cache *cache = fz_malloc(sizeof(xps_font_cache)); - cache->name = fz_strdup(name); - cache->font = fz_keep_font(font); - cache->next = ctx->font_table; - ctx->font_table = cache; -} - -/* - * Some fonts in XPS are obfuscated by XOR:ing the first 32 bytes of the - * data with the GUID in the fontname. - */ -static void -xps_deobfuscate_font_resource(xps_context *ctx, xps_part *part) -{ - byte buf[33]; - byte key[16]; - char *p; - int i; - - p = strrchr(part->name, '/'); - if (!p) - p = part->name; - - for (i = 0; i < 32 && *p; p++) - { - if (ishex(*p)) - buf[i++] = *p; - } - buf[i] = 0; - - if (i != 32) - { - fz_warn("cannot extract GUID from obfuscated font part name"); - return; - } - - for (i = 0; i < 16; i++) - key[i] = unhex(buf[i*2+0]) * 16 + unhex(buf[i*2+1]); - - for (i = 0; i < 16; i++) - { - part->data[i] ^= key[15-i]; - part->data[i+16] ^= key[15-i]; - } -} - -static void -xps_select_best_font_encoding(fz_font *font) -{ - static struct { int pid, eid; } xps_cmap_list[] = - { - { 3, 10 }, /* Unicode with surrogates */ - { 3, 1 }, /* Unicode without surrogates */ - { 3, 5 }, /* Wansung */ - { 3, 4 }, /* Big5 */ - { 3, 3 }, /* Prc */ - { 3, 2 }, /* ShiftJis */ - { 3, 0 }, /* Symbol */ - // { 0, * }, -- Unicode (deprecated) - { 1, 0 }, - { -1, -1 }, - }; - - int i, k, n, pid, eid; - - n = xps_count_font_encodings(font); - for (k = 0; xps_cmap_list[k].pid != -1; k++) - { - for (i = 0; i < n; i++) - { - xps_identify_font_encoding(font, i, &pid, &eid); - if (pid == xps_cmap_list[k].pid && eid == xps_cmap_list[k].eid) - { - xps_select_font_encoding(font, i); - return; - } - } - } - - fz_warn("cannot find a suitable cmap"); -} - -/* - * Parse and draw an XPS element. - * - * Indices syntax: - - GlyphIndices = GlyphMapping ( ";" GlyphMapping ) - GlyphMapping = ( [ClusterMapping] GlyphIndex ) [GlyphMetrics] - ClusterMapping = "(" ClusterCodeUnitCount [":" ClusterGlyphCount] ")" - ClusterCodeUnitCount = * DIGIT - ClusterGlyphCount = * DIGIT - GlyphIndex = * DIGIT - GlyphMetrics = "," AdvanceWidth ["," uOffset ["," vOffset]] - AdvanceWidth = ["+"] RealNum - uOffset = ["+" | "-"] RealNum - vOffset = ["+" | "-"] RealNum - RealNum = ((DIGIT ["." DIGIT]) | ("." DIGIT)) [Exponent] - Exponent = ( ("E"|"e") ("+"|"-") DIGIT ) - - */ - -static char * -xps_parse_digits(char *s, int *digit) -{ - *digit = 0; - while (*s >= '0' && *s <= '9') - { - *digit = *digit * 10 + (*s - '0'); - s ++; - } - return s; -} - -static inline int is_real_num_char(int c) -{ - return (c >= '0' && c <= '9') || - c == 'e' || c == 'E' || c == '+' || c == '-' || c == '.'; -} - -static char * -xps_parse_real_num(char *s, float *number) -{ - char buf[64]; - char *p = buf; - while (is_real_num_char(*s)) - *p++ = *s++; - *p = 0; - if (buf[0]) - *number = fz_atof(buf); - return s; -} - -static char * -xps_parse_cluster_mapping(char *s, int *code_count, int *glyph_count) -{ - if (*s == '(') - s = xps_parse_digits(s + 1, code_count); - if (*s == ':') - s = xps_parse_digits(s + 1, glyph_count); - if (*s == ')') - s ++; - return s; -} - -static char * -xps_parse_glyph_index(char *s, int *glyph_index) -{ - if (*s >= '0' && *s <= '9') - s = xps_parse_digits(s, glyph_index); - return s; -} - -static char * -xps_parse_glyph_metrics(char *s, float *advance, float *uofs, float *vofs) -{ - if (*s == ',') - s = xps_parse_real_num(s + 1, advance); - if (*s == ',') - s = xps_parse_real_num(s + 1, uofs); - if (*s == ',') - s = xps_parse_real_num(s + 1, vofs); - return s; -} - -/* - * Parse unicode and indices strings and encode glyphs. - * Calculate metrics for positioning. - */ -static fz_text * -xps_parse_glyphs_imp(xps_context *ctx, fz_matrix ctm, - fz_font *font, float size, float originx, float originy, - int is_sideways, int bidi_level, - char *indices, char *unicode) -{ - xps_glyph_metrics mtx; - fz_text *text; - fz_matrix tm; - float e, f; - float x = originx; - float y = originy; - char *us = unicode; - char *is = indices; - int un = 0; - - if (!unicode && !indices) - fz_warn("glyphs element with neither characters nor indices"); - - if (us) - { - if (us[0] == '{' && us[1] == '}') - us = us + 2; - un = strlen(us); - } - - if (is_sideways) - tm = fz_concat(fz_scale(-size, size), fz_rotate(90)); - else - tm = fz_scale(size, -size); - - text = fz_new_text(font, tm, is_sideways); - - while ((us && un > 0) || (is && *is)) - { - int char_code = '?'; - int code_count = 1; - int glyph_count = 1; - - if (is && *is) - { - is = xps_parse_cluster_mapping(is, &code_count, &glyph_count); - } - - if (code_count < 1) - code_count = 1; - if (glyph_count < 1) - glyph_count = 1; - - /* TODO: add code chars with cluster mappings for text extraction */ - - while (code_count--) - { - if (us && un > 0) - { - int t = chartorune(&char_code, us); - us += t; un -= t; - } - } - - while (glyph_count--) - { - int glyph_index = -1; - float u_offset = 0; - float v_offset = 0; - float advance; - - if (is && *is) - is = xps_parse_glyph_index(is, &glyph_index); - - if (glyph_index == -1) - glyph_index = xps_encode_font_char(font, char_code); - - xps_measure_font_glyph(ctx, font, glyph_index, &mtx); - if (is_sideways) - advance = mtx.vadv * 100; - else if (bidi_level & 1) - advance = -mtx.hadv * 100; - else - advance = mtx.hadv * 100; - - if (is && *is) - { - is = xps_parse_glyph_metrics(is, &advance, &u_offset, &v_offset); - if (*is == ';') - is ++; - } - - if (bidi_level & 1) - u_offset = -mtx.hadv * 100 - u_offset; - - u_offset = u_offset * 0.01f * size; - v_offset = v_offset * 0.01f * size; - - if (is_sideways) - { - e = x + u_offset + (mtx.vorg * size); - f = y - v_offset + (mtx.hadv * 0.5f * size); - } - else - { - e = x + u_offset; - f = y - v_offset; - } - - fz_add_text(text, glyph_index, char_code, e, f); - - x += advance * 0.01f * size; - } - } - - return text; -} - -void -xps_parse_glyphs(xps_context *ctx, fz_matrix ctm, - char *base_uri, xps_resource *dict, xml_element *root) -{ - xml_element *node; - int code; - - char *fill_uri; - char *opacity_mask_uri; - - char *bidi_level_att; - char *caret_stops_att; - char *fill_att; - char *font_size_att; - char *font_uri_att; - char *origin_x_att; - char *origin_y_att; - char *is_sideways_att; - char *indices_att; - char *unicode_att; - char *style_att; - char *transform_att; - char *clip_att; - char *opacity_att; - char *opacity_mask_att; - - xml_element *transform_tag = NULL; - xml_element *clip_tag = NULL; - xml_element *fill_tag = NULL; - xml_element *opacity_mask_tag = NULL; - - char *fill_opacity_att = NULL; - - xps_part *part; - fz_font *font; - - char partname[1024]; - char *subfont; - - float font_size = 10; - int subfontid = 0; - int is_sideways = 0; - int bidi_level = 0; - - fz_text *text; - fz_rect area; - - /* - * Extract attributes and extended attributes. - */ - - bidi_level_att = xml_att(root, "BidiLevel"); - caret_stops_att = xml_att(root, "CaretStops"); - fill_att = xml_att(root, "Fill"); - font_size_att = xml_att(root, "FontRenderingEmSize"); - font_uri_att = xml_att(root, "FontUri"); - origin_x_att = xml_att(root, "OriginX"); - origin_y_att = xml_att(root, "OriginY"); - is_sideways_att = xml_att(root, "IsSideways"); - indices_att = xml_att(root, "Indices"); - unicode_att = xml_att(root, "UnicodeString"); - style_att = xml_att(root, "StyleSimulations"); - transform_att = xml_att(root, "RenderTransform"); - clip_att = xml_att(root, "Clip"); - opacity_att = xml_att(root, "Opacity"); - opacity_mask_att = xml_att(root, "OpacityMask"); - - for (node = xml_down(root); node; node = xml_next(node)) - { - if (!strcmp(xml_tag(node), "Glyphs.RenderTransform")) - transform_tag = xml_down(node); - if (!strcmp(xml_tag(node), "Glyphs.OpacityMask")) - opacity_mask_tag = xml_down(node); - if (!strcmp(xml_tag(node), "Glyphs.Clip")) - clip_tag = xml_down(node); - if (!strcmp(xml_tag(node), "Glyphs.Fill")) - fill_tag = xml_down(node); - } - - fill_uri = base_uri; - opacity_mask_uri = base_uri; - - xps_resolve_resource_reference(ctx, dict, &transform_att, &transform_tag, NULL); - xps_resolve_resource_reference(ctx, dict, &clip_att, &clip_tag, NULL); - xps_resolve_resource_reference(ctx, dict, &fill_att, &fill_tag, &fill_uri); - xps_resolve_resource_reference(ctx, dict, &opacity_mask_att, &opacity_mask_tag, &opacity_mask_uri); - - /* - * Check that we have all the necessary information. - */ - - if (!font_size_att || !font_uri_att || !origin_x_att || !origin_y_att) { - fz_warn("missing attributes in glyphs element"); - return; - } - - if (!indices_att && !unicode_att) - return; /* nothing to draw */ - - if (is_sideways_att) - is_sideways = !strcmp(is_sideways_att, "true"); - - if (bidi_level_att) - bidi_level = atoi(bidi_level_att); - - /* - * Find and load the font resource - */ - - xps_absolute_path(partname, base_uri, font_uri_att, sizeof partname); - subfont = strrchr(partname, '#'); - if (subfont) - { - subfontid = atoi(subfont + 1); - *subfont = 0; - } - - font = xps_lookup_font(ctx, partname); - if (!font) - { - part = xps_read_part(ctx, partname); - if (!part) { - fz_warn("cannot find font resource part '%s'", partname); - return; - } - - /* deobfuscate if necessary */ - if (strstr(part->name, ".odttf")) - xps_deobfuscate_font_resource(ctx, part); - if (strstr(part->name, ".ODTTF")) - xps_deobfuscate_font_resource(ctx, part); - - code = fz_new_font_from_memory(&font, part->data, part->size, subfontid); - if (code) { - fz_catch(code, "cannot load font resource '%s'", partname); - xps_free_part(ctx, part); - return; - } - - xps_select_best_font_encoding(font); - - xps_insert_font(ctx, part->name, font); - - /* NOTE: we keep part->data in the font */ - font->ft_data = part->data; - font->ft_size = part->size; - fz_free(part->name); - fz_free(part); - } - - /* - * Set up graphics state. - */ - - if (transform_att || transform_tag) - { - fz_matrix transform; - 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(transform, ctm); - } - - if (clip_att || clip_tag) - xps_clip(ctx, ctm, dict, clip_att, clip_tag); - - font_size = fz_atof(font_size_att); - - text = xps_parse_glyphs_imp(ctx, ctm, font, font_size, - fz_atof(origin_x_att), fz_atof(origin_y_att), - is_sideways, bidi_level, indices_att, unicode_att); - - area = fz_bound_text(text, ctm); - - xps_begin_opacity(ctx, ctm, area, opacity_mask_uri, dict, opacity_att, opacity_mask_tag); - - /* If it's a solid color brush fill/stroke do a simple fill */ - - if (fill_tag && !strcmp(xml_tag(fill_tag), "SolidColorBrush")) - { - fill_opacity_att = xml_att(fill_tag, "Opacity"); - fill_att = xml_att(fill_tag, "Color"); - fill_tag = NULL; - } - - if (fill_att) - { - float samples[32]; - fz_colorspace *colorspace; - - xps_parse_color(ctx, base_uri, fill_att, &colorspace, samples); - if (fill_opacity_att) - samples[0] = fz_atof(fill_opacity_att); - xps_set_color(ctx, colorspace, samples); - - fz_fill_text(ctx->dev, text, ctm, - ctx->colorspace, ctx->color, ctx->alpha); - } - - /* If it's a complex brush, use the charpath as a clip mask */ - - if (fill_tag) - { - fz_clip_text(ctx->dev, text, ctm, 0); - xps_parse_brush(ctx, ctm, area, fill_uri, dict, fill_tag); - fz_pop_clip(ctx->dev); - } - - xps_end_opacity(ctx, opacity_mask_uri, dict, opacity_att, opacity_mask_tag); - - fz_free_text(text); - - if (clip_att || clip_tag) - fz_pop_clip(ctx->dev); - - fz_drop_font(font); -} diff --git a/contrib/media/updf/xps/xps_gradient.c b/contrib/media/updf/xps/xps_gradient.c deleted file mode 100644 index f73d33fef5..0000000000 --- a/contrib/media/updf/xps/xps_gradient.c +++ /dev/null @@ -1,458 +0,0 @@ -#include "fitz.h" -#include "muxps.h" - -#define MAX_STOPS 256 - -enum { SPREAD_PAD, SPREAD_REPEAT, SPREAD_REFLECT }; - -/* - * Parse a list of GradientStop elements. - * Fill the offset and color arrays, and - * return the number of stops parsed. - */ - -struct stop -{ - float offset; - float r, g, b, a; -}; - -static int cmp_stop(const void *a, const void *b) -{ - const struct stop *astop = a; - const struct stop *bstop = b; - float diff = astop->offset - bstop->offset; - if (diff < 0) - return -1; - if (diff > 0) - return 1; - return 0; -} - -static inline float lerp(float a, float b, float x) -{ - return a + (b - a) * x; -} - -static int -xps_parse_gradient_stops(xps_context *ctx, char *base_uri, xml_element *node, - struct stop *stops, int maxcount) -{ - fz_colorspace *colorspace; - float sample[8]; - float rgb[3]; - int before, after; - int count; - int i; - - /* We may have to insert 2 extra stops when postprocessing */ - maxcount -= 2; - - count = 0; - while (node && count < maxcount) - { - if (!strcmp(xml_tag(node), "GradientStop")) - { - char *offset = xml_att(node, "Offset"); - char *color = xml_att(node, "Color"); - if (offset && color) - { - stops[count].offset = fz_atof(offset); - - xps_parse_color(ctx, base_uri, color, &colorspace, sample); - - fz_convert_color(colorspace, sample + 1, fz_device_rgb, rgb); - - stops[count].r = rgb[0]; - stops[count].g = rgb[1]; - stops[count].b = rgb[2]; - stops[count].a = sample[0]; - - count ++; - } - } - node = xml_next(node); - } - - if (count == 0) - { - fz_warn("gradient brush has no gradient stops"); - stops[0].offset = 0; - stops[0].r = 0; - stops[0].g = 0; - stops[0].b = 0; - stops[0].a = 1; - stops[1].offset = 1; - stops[1].r = 1; - stops[1].g = 1; - stops[1].b = 1; - stops[1].a = 1; - return 2; - } - - if (count == maxcount) - fz_warn("gradient brush exceeded maximum number of gradient stops"); - - /* Postprocess to make sure the range of offsets is 0.0 to 1.0 */ - - qsort(stops, count, sizeof(struct stop), cmp_stop); - - before = -1; - after = -1; - - for (i = 0; i < count; i++) - { - if (stops[i].offset < 0) - before = i; - if (stops[i].offset > 1) - { - after = i; - break; - } - } - - /* Remove all stops < 0 except the largest one */ - if (before > 0) - { - memmove(stops, stops + before, (count - before) * sizeof(struct stop)); - count -= before; - } - - /* Remove all stops > 1 except the smallest one */ - if (after >= 0) - count = after + 1; - - /* Expand single stop to 0 .. 1 */ - if (count == 1) - { - stops[1] = stops[0]; - stops[0].offset = 0; - stops[1].offset = 1; - return 2; - } - - /* First stop < 0 -- interpolate value to 0 */ - if (stops[0].offset < 0) - { - float d = -stops[0].offset / (stops[1].offset - stops[0].offset); - stops[0].offset = 0; - stops[0].r = lerp(stops[0].r, stops[1].r, d); - stops[0].g = lerp(stops[0].g, stops[1].g, d); - stops[0].b = lerp(stops[0].b, stops[1].b, d); - stops[0].a = lerp(stops[0].a, stops[1].a, d); - } - - /* Last stop > 1 -- interpolate value to 1 */ - if (stops[count-1].offset > 1) - { - float d = (1 - stops[count-2].offset) / (stops[count-1].offset - stops[count-2].offset); - stops[count-1].offset = 1; - stops[0].r = lerp(stops[count-2].r, stops[count-1].r, d); - stops[0].g = lerp(stops[count-2].g, stops[count-1].g, d); - stops[0].b = lerp(stops[count-2].b, stops[count-1].b, d); - stops[0].a = lerp(stops[count-2].a, stops[count-1].a, d); - } - - /* First stop > 0 -- insert a duplicate at 0 */ - if (stops[0].offset > 0) - { - memmove(stops + 1, stops, count * sizeof(struct stop)); - stops[0] = stops[1]; - stops[0].offset = 0; - count++; - } - - /* Last stop < 1 -- insert a duplicate at 1 */ - if (stops[count-1].offset < 1) - { - stops[count] = stops[count-1]; - stops[count].offset = 1; - count++; - } - - return count; -} - -static void -xps_sample_gradient_stops(fz_shade *shade, struct stop *stops, int count) -{ - float offset, d; - int i, k; - - k = 0; - for (i = 0; i < 256; i++) - { - offset = i / 255.0f; - while (k + 1 < count && offset > stops[k+1].offset) - k++; - - d = (offset - stops[k].offset) / (stops[k+1].offset - stops[k].offset); - - shade->function[i][0] = lerp(stops[k].r, stops[k+1].r, d); - shade->function[i][1] = lerp(stops[k].g, stops[k+1].g, d); - shade->function[i][2] = lerp(stops[k].b, stops[k+1].b, d); - shade->function[i][3] = lerp(stops[k].a, stops[k+1].a, d); - } -} - -/* - * Radial gradients map more or less to Radial shadings. - * The inner circle is always a point. - * The outer circle is actually an ellipse, - * mess with the transform to squash the circle into the right aspect. - */ - -static void -xps_draw_one_radial_gradient(xps_context *ctx, fz_matrix ctm, - struct stop *stops, int count, - int extend, - float x0, float y0, float r0, - float x1, float y1, float r1) -{ - fz_shade *shade; - - /* TODO: this (and the stuff in pdf_shade) should move to res_shade.c */ - shade = fz_malloc(sizeof(fz_shade)); - shade->refs = 1; - shade->colorspace = fz_device_rgb; - shade->bbox = fz_infinite_rect; - shade->matrix = fz_identity; - shade->use_background = 0; - shade->use_function = 1; - shade->type = FZ_RADIAL; - shade->extend[0] = extend; - shade->extend[1] = extend; - - xps_sample_gradient_stops(shade, stops, count); - - shade->mesh_len = 6; - shade->mesh_cap = 6; - shade->mesh = fz_calloc(shade->mesh_cap, sizeof(float)); - shade->mesh[0] = x0; - shade->mesh[1] = y0; - shade->mesh[2] = r0; - shade->mesh[3] = x1; - shade->mesh[4] = y1; - shade->mesh[5] = r1; - - fz_fill_shade(ctx->dev, shade, ctm, 1); - - fz_drop_shade(shade); -} - -/* - * Linear gradients map to Axial shadings. - */ - -static void -xps_draw_one_linear_gradient(xps_context *ctx, fz_matrix ctm, - struct stop *stops, int count, - int extend, - float x0, float y0, float x1, float y1) -{ - fz_shade *shade; - - /* TODO: this (and the stuff in pdf_shade) should move to res_shade.c */ - shade = fz_malloc(sizeof(fz_shade)); - shade->refs = 1; - shade->colorspace = fz_device_rgb; - shade->bbox = fz_infinite_rect; - shade->matrix = fz_identity; - shade->use_background = 0; - shade->use_function = 1; - shade->type = FZ_LINEAR; - shade->extend[0] = extend; - shade->extend[1] = extend; - - xps_sample_gradient_stops(shade, stops, count); - - shade->mesh_len = 6; - shade->mesh_cap = 6; - shade->mesh = fz_calloc(shade->mesh_cap, sizeof(float)); - shade->mesh[0] = x0; - shade->mesh[1] = y0; - shade->mesh[2] = 0; - shade->mesh[3] = x1; - shade->mesh[4] = y1; - shade->mesh[5] = 0; - - fz_fill_shade(ctx->dev, shade, ctm, 1); - - fz_drop_shade(shade); -} - -/* - * We need to loop and create many shading objects to account - * for the Repeat and Reflect SpreadMethods. - * I'm not smart enough to calculate this analytically - * so we iterate and check each object until we - * reach a reasonable limit for infinite cases. - */ - -static inline float point_inside_circle(float px, float py, float x, float y, float r) -{ - float dx = px - x; - float dy = py - y; - return dx * dx + dy * dy <= r * r; -} - -static void -xps_draw_radial_gradient(xps_context *ctx, fz_matrix ctm, - struct stop *stops, int count, - xml_element *root, int spread) -{ - float x0, y0, r0; - float x1, y1, r1; - float xrad = 1; - float yrad = 1; - float invscale; - - char *center_att = xml_att(root, "Center"); - char *origin_att = xml_att(root, "GradientOrigin"); - char *radius_x_att = xml_att(root, "RadiusX"); - char *radius_y_att = xml_att(root, "RadiusY"); - - if (origin_att) - sscanf(origin_att, "%g,%g", &x0, &y0); - if (center_att) - sscanf(center_att, "%g,%g", &x1, &y1); - if (radius_x_att) - xrad = fz_atof(radius_x_att); - if (radius_y_att) - yrad = fz_atof(radius_y_att); - - /* scale the ctm to make ellipses */ - ctm = fz_concat(fz_scale(1, yrad / xrad), ctm); - - invscale = xrad / yrad; - y0 = y0 * invscale; - y1 = y1 * invscale; - - r0 = 0; - r1 = xrad; - - xps_draw_one_radial_gradient(ctx, ctm, stops, count, 1, x0, y0, r0, x1, y1, r1); -} - -/* - * Calculate how many iterations are needed to cover - * the bounding box. - */ - -static void -xps_draw_linear_gradient(xps_context *ctx, fz_matrix ctm, - struct stop *stops, int count, - xml_element *root, int spread) -{ - float x0, y0, x1, y1; - - char *start_point_att = xml_att(root, "StartPoint"); - char *end_point_att = xml_att(root, "EndPoint"); - - x0 = y0 = 0; - x1 = y1 = 1; - - if (start_point_att) - sscanf(start_point_att, "%g,%g", &x0, &y0); - if (end_point_att) - sscanf(end_point_att, "%g,%g", &x1, &y1); - - xps_draw_one_linear_gradient(ctx, ctm, stops, count, 1, x0, y0, x1, y1); -} - -/* - * Parse XML tag and attributes for a gradient brush, create color/opacity - * function objects and call gradient drawing primitives. - */ - -static void -xps_parse_gradient_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, - char *base_uri, xps_resource *dict, xml_element *root, - void (*draw)(xps_context *, fz_matrix, struct stop *, int, xml_element *, int)) -{ - xml_element *node; - - char *opacity_att; - char *interpolation_att; - char *spread_att; - char *mapping_att; - char *transform_att; - - xml_element *transform_tag = NULL; - xml_element *stop_tag = NULL; - - struct stop stop_list[MAX_STOPS]; - int stop_count; - fz_matrix transform; - int spread_method; - - opacity_att = xml_att(root, "Opacity"); - interpolation_att = xml_att(root, "ColorInterpolationMode"); - spread_att = xml_att(root, "SpreadMethod"); - mapping_att = xml_att(root, "MappingMode"); - transform_att = xml_att(root, "Transform"); - - for (node = xml_down(root); node; node = xml_next(node)) - { - if (!strcmp(xml_tag(node), "LinearGradientBrush.Transform")) - transform_tag = xml_down(node); - if (!strcmp(xml_tag(node), "RadialGradientBrush.Transform")) - transform_tag = xml_down(node); - if (!strcmp(xml_tag(node), "LinearGradientBrush.GradientStops")) - stop_tag = xml_down(node); - if (!strcmp(xml_tag(node), "RadialGradientBrush.GradientStops")) - stop_tag = xml_down(node); - } - - xps_resolve_resource_reference(ctx, dict, &transform_att, &transform_tag, NULL); - - spread_method = SPREAD_PAD; - if (spread_att) - { - if (!strcmp(spread_att, "Pad")) - spread_method = SPREAD_PAD; - if (!strcmp(spread_att, "Reflect")) - spread_method = SPREAD_REFLECT; - if (!strcmp(spread_att, "Repeat")) - spread_method = SPREAD_REPEAT; - } - - 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(transform, ctm); - - if (!stop_tag) { - fz_warn("missing gradient stops tag"); - return; - } - - stop_count = xps_parse_gradient_stops(ctx, base_uri, stop_tag, stop_list, MAX_STOPS); - if (stop_count == 0) - { - fz_warn("no gradient stops found"); - return; - } - - xps_begin_opacity(ctx, ctm, area, base_uri, dict, opacity_att, NULL); - - draw(ctx, ctm, stop_list, stop_count, root, spread_method); - - xps_end_opacity(ctx, base_uri, dict, opacity_att, NULL); -} - -void -xps_parse_linear_gradient_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, - char *base_uri, xps_resource *dict, xml_element *root) -{ - xps_parse_gradient_brush(ctx, ctm, area, base_uri, dict, root, xps_draw_linear_gradient); -} - -void -xps_parse_radial_gradient_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, - char *base_uri, xps_resource *dict, xml_element *root) -{ - xps_parse_gradient_brush(ctx, ctm, area, base_uri, dict, root, xps_draw_radial_gradient); -} diff --git a/contrib/media/updf/xps/xps_image.c b/contrib/media/updf/xps/xps_image.c deleted file mode 100644 index 4a34743523..0000000000 --- a/contrib/media/updf/xps/xps_image.c +++ /dev/null @@ -1,128 +0,0 @@ -#include "fitz.h" -#include "muxps.h" - -static int -xps_decode_image(fz_pixmap **imagep, byte *buf, int len) -{ - int error; - - if (len < 8) - return fz_throw("unknown image file format"); - - if (buf[0] == 0xff && buf[1] == 0xd8) - { - error = xps_decode_jpeg(imagep, buf, len); - if (error) - return fz_rethrow(error, "cannot decode jpeg image"); - } - else if (memcmp(buf, "\211PNG\r\n\032\n", 8) == 0) - { - error = xps_decode_png(imagep, buf, len); - if (error) - return fz_rethrow(error, "cannot decode png image"); - } - else if (memcmp(buf, "II", 2) == 0 && buf[2] == 0xBC) - { - return fz_throw("JPEG-XR codec is not available"); - } - else if (memcmp(buf, "MM", 2) == 0 || memcmp(buf, "II", 2) == 0) - { - error = xps_decode_tiff(imagep, buf, len); - if (error) - return fz_rethrow(error, "cannot decode TIFF image"); - } - else - return fz_throw("unknown image file format"); - - return fz_okay; -} - -static void -xps_paint_image_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, - xml_element *root, void *vimage) -{ - fz_pixmap *pixmap = vimage; - float xs = pixmap->w * 96 / pixmap->xres; - float ys = pixmap->h * 96 / pixmap->yres; - fz_matrix im = fz_scale(xs, -ys); - im.f = ys; - ctm = fz_concat(im, ctm); - fz_fill_image(ctx->dev, pixmap, ctm, ctx->opacity[ctx->opacity_top]); -} - -static xps_part * -xps_find_image_brush_source_part(xps_context *ctx, char *base_uri, xml_element *root) -{ - char *image_source_att; - char buf[1024]; - char partname[1024]; - char *image_name; - char *profile_name; - char *p; - - image_source_att = xml_att(root, "ImageSource"); - if (!image_source_att) - return NULL; - - /* "{ColorConvertedBitmap /Resources/Image.tiff /Resources/Profile.icc}" */ - if (strstr(image_source_att, "{ColorConvertedBitmap") == image_source_att) - { - image_name = NULL; - profile_name = NULL; - - fz_strlcpy(buf, image_source_att, sizeof buf); - p = strchr(buf, ' '); - if (p) - { - image_name = p + 1; - p = strchr(p + 1, ' '); - if (p) - { - *p = 0; - profile_name = p + 1; - p = strchr(p + 1, '}'); - if (p) - *p = 0; - } - } - } - else - { - image_name = image_source_att; - profile_name = NULL; - } - - if (!image_name) - return NULL; - - xps_absolute_path(partname, base_uri, image_name, sizeof partname); - - return xps_read_part(ctx, partname); -} - -void -xps_parse_image_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, - char *base_uri, xps_resource *dict, xml_element *root) -{ - xps_part *part; - fz_pixmap *image; - int code; - - part = xps_find_image_brush_source_part(ctx, base_uri, root); - if (!part) { - fz_warn("cannot find image source"); - return; - } - - code = xps_decode_image(&image, part->data, part->size); - if (code < 0) { - xps_free_part(ctx, part); - fz_catch(-1, "cannot decode image resource"); - return; - } - - xps_parse_tiling_brush(ctx, ctm, area, base_uri, dict, root, xps_paint_image_brush, image); - - fz_drop_pixmap(image); - xps_free_part(ctx, part); -} diff --git a/contrib/media/updf/xps/xps_jpeg.c b/contrib/media/updf/xps/xps_jpeg.c deleted file mode 100644 index 68bb5eb98b..0000000000 --- a/contrib/media/updf/xps/xps_jpeg.c +++ /dev/null @@ -1,138 +0,0 @@ -#include "fitz.h" -#include "muxps.h" - -#include -#include - -struct jpeg_error_mgr_jmp -{ - struct jpeg_error_mgr super; - jmp_buf env; - char msg[JMSG_LENGTH_MAX]; -}; - -static void error_exit(j_common_ptr cinfo) -{ - struct jpeg_error_mgr_jmp *err = (struct jpeg_error_mgr_jmp *)cinfo->err; - cinfo->err->format_message(cinfo, err->msg); - longjmp(err->env, 1); -} - -static void init_source(j_decompress_ptr cinfo) -{ - /* nothing to do */ -} - -static void term_source(j_decompress_ptr cinfo) -{ - /* nothing to do */ -} - -static boolean fill_input_buffer(j_decompress_ptr cinfo) -{ - static unsigned char eoi[2] = { 0xFF, JPEG_EOI }; - struct jpeg_source_mgr *src = cinfo->src; - src->next_input_byte = eoi; - src->bytes_in_buffer = 2; - return 1; -} - -static void skip_input_data(j_decompress_ptr cinfo, long num_bytes) -{ - struct jpeg_source_mgr *src = cinfo->src; - if (num_bytes > 0) - { - src->next_input_byte += num_bytes; - src->bytes_in_buffer -= num_bytes; - } -} - -int -xps_decode_jpeg(fz_pixmap **imagep, byte *rbuf, int rlen) -{ - struct jpeg_decompress_struct cinfo; - struct jpeg_error_mgr_jmp err; - struct jpeg_source_mgr src; - unsigned char *row[1], *sp, *dp; - fz_colorspace *colorspace; - unsigned int x; - int k; - - fz_pixmap *image = NULL; - - if (setjmp(err.env)) - { - if (image) - fz_drop_pixmap(image); - return fz_throw("jpeg error: %s", err.msg); - } - - cinfo.err = jpeg_std_error(&err.super); - err.super.error_exit = error_exit; - - jpeg_create_decompress(&cinfo); - - cinfo.src = &src; - src.init_source = init_source; - src.fill_input_buffer = fill_input_buffer; - src.skip_input_data = skip_input_data; - src.resync_to_restart = jpeg_resync_to_restart; - src.term_source = term_source; - src.next_input_byte = rbuf; - src.bytes_in_buffer = rlen; - - jpeg_read_header(&cinfo, 1); - - jpeg_start_decompress(&cinfo); - - if (cinfo.output_components == 1) - colorspace = fz_device_gray; - else if (cinfo.output_components == 3) - colorspace = fz_device_rgb; - else if (cinfo.output_components == 4) - colorspace = fz_device_cmyk; - else - return fz_throw("bad number of components in jpeg: %d", cinfo.output_components); - - image = fz_new_pixmap_with_limit(colorspace, cinfo.output_width, cinfo.output_height); - if (!image) - { - jpeg_finish_decompress(&cinfo); - jpeg_destroy_decompress(&cinfo); - return fz_throw("out of memory"); - } - - if (cinfo.density_unit == 1) - { - image->xres = cinfo.X_density; - image->yres = cinfo.Y_density; - } - else if (cinfo.density_unit == 2) - { - image->xres = cinfo.X_density * 254 / 100; - image->yres = cinfo.Y_density * 254 / 100; - } - - fz_clear_pixmap(image); - - row[0] = fz_malloc(cinfo.output_components * cinfo.output_width); - dp = image->samples; - while (cinfo.output_scanline < cinfo.output_height) - { - jpeg_read_scanlines(&cinfo, row, 1); - sp = row[0]; - for (x = 0; x < cinfo.output_width; x++) - { - for (k = 0; k < cinfo.output_components; k++) - *dp++ = *sp++; - *dp++ = 255; - } - } - fz_free(row[0]); - - jpeg_finish_decompress(&cinfo); - jpeg_destroy_decompress(&cinfo); - - *imagep = image; - return fz_okay; -} diff --git a/contrib/media/updf/xps/xps_path.c b/contrib/media/updf/xps/xps_path.c deleted file mode 100644 index 335262621d..0000000000 --- a/contrib/media/updf/xps/xps_path.c +++ /dev/null @@ -1,990 +0,0 @@ -#include "fitz.h" -#include "muxps.h" - -static fz_point -fz_currentpoint(fz_path *path) -{ - fz_point c, m; - int i; - - c.x = c.y = m.x = m.y = 0; - i = 0; - - while (i < path->len) - { - switch (path->items[i++].k) - { - case FZ_MOVETO: - m.x = c.x = path->items[i++].v; - m.y = c.y = path->items[i++].v; - break; - case FZ_LINETO: - c.x = path->items[i++].v; - c.y = path->items[i++].v; - break; - case FZ_CURVETO: - i += 4; - c.x = path->items[i++].v; - c.y = path->items[i++].v; - break; - case FZ_CLOSE_PATH: - c = m; - } - } - - return c; -} - -/* Draw an arc segment transformed by the matrix, we approximate with straight - * 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 void -xps_draw_arc_segment(fz_path *path, fz_matrix mtx, float th0, float th1, int iscw) -{ - float t, d; - fz_point p; - - while (th1 < th0) - th1 += (float)M_PI * 2; - - d = (float)M_PI / 180; /* 1-degree precision */ - - if (iscw) - { - p.x = cosf(th0); - p.y = sinf(th0); - p = fz_transform_point(mtx, p); - fz_lineto(path, p.x, p.y); - for (t = th0; t < th1; t += d) - { - p.x = cosf(t); - p.y = sinf(t); - p = fz_transform_point(mtx, p); - fz_lineto(path, p.x, p.y); - } - p.x = cosf(th1); - p.y = sinf(th1); - p = fz_transform_point(mtx, p); - fz_lineto(path, p.x, p.y); - } - else - { - th0 += (float)M_PI * 2; - p.x = cosf(th0); - p.y = sinf(th0); - p = fz_transform_point(mtx, p); - fz_lineto(path, p.x, p.y); - for (t = th0; t > th1; t -= d) - { - p.x = cosf(t); - p.y = sinf(t); - p = fz_transform_point(mtx, p); - fz_lineto(path, p.x, p.y); - } - p.x = cosf(th1); - p.y = sinf(th1); - p = fz_transform_point(mtx, p); - fz_lineto(path, p.x, p.y); - } -} - -/* Given two vectors find the angle between them. */ -static float -angle_between(const fz_point u, const fz_point v) -{ - float det = u.x * v.y - u.y * v.x; - float sign = (det < 0 ? -1 : 1); - float magu = u.x * u.x + u.y * u.y; - float magv = v.x * v.x + v.y * v.y; - float udotv = u.x * v.x + u.y * v.y; - float t = udotv / (magu * magv); - /* guard against rounding errors when near |1| (where acos will return NaN) */ - if (t < -1) t = -1; - if (t > 1) t = 1; - return sign * acosf(t); -} - -static void -xps_draw_arc(fz_path *path, - float size_x, float size_y, float rotation_angle, - int is_large_arc, int is_clockwise, - float point_x, float point_y) -{ - fz_matrix rotmat, revmat; - fz_matrix mtx; - fz_point pt; - float rx, ry; - float x1, y1, x2, y2; - float x1t, y1t; - float cxt, cyt, cx, cy; - float t1, t2, t3; - float sign; - float th1, dth; - - pt = fz_currentpoint(path); - x1 = pt.x; - y1 = pt.y; - x2 = point_x; - y2 = point_y; - rx = size_x; - ry = size_y; - - if (is_clockwise != is_large_arc) - sign = 1; - else - sign = -1; - - 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 */ - - /* F.6.6.1 -- ensure radii are positive and non-zero */ - rx = fabsf(rx); - ry = fabsf(ry); - if (rx < 0.001f || ry < 0.001f) - { - fz_lineto(path, x2, y2); - return; - } - - /* F.6.5.1 */ - pt.x = (x1 - x2) / 2; - pt.y = (y1 - y2) / 2; - pt = fz_transform_vector(revmat, pt); - x1t = pt.x; - y1t = pt.y; - - /* F.6.6.2 -- ensure radii are large enough */ - t1 = (x1t * x1t) / (rx * rx) + (y1t * y1t) / (ry * ry); - if (t1 > 1) - { - rx = rx * sqrtf(t1); - ry = ry * sqrtf(t1); - } - - /* F.6.5.2 */ - t1 = (rx * rx * ry * ry) - (rx * rx * y1t * y1t) - (ry * ry * x1t * x1t); - t2 = (rx * rx * y1t * y1t) + (ry * ry * x1t * x1t); - t3 = t1 / t2; - /* guard against rounding errors; sqrt of negative numbers is bad for your health */ - if (t3 < 0) t3 = 0; - t3 = sqrtf(t3); - - cxt = sign * t3 * (rx * y1t) / ry; - cyt = sign * t3 * -(ry * x1t) / rx; - - /* F.6.5.3 */ - pt.x = cxt; - pt.y = cyt; - pt = fz_transform_vector(rotmat, pt); - cx = pt.x + (x1 + x2) / 2; - cy = pt.y + (y1 + y2) / 2; - - /* F.6.5.4 */ - { - fz_point coord1, coord2, coord3, coord4; - coord1.x = 1; - coord1.y = 0; - coord2.x = (x1t - cxt) / rx; - coord2.y = (y1t - cyt) / ry; - coord3.x = (x1t - cxt) / rx; - coord3.y = (y1t - cyt) / ry; - coord4.x = (-x1t - cxt) / rx; - coord4.y = (-y1t - cyt) / ry; - th1 = angle_between(coord1, coord2); - dth = angle_between(coord3, coord4); - if (dth < 0 && !is_clockwise) - dth += (((float)M_PI / 180) * 360); - if (dth > 0 && is_clockwise) - dth -= (((float)M_PI / 180) * 360); - } - - mtx = fz_identity; - mtx = fz_concat(fz_translate(cx, cy), mtx); - mtx = fz_concat(fz_rotate(rotation_angle), mtx); - mtx = fz_concat(fz_scale(rx, ry), mtx); - xps_draw_arc_segment(path, mtx, th1, th1 + dth, is_clockwise); - - fz_lineto(path, point_x, point_y); -} - -/* - * Parse an abbreviated geometry string, and call - * ghostscript moveto/lineto/curveto functions to - * build up a path. - */ - -static fz_path * -xps_parse_abbreviated_geometry(xps_context *ctx, char *geom, int *fill_rule) -{ - fz_path *path; - char **args; - char **pargs; - char *s = geom; - 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; - - path = fz_new_path(); - - args = fz_calloc(strlen(geom) + 1, sizeof(char*)); - pargs = args; - - while (*s) - { - if ((*s >= 'A' && *s <= 'Z') || (*s >= 'a' && *s <= 'z')) - { - *pargs++ = s++; - } - else if ((*s >= '0' && *s <= '9') || *s == '.' || *s == '+' || *s == '-' || *s == 'e' || *s == 'E') - { - *pargs++ = s; - while ((*s >= '0' && *s <= '9') || *s == '.' || *s == '+' || *s == '-' || *s == 'e' || *s == 'E') - s ++; - } - else - { - s++; - } - } - - pargs[0] = s; - pargs[1] = 0; - - n = pargs - args; - i = 0; - - old = 0; - - reset_smooth = 1; - smooth_x = 0; - smooth_y = 0; - - while (i < n) - { - cmd = args[i][0]; - if (cmd == '+' || cmd == '.' || cmd == '-' || (cmd >= '0' && cmd <= '9')) - cmd = old; /* it's a number, repeat old command */ - else - i ++; - - if (reset_smooth) - { - smooth_x = 0; - smooth_y = 0; - } - - reset_smooth = 1; - - switch (cmd) - { - case 'F': - *fill_rule = atoi(args[i]); - i ++; - break; - - case 'M': - fz_moveto(path, fz_atof(args[i]), fz_atof(args[i+1])); - i += 2; - break; - case 'm': - pt = fz_currentpoint(path); - fz_moveto(path, pt.x + fz_atof(args[i]), pt.y + fz_atof(args[i+1])); - i += 2; - break; - - case 'L': - fz_lineto(path, fz_atof(args[i]), fz_atof(args[i+1])); - i += 2; - break; - case 'l': - pt = fz_currentpoint(path); - fz_lineto(path, pt.x + fz_atof(args[i]), pt.y + fz_atof(args[i+1])); - i += 2; - break; - - case 'H': - pt = fz_currentpoint(path); - fz_lineto(path, fz_atof(args[i]), pt.y); - i += 1; - break; - case 'h': - pt = fz_currentpoint(path); - fz_lineto(path, pt.x + fz_atof(args[i]), pt.y); - i += 1; - break; - - case 'V': - pt = fz_currentpoint(path); - fz_lineto(path, pt.x, fz_atof(args[i])); - i += 1; - break; - case 'v': - pt = fz_currentpoint(path); - fz_lineto(path, pt.x, pt.y + fz_atof(args[i])); - i += 1; - break; - - case 'C': - x1 = fz_atof(args[i+0]); - y1 = fz_atof(args[i+1]); - x2 = fz_atof(args[i+2]); - y2 = fz_atof(args[i+3]); - x3 = fz_atof(args[i+4]); - y3 = fz_atof(args[i+5]); - fz_curveto(path, x1, y1, x2, y2, x3, y3); - i += 6; - reset_smooth = 0; - smooth_x = x3 - x2; - smooth_y = y3 - y2; - break; - - case 'c': - pt = fz_currentpoint(path); - x1 = fz_atof(args[i+0]) + pt.x; - y1 = fz_atof(args[i+1]) + pt.y; - x2 = fz_atof(args[i+2]) + pt.x; - y2 = fz_atof(args[i+3]) + pt.y; - x3 = fz_atof(args[i+4]) + pt.x; - y3 = fz_atof(args[i+5]) + pt.y; - fz_curveto(path, x1, y1, x2, y2, x3, y3); - i += 6; - reset_smooth = 0; - smooth_x = x3 - x2; - smooth_y = y3 - y2; - break; - - case 'S': - pt = fz_currentpoint(path); - x1 = fz_atof(args[i+0]); - y1 = fz_atof(args[i+1]); - x2 = fz_atof(args[i+2]); - y2 = fz_atof(args[i+3]); - fz_curveto(path, pt.x + smooth_x, pt.y + smooth_y, x1, y1, x2, y2); - i += 4; - reset_smooth = 0; - smooth_x = x2 - x1; - smooth_y = y2 - y1; - break; - - case 's': - pt = fz_currentpoint(path); - x1 = fz_atof(args[i+0]) + pt.x; - y1 = fz_atof(args[i+1]) + pt.y; - x2 = fz_atof(args[i+2]) + pt.x; - y2 = fz_atof(args[i+3]) + pt.y; - fz_curveto(path, pt.x + smooth_x, pt.y + smooth_y, x1, y1, x2, y2); - i += 4; - reset_smooth = 0; - smooth_x = x2 - x1; - smooth_y = y2 - y1; - break; - - case 'Q': - pt = fz_currentpoint(path); - x1 = fz_atof(args[i+0]); - y1 = fz_atof(args[i+1]); - x2 = fz_atof(args[i+2]); - y2 = fz_atof(args[i+3]); - fz_curveto(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': - pt = fz_currentpoint(path); - x1 = fz_atof(args[i+0]) + pt.x; - y1 = fz_atof(args[i+1]) + pt.y; - x2 = fz_atof(args[i+2]) + pt.x; - y2 = fz_atof(args[i+3]) + pt.y; - fz_curveto(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 'A': - xps_draw_arc(path, - fz_atof(args[i+0]), fz_atof(args[i+1]), fz_atof(args[i+2]), - atoi(args[i+3]), atoi(args[i+4]), - fz_atof(args[i+5]), fz_atof(args[i+6])); - i += 7; - break; - case 'a': - pt = fz_currentpoint(path); - xps_draw_arc(path, - fz_atof(args[i+0]), fz_atof(args[i+1]), fz_atof(args[i+2]), - atoi(args[i+3]), atoi(args[i+4]), - fz_atof(args[i+5]) + pt.x, fz_atof(args[i+6]) + pt.y); - i += 7; - break; - - case 'Z': - case 'z': - fz_closepath(path); - break; - - default: - /* eek */ - break; - } - - old = cmd; - } - - fz_free(args); - return path; -} - -static void -xps_parse_arc_segment(fz_path *path, xml_element *root, int stroking, int *skipped_stroke) -{ - /* ArcSegment pretty much follows the SVG algorithm for converting an - * arc in endpoint representation to an arc in centerpoint - * representation. Once in centerpoint it can be given to the - * graphics library in the form of a postscript arc. */ - - float rotation_angle; - int is_large_arc, is_clockwise; - float point_x, point_y; - float size_x, size_y; - int is_stroked; - - char *point_att = xml_att(root, "Point"); - char *size_att = xml_att(root, "Size"); - char *rotation_angle_att = xml_att(root, "RotationAngle"); - char *is_large_arc_att = xml_att(root, "IsLargeArc"); - char *sweep_direction_att = xml_att(root, "SweepDirection"); - char *is_stroked_att = xml_att(root, "IsStroked"); - - if (!point_att || !size_att || !rotation_angle_att || !is_large_arc_att || !sweep_direction_att) - { - fz_warn("ArcSegment element is missing attributes"); - return; - } - - is_stroked = 1; - if (is_stroked_att && !strcmp(is_stroked_att, "false")) - is_stroked = 0; - if (!is_stroked) - *skipped_stroke = 1; - - sscanf(point_att, "%g,%g", &point_x, &point_y); - sscanf(size_att, "%g,%g", &size_x, &size_y); - rotation_angle = fz_atof(rotation_angle_att); - is_large_arc = !strcmp(is_large_arc_att, "true"); - is_clockwise = !strcmp(sweep_direction_att, "Clockwise"); - - if (stroking && !is_stroked) - { - fz_moveto(path, point_x, point_y); - return; - } - - xps_draw_arc(path, size_x, size_y, rotation_angle, is_large_arc, is_clockwise, point_x, point_y); -} - -static void -xps_parse_poly_quadratic_bezier_segment(fz_path *path, xml_element *root, int stroking, int *skipped_stroke) -{ - char *points_att = xml_att(root, "Points"); - char *is_stroked_att = xml_att(root, "IsStroked"); - float x[2], y[2]; - int is_stroked; - fz_point pt; - char *s; - int n; - - if (!points_att) - { - fz_warn("PolyQuadraticBezierSegment element has no points"); - return; - } - - is_stroked = 1; - if (is_stroked_att && !strcmp(is_stroked_att, "false")) - is_stroked = 0; - if (!is_stroked) - *skipped_stroke = 1; - - s = points_att; - n = 0; - while (*s != 0) - { - while (*s == ' ') s++; - sscanf(s, "%g,%g", &x[n], &y[n]); - while (*s != ' ' && *s != 0) s++; - n ++; - if (n == 2) - { - if (stroking && !is_stroked) - { - fz_moveto(path, x[1], y[1]); - } - else - { - pt = fz_currentpoint(path); - fz_curveto(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]); - } - n = 0; - } - } -} - -static void -xps_parse_poly_bezier_segment(fz_path *path, xml_element *root, int stroking, int *skipped_stroke) -{ - char *points_att = xml_att(root, "Points"); - char *is_stroked_att = xml_att(root, "IsStroked"); - float x[3], y[3]; - int is_stroked; - char *s; - int n; - - if (!points_att) - { - fz_warn("PolyBezierSegment element has no points"); - return; - } - - is_stroked = 1; - if (is_stroked_att && !strcmp(is_stroked_att, "false")) - is_stroked = 0; - if (!is_stroked) - *skipped_stroke = 1; - - s = points_att; - n = 0; - while (*s != 0) - { - while (*s == ' ') s++; - sscanf(s, "%g,%g", &x[n], &y[n]); - while (*s != ' ' && *s != 0) s++; - n ++; - if (n == 3) - { - if (stroking && !is_stroked) - fz_moveto(path, x[2], y[2]); - else - fz_curveto(path, x[0], y[0], x[1], y[1], x[2], y[2]); - n = 0; - } - } -} - -static void -xps_parse_poly_line_segment(fz_path *path, xml_element *root, int stroking, int *skipped_stroke) -{ - char *points_att = xml_att(root, "Points"); - char *is_stroked_att = xml_att(root, "IsStroked"); - int is_stroked; - float x, y; - char *s; - - if (!points_att) - { - fz_warn("PolyLineSegment element has no points"); - return; - } - - is_stroked = 1; - if (is_stroked_att && !strcmp(is_stroked_att, "false")) - is_stroked = 0; - if (!is_stroked) - *skipped_stroke = 1; - - s = points_att; - while (*s != 0) - { - while (*s == ' ') s++; - sscanf(s, "%g,%g", &x, &y); - if (stroking && !is_stroked) - fz_moveto(path, x, y); - else - fz_lineto(path, x, y); - while (*s != ' ' && *s != 0) s++; - } -} - -static void -xps_parse_path_figure(fz_path *path, xml_element *root, int stroking) -{ - xml_element *node; - - char *is_closed_att; - char *start_point_att; - char *is_filled_att; - - int is_closed = 0; - int is_filled = 1; - float start_x = 0; - float start_y = 0; - - int skipped_stroke = 0; - - is_closed_att = xml_att(root, "IsClosed"); - start_point_att = xml_att(root, "StartPoint"); - is_filled_att = xml_att(root, "IsFilled"); - - if (is_closed_att) - is_closed = !strcmp(is_closed_att, "true"); - if (is_filled_att) - is_filled = !strcmp(is_filled_att, "true"); - if (start_point_att) - sscanf(start_point_att, "%g,%g", &start_x, &start_y); - - if (!stroking && !is_filled) /* not filled, when filling */ - return; - - fz_moveto(path, start_x, start_y); - - for (node = xml_down(root); node; node = xml_next(node)) - { - if (!strcmp(xml_tag(node), "ArcSegment")) - xps_parse_arc_segment(path, node, stroking, &skipped_stroke); - if (!strcmp(xml_tag(node), "PolyBezierSegment")) - xps_parse_poly_bezier_segment(path, node, stroking, &skipped_stroke); - if (!strcmp(xml_tag(node), "PolyLineSegment")) - xps_parse_poly_line_segment(path, node, stroking, &skipped_stroke); - if (!strcmp(xml_tag(node), "PolyQuadraticBezierSegment")) - xps_parse_poly_quadratic_bezier_segment(path, node, stroking, &skipped_stroke); - } - - if (is_closed) - { - if (stroking && skipped_stroke) - fz_lineto(path, start_x, start_y); /* we've skipped using fz_moveto... */ - else - fz_closepath(path); /* no skipped segments, safe to closepath properly */ - } -} - -fz_path * -xps_parse_path_geometry(xps_context *ctx, xps_resource *dict, xml_element *root, int stroking, int *fill_rule) -{ - xml_element *node; - - char *figures_att; - char *fill_rule_att; - char *transform_att; - - xml_element *transform_tag = NULL; - xml_element *figures_tag = NULL; /* only used by resource */ - - fz_matrix transform; - fz_path *path; - - figures_att = xml_att(root, "Figures"); - fill_rule_att = xml_att(root, "FillRule"); - transform_att = xml_att(root, "Transform"); - - for (node = xml_down(root); node; node = xml_next(node)) - { - if (!strcmp(xml_tag(node), "PathGeometry.Transform")) - transform_tag = xml_down(node); - } - - xps_resolve_resource_reference(ctx, dict, &transform_att, &transform_tag, NULL); - xps_resolve_resource_reference(ctx, dict, &figures_att, &figures_tag, NULL); - - if (fill_rule_att) - { - if (!strcmp(fill_rule_att, "NonZero")) - *fill_rule = 1; - if (!strcmp(fill_rule_att, "EvenOdd")) - *fill_rule = 0; - } - - 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); - - if (figures_att) - path = xps_parse_abbreviated_geometry(ctx, figures_att, fill_rule); - else - path = fz_new_path(); - - if (figures_tag) - xps_parse_path_figure(path, figures_tag, stroking); - - for (node = xml_down(root); node; node = xml_next(node)) - { - if (!strcmp(xml_tag(node), "PathFigure")) - xps_parse_path_figure(path, node, stroking); - } - - if (transform_att || transform_tag) - fz_transform_path(path, transform); - - return path; -} - -static int -xps_parse_line_cap(char *attr) -{ - if (attr) - { - if (!strcmp(attr, "Flat")) return 0; - if (!strcmp(attr, "Round")) return 1; - if (!strcmp(attr, "Square")) return 2; - if (!strcmp(attr, "Triangle")) return 3; - } - return 0; -} - -void -xps_clip(xps_context *ctx, fz_matrix ctm, xps_resource *dict, char *clip_att, xml_element *clip_tag) -{ - fz_path *path; - int fill_rule = 0; - - if (clip_att) - path = xps_parse_abbreviated_geometry(ctx, clip_att, &fill_rule); - else if (clip_tag) - path = xps_parse_path_geometry(ctx, dict, clip_tag, 0, &fill_rule); - else - path = fz_new_path(); - fz_clip_path(ctx->dev, path, NULL, fill_rule == 0, ctm); - fz_free_path(path); -} - -/* - * Parse an XPS element, and call relevant ghostscript - * functions for drawing and/or clipping the child elements. - */ - -void -xps_parse_path(xps_context *ctx, fz_matrix ctm, char *base_uri, xps_resource *dict, xml_element *root) -{ - xml_element *node; - - char *fill_uri; - char *stroke_uri; - char *opacity_mask_uri; - - char *transform_att; - char *clip_att; - char *data_att; - char *fill_att; - char *stroke_att; - char *opacity_att; - char *opacity_mask_att; - - xml_element *transform_tag = NULL; - xml_element *clip_tag = NULL; - xml_element *data_tag = NULL; - xml_element *fill_tag = NULL; - xml_element *stroke_tag = NULL; - xml_element *opacity_mask_tag = NULL; - - char *fill_opacity_att = NULL; - char *stroke_opacity_att = NULL; - - char *stroke_dash_array_att; - char *stroke_dash_cap_att; - char *stroke_dash_offset_att; - char *stroke_end_line_cap_att; - char *stroke_start_line_cap_att; - char *stroke_line_join_att; - char *stroke_miter_limit_att; - char *stroke_thickness_att; - - fz_stroke_state stroke; - fz_matrix transform; - float samples[32]; - fz_colorspace *colorspace; - fz_path *path; - fz_rect area; - int fill_rule; - - /* - * Extract attributes and extended attributes. - */ - - transform_att = xml_att(root, "RenderTransform"); - clip_att = xml_att(root, "Clip"); - data_att = xml_att(root, "Data"); - fill_att = xml_att(root, "Fill"); - stroke_att = xml_att(root, "Stroke"); - opacity_att = xml_att(root, "Opacity"); - opacity_mask_att = xml_att(root, "OpacityMask"); - - stroke_dash_array_att = xml_att(root, "StrokeDashArray"); - stroke_dash_cap_att = xml_att(root, "StrokeDashCap"); - stroke_dash_offset_att = xml_att(root, "StrokeDashOffset"); - stroke_end_line_cap_att = xml_att(root, "StrokeEndLineCap"); - stroke_start_line_cap_att = xml_att(root, "StrokeStartLineCap"); - stroke_line_join_att = xml_att(root, "StrokeLineJoin"); - stroke_miter_limit_att = xml_att(root, "StrokeMiterLimit"); - stroke_thickness_att = xml_att(root, "StrokeThickness"); - - for (node = xml_down(root); node; node = xml_next(node)) - { - if (!strcmp(xml_tag(node), "Path.RenderTransform")) - transform_tag = xml_down(node); - if (!strcmp(xml_tag(node), "Path.OpacityMask")) - opacity_mask_tag = xml_down(node); - if (!strcmp(xml_tag(node), "Path.Clip")) - clip_tag = xml_down(node); - if (!strcmp(xml_tag(node), "Path.Fill")) - fill_tag = xml_down(node); - if (!strcmp(xml_tag(node), "Path.Stroke")) - stroke_tag = xml_down(node); - if (!strcmp(xml_tag(node), "Path.Data")) - data_tag = xml_down(node); - } - - fill_uri = base_uri; - stroke_uri = base_uri; - opacity_mask_uri = base_uri; - - xps_resolve_resource_reference(ctx, dict, &data_att, &data_tag, NULL); - xps_resolve_resource_reference(ctx, dict, &clip_att, &clip_tag, NULL); - xps_resolve_resource_reference(ctx, dict, &transform_att, &transform_tag, NULL); - xps_resolve_resource_reference(ctx, dict, &fill_att, &fill_tag, &fill_uri); - xps_resolve_resource_reference(ctx, dict, &stroke_att, &stroke_tag, &stroke_uri); - xps_resolve_resource_reference(ctx, dict, &opacity_mask_att, &opacity_mask_tag, &opacity_mask_uri); - - /* - * Act on the information we have gathered: - */ - - if (!data_att && !data_tag) - return; - - if (fill_tag && !strcmp(xml_tag(fill_tag), "SolidColorBrush")) - { - fill_opacity_att = xml_att(fill_tag, "Opacity"); - fill_att = xml_att(fill_tag, "Color"); - fill_tag = NULL; - } - - if (stroke_tag && !strcmp(xml_tag(stroke_tag), "SolidColorBrush")) - { - stroke_opacity_att = xml_att(stroke_tag, "Opacity"); - stroke_att = xml_att(stroke_tag, "Color"); - stroke_tag = NULL; - } - - stroke.start_cap = xps_parse_line_cap(stroke_start_line_cap_att); - stroke.dash_cap = xps_parse_line_cap(stroke_dash_cap_att); - stroke.end_cap = xps_parse_line_cap(stroke_end_line_cap_att); - - stroke.linejoin = 0; - if (stroke_line_join_att) - { - 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; - } - - stroke.miterlimit = 10; - if (stroke_miter_limit_att) - stroke.miterlimit = fz_atof(stroke_miter_limit_att); - - stroke.linewidth = 1; - if (stroke_thickness_att) - stroke.linewidth = fz_atof(stroke_thickness_att); - - stroke.dash_phase = 0; - stroke.dash_len = 0; - if (stroke_dash_array_att) - { - char *s = stroke_dash_array_att; - - if (stroke_dash_offset_att) - stroke.dash_phase = fz_atof(stroke_dash_offset_att) * stroke.linewidth; - - while (*s && stroke.dash_len < nelem(stroke.dash_list)) - { - while (*s == ' ') - s++; - stroke.dash_list[stroke.dash_len++] = fz_atof(s) * stroke.linewidth; - while (*s && *s != ' ') - s++; - } - } - - 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(transform, ctm); - - if (clip_att || clip_tag) - xps_clip(ctx, ctm, dict, clip_att, clip_tag); - - fill_rule = 0; - if (data_att) - path = xps_parse_abbreviated_geometry(ctx, data_att, &fill_rule); - else if (data_tag) - path = xps_parse_path_geometry(ctx, dict, data_tag, 0, &fill_rule); - - if (stroke_att || stroke_tag) - area = fz_bound_path(path, &stroke, ctm); - else - area = fz_bound_path(path, NULL, ctm); - - xps_begin_opacity(ctx, ctm, area, opacity_mask_uri, dict, opacity_att, opacity_mask_tag); - - if (fill_att) - { - xps_parse_color(ctx, base_uri, fill_att, &colorspace, samples); - if (fill_opacity_att) - samples[0] = fz_atof(fill_opacity_att); - xps_set_color(ctx, colorspace, samples); - - fz_fill_path(ctx->dev, path, fill_rule == 0, ctm, - ctx->colorspace, ctx->color, ctx->alpha); - } - - if (fill_tag) - { - area = fz_bound_path(path, NULL, ctm); - - fz_clip_path(ctx->dev, path, NULL, fill_rule == 0, ctm); - xps_parse_brush(ctx, ctm, area, fill_uri, dict, fill_tag); - fz_pop_clip(ctx->dev); - } - - if (stroke_att) - { - xps_parse_color(ctx, base_uri, stroke_att, &colorspace, samples); - if (stroke_opacity_att) - samples[0] = fz_atof(stroke_opacity_att); - xps_set_color(ctx, colorspace, samples); - - fz_stroke_path(ctx->dev, path, &stroke, ctm, - ctx->colorspace, ctx->color, ctx->alpha); - } - - if (stroke_tag) - { - fz_clip_stroke_path(ctx->dev, path, NULL, &stroke, ctm); - xps_parse_brush(ctx, ctm, area, stroke_uri, dict, stroke_tag); - fz_pop_clip(ctx->dev); - } - - xps_end_opacity(ctx, opacity_mask_uri, dict, opacity_att, opacity_mask_tag); - - fz_free_path(path); - path = NULL; - - if (clip_att || clip_tag) - fz_pop_clip(ctx->dev); -} diff --git a/contrib/media/updf/xps/xps_png.c b/contrib/media/updf/xps/xps_png.c deleted file mode 100644 index 245dd285e3..0000000000 --- a/contrib/media/updf/xps/xps_png.c +++ /dev/null @@ -1,578 +0,0 @@ -#include "fitz.h" -#include "muxps.h" - -#include - -struct info -{ - int width, height, depth, n; - int interlace, indexed; - int size; - unsigned char *samples; - unsigned char palette[256*4]; - int transparency; - int trns[3]; - int xres, yres; -}; - -static inline int getint(unsigned char *p) -{ - return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; -} - -static inline int getcomp(unsigned char *line, int x, int bpc) -{ - switch (bpc) - { - case 1: return (line[x >> 3] >> ( 7 - (x & 7) ) ) & 1; - case 2: return (line[x >> 2] >> ( ( 3 - (x & 3) ) << 1 ) ) & 3; - case 4: return (line[x >> 1] >> ( ( 1 - (x & 1) ) << 2 ) ) & 15; - case 8: return line[x]; - case 16: return line[x << 1] << 8 | line[(x << 1) + 1]; - } - return 0; -} - -static inline void putcomp(unsigned char *line, int x, int bpc, int value) -{ - int maxval = (1 << bpc) - 1; - - switch (bpc) - { - case 1: line[x >> 3] &= ~(maxval << (7 - (x & 7))); break; - case 2: line[x >> 2] &= ~(maxval << ((3 - (x & 3)) << 1)); break; - case 4: line[x >> 1] &= ~(maxval << ((1 - (x & 1)) << 2)); break; - } - - switch (bpc) - { - case 1: line[x >> 3] |= value << (7 - (x & 7)); break; - case 2: line[x >> 2] |= value << ((3 - (x & 3)) << 1); break; - case 4: line[x >> 1] |= value << ((1 - (x & 1)) << 2); break; - case 8: line[x] = value; break; - case 16: line[x << 1] = value >> 8; line[(x << 1) + 1] = value & 0xFF; break; - } -} - -static const unsigned char png_signature[8] = -{ - 137, 80, 78, 71, 13, 10, 26, 10 -}; - -static void *zalloc(void *opaque, unsigned int items, unsigned int size) -{ - return fz_calloc(items, size); -} - -static void zfree(void *opaque, void *address) -{ - fz_free(address); -} - -static inline int paeth(int a, int b, int c) -{ - /* The definitions of ac and bc are correct, not a typo. */ - int ac = b - c, bc = a - c, abcc = ac + bc; - int pa = (ac < 0 ? -ac : ac); - int pb = (bc < 0 ? -bc : bc); - int pc = (abcc < 0 ? -abcc : abcc); - return pa <= pb && pa <= pc ? a : pb <= pc ? b : c; -} - -static void -png_predict(unsigned char *samples, int width, int height, int n, int depth) -{ - int stride = (width * n * depth + 7) / 8; - int bpp = (n * depth + 7) / 8; - int i, row; - - for (row = 0; row < height; row ++) - { - unsigned char *src = samples + (stride + 1) * row; - unsigned char *dst = samples + stride * row; - - unsigned char *a = dst; - unsigned char *b = dst - stride; - unsigned char *c = dst - stride; - - switch (*src++) - { - default: - case 0: /* None */ - for (i = 0; i < stride; i++) - *dst++ = *src++; - break; - - case 1: /* Sub */ - for (i = 0; i < bpp; i++) - *dst++ = *src++; - for (i = bpp; i < stride; i++) - *dst++ = *src++ + *a++; - break; - - case 2: /* Up */ - if (row == 0) - for (i = 0; i < stride; i++) - *dst++ = *src++; - else - for (i = 0; i < stride; i++) - *dst++ = *src++ + *b++; - break; - - case 3: /* Average */ - if (row == 0) - { - for (i = 0; i < bpp; i++) - *dst++ = *src++; - for (i = bpp; i < stride; i++) - *dst++ = *src++ + (*a++ >> 1); - } - else - { - for (i = 0; i < bpp; i++) - *dst++ = *src++ + (*b++ >> 1); - for (i = bpp; i < stride; i++) - *dst++ = *src++ + ((*b++ + *a++) >> 1); - } - break; - - case 4: /* Paeth */ - if (row == 0) - { - for (i = 0; i < bpp; i++) - *dst++ = *src++ + paeth(0, 0, 0); - for (i = bpp; i < stride; i++) - *dst++ = *src++ + paeth(*a++, 0, 0); - } - else - { - for (i = 0; i < bpp; i++) - *dst++ = *src++ + paeth(0, *b++, 0); - for (i = bpp; i < stride; i++) - *dst++ = *src++ + paeth(*a++, *b++, *c++); - } - break; - } - } -} - -static const int adam7_ix[7] = { 0, 4, 0, 2, 0, 1, 0 }; -static const int adam7_dx[7] = { 8, 8, 4, 4, 2, 2, 1 }; -static const int adam7_iy[7] = { 0, 0, 4, 0, 2, 0, 1 }; -static const int adam7_dy[7] = { 8, 8, 8, 4, 4, 2, 2 }; - -static void -png_deinterlace_passes(struct info *info, int *w, int *h, int *ofs) -{ - int p, bpp = info->depth * info->n; - ofs[0] = 0; - for (p = 0; p < 7; p++) - { - w[p] = (info->width + adam7_dx[p] - adam7_ix[p] - 1) / adam7_dx[p]; - h[p] = (info->height + adam7_dy[p] - adam7_iy[p] - 1) / adam7_dy[p]; - if (w[p] == 0) h[p] = 0; - if (h[p] == 0) w[p] = 0; - if (w[p] && h[p]) - ofs[p + 1] = ofs[p] + h[p] * (1 + (w[p] * bpp + 7) / 8); - else - ofs[p + 1] = ofs[p]; - } -} - -static void -png_deinterlace(struct info *info, int *passw, int *passh, int *passofs) -{ - int n = info->n; - int depth = info->depth; - int stride = (info->width * n * depth + 7) / 8; - unsigned char *output; - int p, x, y, k; - - output = fz_calloc(info->height, stride); - - for (p = 0; p < 7; p++) - { - unsigned char *sp = info->samples + passofs[p]; - int w = passw[p]; - int h = passh[p]; - - png_predict(sp, w, h, n, depth); - for (y = 0; y < h; y++) - { - for (x = 0; x < w; x++) - { - int outx = x * adam7_dx[p] + adam7_ix[p]; - int outy = y * adam7_dy[p] + adam7_iy[p]; - unsigned char *dp = output + outy * stride; - for (k = 0; k < n; k++) - { - int v = getcomp(sp, x * n + k, depth); - putcomp(dp, outx * n + k, depth, v); - } - } - sp += (w * depth * n + 7) / 8; - } - } - - fz_free(info->samples); - info->samples = output; -} - -static int -png_read_ihdr(struct info *info, unsigned char *p, int size) -{ - int color, compression, filter; - - if (size != 13) - return fz_throw("IHDR chunk is the wrong size"); - - info->width = getint(p + 0); - info->height = getint(p + 4); - info->depth = p[8]; - - color = p[9]; - compression = p[10]; - filter = p[11]; - info->interlace = p[12]; - - if (info->width <= 0) - return fz_throw("image width must be > 0"); - if (info->height <= 0) - return fz_throw("image height must be > 0"); - - if (info->depth != 1 && info->depth != 2 && info->depth != 4 && - info->depth != 8 && info->depth != 16) - return fz_throw("image bit depth must be one of 1, 2, 4, 8, 16"); - if (color == 2 && info->depth < 8) - return fz_throw("illegal bit depth for truecolor"); - if (color == 3 && info->depth > 8) - return fz_throw("illegal bit depth for indexed"); - if (color == 4 && info->depth < 8) - return fz_throw("illegal bit depth for grayscale with alpha"); - if (color == 6 && info->depth < 8) - return fz_throw("illegal bit depth for truecolor with alpha"); - - info->indexed = 0; - if (color == 0) /* gray */ - info->n = 1; - else if (color == 2) /* rgb */ - info->n = 3; - else if (color == 4) /* gray alpha */ - info->n = 2; - else if (color == 6) /* rgb alpha */ - info->n = 4; - else if (color == 3) /* indexed */ - { - info->indexed = 1; - info->n = 1; - } - else - return fz_throw("unknown color type"); - - if (compression != 0) - return fz_throw("unknown compression method"); - if (filter != 0) - return fz_throw("unknown filter method"); - if (info->interlace != 0 && info->interlace != 1) - return fz_throw("interlace method not supported"); - - return fz_okay; -} - -static int -png_read_plte(struct info *info, unsigned char *p, int size) -{ - int n = size / 3; - int i; - - if (n > 256 || n > (1 << info->depth)) - return fz_throw("too many samples in palette"); - - for (i = 0; i < n; i++) - { - info->palette[i * 4] = p[i * 3]; - info->palette[i * 4 + 1] = p[i * 3 + 1]; - info->palette[i * 4 + 2] = p[i * 3 + 2]; - } - - return fz_okay; -} - -static int -png_read_trns(struct info *info, unsigned char *p, int size) -{ - int i; - - info->transparency = 1; - - if (info->indexed) - { - if (size > 256 || size > (1 << info->depth)) - return fz_throw("too many samples in transparency table"); - for (i = 0; i < size; i++) - info->palette[i * 4 + 3] = p[i]; - } - else - { - if (size != info->n * 2) - return fz_throw("tRNS chunk is the wrong size"); - for (i = 0; i < info->n; i++) - info->trns[i] = (p[i * 2] << 8 | p[i * 2 + 1]) & ((1 << info->depth) - 1); - } - - return fz_okay; -} - -static int -png_read_idat(struct info *info, unsigned char *p, int size, z_stream *stm) -{ - int code; - - stm->next_in = p; - stm->avail_in = size; - - code = inflate(stm, Z_SYNC_FLUSH); - if (code != Z_OK && code != Z_STREAM_END) - return fz_throw("zlib error: %s", stm->msg); - if (stm->avail_in != 0) - { - if (stm->avail_out == 0) - return fz_throw("ran out of output before input"); - return fz_throw("inflate did not consume buffer (%d remaining)", stm->avail_in); - } - - return fz_okay; -} - -static int -png_read_phys(struct info *info, unsigned char *p, int size) -{ - if (size != 9) - return fz_throw("pHYs chunk is the wrong size"); - if (p[8] == 1) - { - info->xres = getint(p) * 254 / 10000; - info->yres = getint(p + 4) * 254 / 10000; - } - return fz_okay; -} - -static int -png_read_image(struct info *info, unsigned char *p, int total) -{ - int passw[7], passh[7], passofs[8]; - int code, size; - z_stream stm; - - memset(info, 0, sizeof (struct info)); - memset(info->palette, 255, sizeof(info->palette)); - info->xres = 96; - info->yres = 96; - - /* Read signature */ - - if (total < 8 + 12 || memcmp(p, png_signature, 8)) - return fz_throw("not a png image (wrong signature)"); - - p += 8; - total -= 8; - - /* Read IHDR chunk (must come first) */ - - size = getint(p); - - if (size + 12 > total) - return fz_throw("premature end of data in png image"); - - if (!memcmp(p + 4, "IHDR", 4)) - { - code = png_read_ihdr(info, p + 8, size); - if (code) - return fz_rethrow(code, "cannot read png header"); - } - else - return fz_throw("png file must start with IHDR chunk"); - - p += size + 12; - total -= size + 12; - - /* Prepare output buffer */ - - if (!info->interlace) - { - info->size = info->height * (1 + (info->width * info->n * info->depth + 7) / 8); - } - else - { - png_deinterlace_passes(info, passw, passh, passofs); - info->size = passofs[7]; - } - - info->samples = fz_malloc(info->size); - - stm.zalloc = zalloc; - stm.zfree = zfree; - stm.opaque = NULL; - - stm.next_out = info->samples; - stm.avail_out = info->size; - - code = inflateInit(&stm); - if (code != Z_OK) - return fz_throw("zlib error: %s", stm.msg); - - /* Read remaining chunks until IEND */ - - while (total > 8) - { - size = getint(p); - - if (size + 12 > total) - return fz_throw("premature end of data in png image"); - - if (!memcmp(p + 4, "PLTE", 4)) - { - code = png_read_plte(info, p + 8, size); - if (code) - return fz_rethrow(code, "cannot read png palette"); - } - - if (!memcmp(p + 4, "tRNS", 4)) - { - code = png_read_trns(info, p + 8, size); - if (code) - return fz_rethrow(code, "cannot read png transparency"); - } - - if (!memcmp(p + 4, "pHYs", 4)) - { - code = png_read_phys(info, p + 8, size); - if (code) - return fz_rethrow(code, "cannot read png resolution"); - } - - if (!memcmp(p + 4, "IDAT", 4)) - { - code = png_read_idat(info, p + 8, size, &stm); - if (code) - return fz_rethrow(code, "cannot read png image data"); - } - - if (!memcmp(p + 4, "IEND", 4)) - break; - - p += size + 12; - total -= size + 12; - } - - code = inflateEnd(&stm); - if (code != Z_OK) - return fz_throw("zlib error: %s", stm.msg); - - /* Apply prediction filter and deinterlacing */ - - if (!info->interlace) - png_predict(info->samples, info->width, info->height, info->n, info->depth); - else - png_deinterlace(info, passw, passh, passofs); - - return fz_okay; -} - -static fz_pixmap * -png_expand_palette(struct info *info, fz_pixmap *src) -{ - fz_pixmap *dst = fz_new_pixmap(fz_device_rgb, src->w, src->h); - unsigned char *sp = src->samples; - unsigned char *dp = dst->samples; - int x, y; - - dst->xres = src->xres; - dst->yres = src->yres; - - for (y = 0; y < info->height; y++) - { - for (x = 0; x < info->width; x++) - { - int v = *sp << 2; - *dp++ = info->palette[v]; - *dp++ = info->palette[v + 1]; - *dp++ = info->palette[v + 2]; - *dp++ = info->palette[v + 3]; - sp += 2; - } - } - - fz_drop_pixmap(src); - return dst; -} - -static void -png_mask_transparency(struct info *info, fz_pixmap *dst) -{ - int stride = (info->width * info->n * info->depth + 7) / 8; - int depth = info->depth; - int n = info->n; - int x, y, k, t; - - for (y = 0; y < info->height; y++) - { - unsigned char *sp = info->samples + y * stride; - unsigned char *dp = dst->samples + y * dst->w * dst->n; - for (x = 0; x < info->width; x++) - { - t = 1; - for (k = 0; k < n; k++) - if (getcomp(sp, x * n + k, depth) != info->trns[k]) - t = 0; - if (t) - dp[x * dst->n + dst->n - 1] = 0; - } - } -} - -int -xps_decode_png(fz_pixmap **imagep, byte *p, int total) -{ - fz_pixmap *image; - fz_colorspace *colorspace; - struct info png; - int code; - int stride; - - code = png_read_image(&png, p, total); - if (code) - return fz_rethrow(code, "cannot read png image"); - - if (png.n == 3 || png.n == 4) - colorspace = fz_device_rgb; - else - colorspace = fz_device_gray; - - stride = (png.width * png.n * png.depth + 7) / 8; - - image = fz_new_pixmap_with_limit(colorspace, png.width, png.height); - if (!image) - { - fz_free(png.samples); - return fz_throw("out of memory"); - } - - image->xres = png.xres; - image->yres = png.yres; - - fz_unpack_tile(image, png.samples, png.n, png.depth, stride, png.indexed); - - if (png.indexed) - image = png_expand_palette(&png, image); - else if (png.transparency) - png_mask_transparency(&png, image); - - if (png.transparency || png.n == 2 || png.n == 4) - fz_premultiply_pixmap(image); - - fz_free(png.samples); - - *imagep = image; - return fz_okay; -} diff --git a/contrib/media/updf/xps/xps_resource.c b/contrib/media/updf/xps/xps_resource.c deleted file mode 100644 index c96f3619de..0000000000 --- a/contrib/media/updf/xps/xps_resource.c +++ /dev/null @@ -1,187 +0,0 @@ -#include "fitz.h" -#include "muxps.h" - -static xml_element * -xps_find_resource(xps_context *ctx, xps_resource *dict, char *name, char **urip) -{ - xps_resource *head, *node; - for (head = dict; head; head = head->parent) - { - for (node = head; node; node = node->next) - { - if (!strcmp(node->name, name)) - { - if (urip && head->base_uri) - *urip = head->base_uri; - return node->data; - } - } - } - return NULL; -} - -static xml_element * -xps_parse_resource_reference(xps_context *ctx, xps_resource *dict, char *att, char **urip) -{ - char name[1024]; - char *s; - - if (strstr(att, "{StaticResource ") != att) - return NULL; - - fz_strlcpy(name, att + 16, sizeof name); - s = strrchr(name, '}'); - if (s) - *s = 0; - - return xps_find_resource(ctx, dict, name, urip); -} - -void -xps_resolve_resource_reference(xps_context *ctx, xps_resource *dict, - char **attp, xml_element **tagp, char **urip) -{ - if (*attp) - { - xml_element *rsrc = xps_parse_resource_reference(ctx, dict, *attp, urip); - if (rsrc) - { - *attp = NULL; - *tagp = rsrc; - } - } -} - -static int -xps_parse_remote_resource_dictionary(xps_context *ctx, xps_resource **dictp, char *base_uri, char *source_att) -{ - char part_name[1024]; - char part_uri[1024]; - xps_resource *dict; - xps_part *part; - xml_element *xml; - char *s; - int code; - - /* External resource dictionaries MUST NOT reference other resource dictionaries */ - xps_absolute_path(part_name, base_uri, source_att, sizeof part_name); - part = xps_read_part(ctx, part_name); - if (!part) - { - return fz_throw("cannot find remote resource part '%s'", part_name); - } - - xml = xml_parse_document(part->data, part->size); - if (!xml) - { - xps_free_part(ctx, part); - return fz_rethrow(-1, "cannot parse xml"); - } - - if (strcmp(xml_tag(xml), "ResourceDictionary")) - { - xml_free_element(xml); - xps_free_part(ctx, part); - return fz_throw("expected ResourceDictionary element (found %s)", xml_tag(xml)); - } - - fz_strlcpy(part_uri, part_name, sizeof part_uri); - s = strrchr(part_uri, '/'); - if (s) - s[1] = 0; - - code = xps_parse_resource_dictionary(ctx, &dict, part_uri, xml); - if (code) - { - xml_free_element(xml); - xps_free_part(ctx, part); - return fz_rethrow(code, "cannot parse remote resource dictionary: %s", part_uri); - } - - dict->base_xml = xml; /* pass on ownership */ - - xps_free_part(ctx, part); - - *dictp = dict; - return fz_okay; -} - -int -xps_parse_resource_dictionary(xps_context *ctx, xps_resource **dictp, char *base_uri, xml_element *root) -{ - xps_resource *head; - xps_resource *entry; - xml_element *node; - char *source; - char *key; - int code; - - source = xml_att(root, "Source"); - if (source) - { - code = xps_parse_remote_resource_dictionary(ctx, dictp, base_uri, source); - if (code) - return fz_rethrow(code, "cannot parse remote resource dictionary"); - return fz_okay; - } - - head = NULL; - - for (node = xml_down(root); node; node = xml_next(node)) - { - key = xml_att(node, "x:Key"); - if (key) - { - entry = fz_malloc(sizeof(xps_resource)); - entry->name = key; - entry->base_uri = NULL; - entry->base_xml = NULL; - entry->data = node; - entry->next = head; - entry->parent = NULL; - head = entry; - } - } - - if (head) - head->base_uri = fz_strdup(base_uri); - else - return fz_throw("empty resource dictionary"); - - *dictp = head; - return fz_okay; -} - -void -xps_free_resource_dictionary(xps_context *ctx, xps_resource *dict) -{ - xps_resource *next; - while (dict) - { - next = dict->next; - if (dict->base_xml) - xml_free_element(dict->base_xml); - if (dict->base_uri) - fz_free(dict->base_uri); - fz_free(dict); - dict = next; - } -} - -void -xps_debug_resource_dictionary(xps_resource *dict) -{ - while (dict) - { - if (dict->base_uri) - printf("URI = '%s'\n", dict->base_uri); - printf("KEY = '%s' VAL = %p\n", dict->name, dict->data); - if (dict->parent) - { - printf("PARENT = {\n"); - xps_debug_resource_dictionary(dict->parent); - printf("}\n"); - } - dict = dict->next; - } -} diff --git a/contrib/media/updf/xps/xps_tiff.c b/contrib/media/updf/xps/xps_tiff.c deleted file mode 100644 index 8c58b4d12b..0000000000 --- a/contrib/media/updf/xps/xps_tiff.c +++ /dev/null @@ -1,865 +0,0 @@ -#include "fitz.h" -#include "muxps.h" - -/* - * TIFF image loader. Should be enough to support TIFF files in XPS. - * Baseline TIFF 6.0 plus CMYK, LZW, Flate and JPEG support. - * Limited bit depths (1,2,4,8). - * Limited planar configurations (1=chunky). - * No tiles (easy fix if necessary). - * TODO: RGBPal images - */ - -struct tiff -{ - /* "file" */ - byte *bp, *rp, *ep; - - /* byte order */ - unsigned order; - - /* where we can find the strips of image data */ - unsigned rowsperstrip; - unsigned *stripoffsets; - unsigned *stripbytecounts; - - /* colormap */ - unsigned *colormap; - - /* assorted tags */ - unsigned subfiletype; - unsigned photometric; - unsigned compression; - unsigned imagewidth; - unsigned imagelength; - unsigned samplesperpixel; - unsigned bitspersample; - unsigned planar; - unsigned extrasamples; - unsigned xresolution; - unsigned yresolution; - unsigned resolutionunit; - unsigned fillorder; - unsigned g3opts; - unsigned g4opts; - unsigned predictor; - - unsigned ycbcrsubsamp[2]; - - byte *jpegtables; /* point into "file" buffer */ - unsigned jpegtableslen; - - byte *profile; - int profilesize; - - /* decoded data */ - fz_colorspace *colorspace; - byte *samples; - int stride; -}; - -enum -{ - TII = 0x4949, /* 'II' */ - TMM = 0x4d4d, /* 'MM' */ - TBYTE = 1, - TASCII = 2, - TSHORT = 3, - TLONG = 4, - TRATIONAL = 5 -}; - -#define NewSubfileType 254 -#define ImageWidth 256 -#define ImageLength 257 -#define BitsPerSample 258 -#define Compression 259 -#define PhotometricInterpretation 262 -#define FillOrder 266 -#define StripOffsets 273 -#define SamplesPerPixel 277 -#define RowsPerStrip 278 -#define StripByteCounts 279 -#define XResolution 282 -#define YResolution 283 -#define PlanarConfiguration 284 -#define T4Options 292 -#define T6Options 293 -#define ResolutionUnit 296 -#define Predictor 317 -#define ColorMap 320 -#define TileWidth 322 -#define TileLength 323 -#define TileOffsets 324 -#define TileByteCounts 325 -#define ExtraSamples 338 -#define JPEGTables 347 -#define YCbCrSubSampling 520 -#define ICCProfile 34675 - -static const byte bitrev[256] = -{ - 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, - 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, - 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, - 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, - 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, - 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, - 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, - 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, - 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, - 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, - 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, - 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, - 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, - 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, - 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, - 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, - 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, - 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, - 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, - 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, - 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, - 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, - 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, - 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, - 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, - 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, - 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, - 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, - 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, - 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, - 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, - 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff -}; - -static int -xps_decode_tiff_uncompressed(struct tiff *tiff, fz_stream *stm, byte *wp, int wlen) -{ - int n = fz_read(stm, wp, wlen); - fz_close(stm); - if (n < 0) - return fz_rethrow(n, "cannot read uncompressed strip"); - return fz_okay; -} - -static int -xps_decode_tiff_packbits(struct tiff *tiff, fz_stream *chain, byte *wp, int wlen) -{ - fz_stream *stm = fz_open_rld(chain); - int n = fz_read(stm, wp, wlen); - fz_close(stm); - if (n < 0) - return fz_rethrow(n, "cannot read packbits strip"); - return fz_okay; -} - -static int -xps_decode_tiff_lzw(struct tiff *tiff, fz_stream *chain, byte *wp, int wlen) -{ - fz_stream *stm = fz_open_lzwd(chain, NULL); - int n = fz_read(stm, wp, wlen); - fz_close(stm); - if (n < 0) - return fz_rethrow(n, "cannot read lzw strip"); - return fz_okay; -} -static int -xps_decode_tiff_flate(struct tiff *tiff, fz_stream *chain, byte *wp, int wlen) -{ - fz_stream *stm = fz_open_flated(chain); - int n = fz_read(stm, wp, wlen); - fz_close(stm); - if (n < 0) - return fz_rethrow(n, "cannot read flate strip"); - return fz_okay; -} - -static int -xps_decode_tiff_fax(struct tiff *tiff, int comp, fz_stream *chain, byte *wp, int wlen) -{ - fz_stream *stm; - fz_obj *params; - fz_obj *columns, *rows, *black_is_1, *k, *encoded_byte_align; - int n; - - columns = fz_new_int(tiff->imagewidth); - rows = fz_new_int(tiff->imagelength); - black_is_1 = fz_new_bool(tiff->photometric == 0); - k = fz_new_int(comp == 4 ? -1 : 0); - encoded_byte_align = fz_new_bool(comp == 2); - - params = fz_new_dict(5); - fz_dict_puts(params, "Columns", columns); - fz_dict_puts(params, "Rows", rows); - fz_dict_puts(params, "BlackIs1", black_is_1); - fz_dict_puts(params, "K", k); - fz_dict_puts(params, "EncodedByteAlign", encoded_byte_align); - - fz_drop_obj(columns); - fz_drop_obj(rows); - fz_drop_obj(black_is_1); - fz_drop_obj(k); - fz_drop_obj(encoded_byte_align); - - stm = fz_open_faxd(chain, params); - n = fz_read(stm, wp, wlen); - fz_close(stm); - fz_drop_obj(params); - - if (n < 0) - return fz_rethrow(n, "cannot read fax strip"); - return fz_okay; -} - -static int -xps_decode_tiff_jpeg(struct tiff *tiff, fz_stream *chain, byte *wp, int wlen) -{ - fz_stream *stm = fz_open_dctd(chain, NULL); - int n = fz_read(stm, wp, wlen); - fz_close(stm); - if (n < 0) - return fz_rethrow(n, "cannot read jpeg strip"); - return fz_okay; -} - -static inline int getcomp(byte *line, int x, int bpc) -{ - switch (bpc) - { - case 1: return (line[x >> 3] >> ( 7 - (x & 7) ) ) & 1; - case 2: return (line[x >> 2] >> ( ( 3 - (x & 3) ) << 1 ) ) & 3; - case 4: return (line[x >> 1] >> ( ( 1 - (x & 1) ) << 2 ) ) & 15; - case 8: return line[x]; - case 16: return line[x << 1] << 8 | line[(x << 1) + 1]; - } - return 0; -} - -static inline void putcomp(byte *line, int x, int bpc, int value) -{ - int maxval = (1 << bpc) - 1; - - switch (bpc) - { - case 1: line[x >> 3] &= ~(maxval << (7 - (x & 7))); break; - case 2: line[x >> 2] &= ~(maxval << ((3 - (x & 3)) << 1)); break; - case 4: line[x >> 1] &= ~(maxval << ((1 - (x & 1)) << 2)); break; - } - - switch (bpc) - { - case 1: line[x >> 3] |= value << (7 - (x & 7)); break; - case 2: line[x >> 2] |= value << ((3 - (x & 3)) << 1); break; - case 4: line[x >> 1] |= value << ((1 - (x & 1)) << 2); break; - case 8: line[x] = value; break; - case 16: line[x << 1] = value >> 8; line[(x << 1) + 1] = value & 0xFF; break; - } -} - -static void -xps_unpredict_tiff(byte *line, int width, int comps, int bits) -{ - byte left[32]; - int i, k, v; - - for (k = 0; k < comps; k++) - left[k] = 0; - - for (i = 0; i < width; i++) - { - for (k = 0; k < comps; k++) - { - v = getcomp(line, i * comps + k, bits); - v = v + left[k]; - v = v % (1 << bits); - putcomp(line, i * comps + k, bits, v); - left[k] = v; - } - } -} - -static void -xps_invert_tiff(byte *line, int width, int comps, int bits, int alpha) -{ - int i, k, v; - int m = (1 << bits) - 1; - - for (i = 0; i < width; i++) - { - for (k = 0; k < comps; k++) - { - v = getcomp(line, i * comps + k, bits); - if (!alpha || k < comps - 1) - v = m - v; - putcomp(line, i * comps + k, bits, v); - } - } -} - -static int -xps_expand_tiff_colormap(struct tiff *tiff) -{ - int maxval = 1 << tiff->bitspersample; - byte *samples; - byte *src, *dst; - unsigned int x, y; - unsigned int stride; - - /* colormap has first all red, then all green, then all blue values */ - /* colormap values are 0..65535, bits is 4 or 8 */ - /* image can be with or without extrasamples: comps is 1 or 2 */ - - if (tiff->samplesperpixel != 1 && tiff->samplesperpixel != 2) - return fz_throw("invalid number of samples for RGBPal"); - - if (tiff->bitspersample != 4 && tiff->bitspersample != 8) - return fz_throw("invalid number of bits for RGBPal"); - - stride = tiff->imagewidth * (tiff->samplesperpixel + 2); - - samples = fz_malloc(stride * tiff->imagelength); - - for (y = 0; y < tiff->imagelength; y++) - { - src = tiff->samples + (tiff->stride * y); - dst = samples + (stride * y); - - for (x = 0; x < tiff->imagewidth; x++) - { - if (tiff->extrasamples) - { - int c = getcomp(src, x * 2, tiff->bitspersample); - int a = getcomp(src, x * 2 + 1, tiff->bitspersample); - *dst++ = tiff->colormap[c + 0] >> 8; - *dst++ = tiff->colormap[c + maxval] >> 8; - *dst++ = tiff->colormap[c + maxval * 2] >> 8; - *dst++ = a << (8 - tiff->bitspersample); - } - else - { - int c = getcomp(src, x, tiff->bitspersample); - *dst++ = tiff->colormap[c + 0] >> 8; - *dst++ = tiff->colormap[c + maxval] >> 8; - *dst++ = tiff->colormap[c + maxval * 2] >> 8; - } - } - } - - tiff->samplesperpixel += 2; - tiff->bitspersample = 8; - tiff->stride = stride; - tiff->samples = samples; - return fz_okay; -} - -static int -xps_decode_tiff_strips(struct tiff *tiff) -{ - fz_stream *stm; - int error; - - /* switch on compression to create a filter */ - /* feed each strip to the filter */ - /* read out the data and pack the samples into an xps_image */ - - /* type 32773 / packbits -- nothing special (same row-padding as PDF) */ - /* type 2 / ccitt rle -- no EOL, no RTC, rows are byte-aligned */ - /* type 3 and 4 / g3 and g4 -- each strip starts new section */ - /* type 5 / lzw -- each strip is handled separately */ - - byte *wp; - unsigned row; - unsigned strip; - unsigned i; - - if (!tiff->rowsperstrip || !tiff->stripoffsets || !tiff->rowsperstrip) - return fz_throw("no image data in tiff; maybe it is tiled"); - - if (tiff->planar != 1) - return fz_throw("image data is not in chunky format"); - - tiff->stride = (tiff->imagewidth * tiff->samplesperpixel * tiff->bitspersample + 7) / 8; - - switch (tiff->photometric) - { - case 0: /* WhiteIsZero -- inverted */ - tiff->colorspace = fz_device_gray; - break; - case 1: /* BlackIsZero */ - tiff->colorspace = fz_device_gray; - break; - case 2: /* RGB */ - tiff->colorspace = fz_device_rgb; - break; - case 3: /* RGBPal */ - tiff->colorspace = fz_device_rgb; - break; - case 5: /* CMYK */ - tiff->colorspace = fz_device_cmyk; - break; - case 6: /* YCbCr */ - /* it's probably a jpeg ... we let jpeg convert to rgb */ - tiff->colorspace = fz_device_rgb; - break; - default: - return fz_throw("unknown photometric: %d", tiff->photometric); - } - - switch (tiff->resolutionunit) - { - case 2: - /* no unit conversion needed */ - break; - case 3: - tiff->xresolution = tiff->xresolution * 254 / 100; - tiff->yresolution = tiff->yresolution * 254 / 100; - break; - default: - tiff->xresolution = 96; - tiff->yresolution = 96; - break; - } - - /* Note xres and yres could be 0 even if unit was set. If so default to 96dpi. */ - if (tiff->xresolution == 0 || tiff->yresolution == 0) - { - tiff->xresolution = 96; - tiff->yresolution = 96; - } - - tiff->samples = fz_calloc(tiff->imagelength, tiff->stride); - memset(tiff->samples, 0x55, tiff->imagelength * tiff->stride); - wp = tiff->samples; - - strip = 0; - for (row = 0; row < tiff->imagelength; row += tiff->rowsperstrip) - { - unsigned offset = tiff->stripoffsets[strip]; - unsigned rlen = tiff->stripbytecounts[strip]; - unsigned wlen = tiff->stride * tiff->rowsperstrip; - byte *rp = tiff->bp + offset; - - if (wp + wlen > tiff->samples + tiff->stride * tiff->imagelength) - wlen = tiff->samples + tiff->stride * tiff->imagelength - wp; - - if (rp + rlen > tiff->ep) - return fz_throw("strip extends beyond the end of the file"); - - /* the bits are in un-natural order */ - if (tiff->fillorder == 2) - for (i = 0; i < rlen; i++) - rp[i] = bitrev[rp[i]]; - - /* the strip decoders will close this */ - stm = fz_open_memory(rp, rlen); - - switch (tiff->compression) - { - case 1: - error = xps_decode_tiff_uncompressed(tiff, stm, wp, wlen); - break; - case 2: - error = xps_decode_tiff_fax(tiff, 2, stm, wp, wlen); - break; - case 3: - error = xps_decode_tiff_fax(tiff, 3, stm, wp, wlen); - break; - case 4: - error = xps_decode_tiff_fax(tiff, 4, stm, wp, wlen); - break; - case 5: - error = xps_decode_tiff_lzw(tiff, stm, wp, wlen); - break; - case 6: - error = fz_throw("deprecated JPEG in TIFF compression not supported"); - break; - case 7: - error = xps_decode_tiff_jpeg(tiff, stm, wp, wlen); - break; - case 8: - error = xps_decode_tiff_flate(tiff, stm, wp, wlen); - break; - case 32773: - error = xps_decode_tiff_packbits(tiff, stm, wp, wlen); - break; - default: - error = fz_throw("unknown TIFF compression: %d", tiff->compression); - } - - if (error) - return fz_rethrow(error, "cannot decode strip %d", row / tiff->rowsperstrip); - - /* scramble the bits back into original order */ - if (tiff->fillorder == 2) - for (i = 0; i < rlen; i++) - rp[i] = bitrev[rp[i]]; - - wp += tiff->stride * tiff->rowsperstrip; - strip ++; - } - - /* Predictor (only for LZW and Flate) */ - if ((tiff->compression == 5 || tiff->compression == 8) && tiff->predictor == 2) - { - byte *p = tiff->samples; - for (i = 0; i < tiff->imagelength; i++) - { - xps_unpredict_tiff(p, tiff->imagewidth, tiff->samplesperpixel, tiff->bitspersample); - p += tiff->stride; - } - } - - /* RGBPal */ - if (tiff->photometric == 3 && tiff->colormap) - { - error = xps_expand_tiff_colormap(tiff); - if (error) - return fz_rethrow(error, "cannot expand colormap"); - } - - /* WhiteIsZero .. invert */ - if (tiff->photometric == 0) - { - byte *p = tiff->samples; - for (i = 0; i < tiff->imagelength; i++) - { - xps_invert_tiff(p, tiff->imagewidth, tiff->samplesperpixel, tiff->bitspersample, tiff->extrasamples); - p += tiff->stride; - } - } - - return fz_okay; -} - -static inline int readbyte(struct tiff *tiff) -{ - if (tiff->rp < tiff->ep) - return *tiff->rp++; - return EOF; -} - -static inline unsigned readshort(struct tiff *tiff) -{ - unsigned a = readbyte(tiff); - unsigned b = readbyte(tiff); - if (tiff->order == TII) - return (b << 8) | a; - return (a << 8) | b; -} - -static inline unsigned readlong(struct tiff *tiff) -{ - unsigned a = readbyte(tiff); - unsigned b = readbyte(tiff); - unsigned c = readbyte(tiff); - unsigned d = readbyte(tiff); - if (tiff->order == TII) - return (d << 24) | (c << 16) | (b << 8) | a; - return (a << 24) | (b << 16) | (c << 8) | d; -} - -static void -xps_read_tiff_bytes(unsigned char *p, struct tiff *tiff, unsigned ofs, unsigned n) -{ - tiff->rp = tiff->bp + ofs; - if (tiff->rp > tiff->ep) - tiff->rp = tiff->bp; - - while (n--) - *p++ = readbyte(tiff); -} - -static void -xps_read_tiff_tag_value(unsigned *p, struct tiff *tiff, unsigned type, unsigned ofs, unsigned n) -{ - tiff->rp = tiff->bp + ofs; - if (tiff->rp > tiff->ep) - tiff->rp = tiff->bp; - - while (n--) - { - switch (type) - { - case TRATIONAL: - *p = readlong(tiff); - *p = *p / readlong(tiff); - p ++; - break; - case TBYTE: *p++ = readbyte(tiff); break; - case TSHORT: *p++ = readshort(tiff); break; - case TLONG: *p++ = readlong(tiff); break; - default: *p++ = 0; break; - } - } -} - -static int -xps_read_tiff_tag(struct tiff *tiff, unsigned offset) -{ - unsigned tag; - unsigned type; - unsigned count; - unsigned value; - - tiff->rp = tiff->bp + offset; - - tag = readshort(tiff); - type = readshort(tiff); - count = readlong(tiff); - - if ((type == TBYTE && count <= 4) || - (type == TSHORT && count <= 2) || - (type == TLONG && count <= 1)) - value = tiff->rp - tiff->bp; - else - value = readlong(tiff); - - switch (tag) - { - case NewSubfileType: - xps_read_tiff_tag_value(&tiff->subfiletype, tiff, type, value, 1); - break; - case ImageWidth: - xps_read_tiff_tag_value(&tiff->imagewidth, tiff, type, value, 1); - break; - case ImageLength: - xps_read_tiff_tag_value(&tiff->imagelength, tiff, type, value, 1); - break; - case BitsPerSample: - xps_read_tiff_tag_value(&tiff->bitspersample, tiff, type, value, 1); - break; - case Compression: - xps_read_tiff_tag_value(&tiff->compression, tiff, type, value, 1); - break; - case PhotometricInterpretation: - xps_read_tiff_tag_value(&tiff->photometric, tiff, type, value, 1); - break; - case FillOrder: - xps_read_tiff_tag_value(&tiff->fillorder, tiff, type, value, 1); - break; - case SamplesPerPixel: - xps_read_tiff_tag_value(&tiff->samplesperpixel, tiff, type, value, 1); - break; - case RowsPerStrip: - xps_read_tiff_tag_value(&tiff->rowsperstrip, tiff, type, value, 1); - break; - case XResolution: - xps_read_tiff_tag_value(&tiff->xresolution, tiff, type, value, 1); - break; - case YResolution: - xps_read_tiff_tag_value(&tiff->yresolution, tiff, type, value, 1); - break; - case PlanarConfiguration: - xps_read_tiff_tag_value(&tiff->planar, tiff, type, value, 1); - break; - case T4Options: - xps_read_tiff_tag_value(&tiff->g3opts, tiff, type, value, 1); - break; - case T6Options: - xps_read_tiff_tag_value(&tiff->g4opts, tiff, type, value, 1); - break; - case Predictor: - xps_read_tiff_tag_value(&tiff->predictor, tiff, type, value, 1); - break; - case ResolutionUnit: - xps_read_tiff_tag_value(&tiff->resolutionunit, tiff, type, value, 1); - break; - case YCbCrSubSampling: - xps_read_tiff_tag_value(tiff->ycbcrsubsamp, tiff, type, value, 2); - break; - case ExtraSamples: - xps_read_tiff_tag_value(&tiff->extrasamples, tiff, type, value, 1); - break; - - case ICCProfile: - tiff->profile = fz_malloc(count); - /* 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); - tiff->profilesize = count; - break; - - case JPEGTables: - fz_warn("jpeg tables in tiff not implemented"); - tiff->jpegtables = tiff->bp + value; - tiff->jpegtableslen = count; - break; - - case StripOffsets: - tiff->stripoffsets = fz_calloc(count, sizeof(unsigned)); - xps_read_tiff_tag_value(tiff->stripoffsets, tiff, type, value, count); - break; - - case StripByteCounts: - tiff->stripbytecounts = fz_calloc(count, sizeof(unsigned)); - xps_read_tiff_tag_value(tiff->stripbytecounts, tiff, type, value, count); - break; - - case ColorMap: - tiff->colormap = fz_calloc(count, sizeof(unsigned)); - xps_read_tiff_tag_value(tiff->colormap, tiff, type, value, count); - break; - - case TileWidth: - case TileLength: - case TileOffsets: - case TileByteCounts: - return fz_throw("tiled tiffs not supported"); - - default: - /* printf("unknown tag: %d t=%d n=%d\n", tag, type, count); */ - break; - } - - return fz_okay; -} - -static void -xps_swap_byte_order(byte *buf, int n) -{ - int i, t; - for (i = 0; i < n; i++) - { - t = buf[i * 2 + 0]; - buf[i * 2 + 0] = buf[i * 2 + 1]; - buf[i * 2 + 1] = t; - } -} - -static int -xps_decode_tiff_header(struct tiff *tiff, byte *buf, int len) -{ - unsigned version; - unsigned offset; - unsigned count; - unsigned i; - int error; - - memset(tiff, 0, sizeof(struct tiff)); - - tiff->bp = buf; - tiff->rp = buf; - tiff->ep = buf + len; - - /* tag defaults, where applicable */ - tiff->bitspersample = 1; - tiff->compression = 1; - tiff->samplesperpixel = 1; - tiff->resolutionunit = 2; - tiff->rowsperstrip = 0xFFFFFFFF; - tiff->fillorder = 1; - tiff->planar = 1; - tiff->subfiletype = 0; - tiff->predictor = 1; - tiff->ycbcrsubsamp[0] = 2; - tiff->ycbcrsubsamp[1] = 2; - - /* - * Read IFH - */ - - /* get byte order marker */ - tiff->order = TII; - tiff->order = readshort(tiff); - if (tiff->order != TII && tiff->order != TMM) - return fz_throw("not a TIFF file, wrong magic marker"); - - /* check version */ - version = readshort(tiff); - if (version != 42) - return fz_throw("not a TIFF file, wrong version marker"); - - /* get offset of IFD */ - offset = readlong(tiff); - - /* - * Read IFD - */ - - tiff->rp = tiff->bp + offset; - - count = readshort(tiff); - - offset += 2; - for (i = 0; i < count; i++) - { - error = xps_read_tiff_tag(tiff, offset); - if (error) - return fz_rethrow(error, "cannot read TIFF header tag"); - offset += 12; - } - - return fz_okay; -} - -int -xps_decode_tiff(fz_pixmap **imagep, byte *buf, int len) -{ - int error; - fz_pixmap *image; - struct tiff tiff; - - error = xps_decode_tiff_header(&tiff, buf, len); - if (error) - return fz_rethrow(error, "cannot decode tiff header"); - - /* Decode the image strips */ - - if (tiff.rowsperstrip > tiff.imagelength) - tiff.rowsperstrip = tiff.imagelength; - - error = xps_decode_tiff_strips(&tiff); - if (error) - return fz_rethrow(error, "cannot decode image data"); - - /* Byte swap 16-bit images to big endian if necessary */ - if (tiff.bitspersample == 16) - { - if (tiff.order == TII) - xps_swap_byte_order(tiff.samples, tiff.imagewidth * tiff.imagelength * tiff.samplesperpixel); - } - - /* Expand into fz_pixmap struct */ - - image = fz_new_pixmap_with_limit(tiff.colorspace, tiff.imagewidth, tiff.imagelength); - if (!image) - { - if (tiff.colormap) fz_free(tiff.colormap); - if (tiff.stripoffsets) fz_free(tiff.stripoffsets); - if (tiff.stripbytecounts) fz_free(tiff.stripbytecounts); - if (tiff.samples) fz_free(tiff.samples); - return fz_throw("out of memory"); - } - - image->xres = tiff.xresolution; - image->yres = tiff.yresolution; - - fz_unpack_tile(image, tiff.samples, tiff.samplesperpixel, tiff.bitspersample, tiff.stride, 0); - - /* We should only do this on non-pre-multiplied images, but files in the wild are bad */ - if (tiff.extrasamples /* == 2 */) - { - /* CMYK is a subtractive colorspace, we want additive for premul alpha */ - if (image->n == 5) - { - fz_pixmap *rgb = fz_new_pixmap(fz_device_rgb, image->w, image->h); - fz_convert_pixmap(image, rgb); - rgb->xres = image->xres; - rgb->yres = image->yres; - fz_drop_pixmap(image); - image = rgb; - } - fz_premultiply_pixmap(image); - } - - /* Clean up scratch memory */ - - if (tiff.colormap) fz_free(tiff.colormap); - if (tiff.stripoffsets) fz_free(tiff.stripoffsets); - if (tiff.stripbytecounts) fz_free(tiff.stripbytecounts); - if (tiff.samples) fz_free(tiff.samples); - - *imagep = image; - return fz_okay; -} diff --git a/contrib/media/updf/xps/xps_tile.c b/contrib/media/updf/xps/xps_tile.c deleted file mode 100644 index 0ea271c85f..0000000000 --- a/contrib/media/updf/xps/xps_tile.c +++ /dev/null @@ -1,365 +0,0 @@ -#include "fitz.h" -#include "muxps.h" - -#define TILE - -/* - * Parse a tiling brush (visual and image brushes at this time) common - * properties. Use the callback to draw the individual tiles. - */ - -enum { TILE_NONE, TILE_TILE, TILE_FLIP_X, TILE_FLIP_Y, TILE_FLIP_X_Y }; - -struct closure -{ - char *base_uri; - xps_resource *dict; - xml_element *root; - void *user; - void (*func)(xps_context*, fz_matrix, fz_rect, char*, xps_resource*, xml_element*, void*); -}; - -static void -xps_paint_tiling_brush_clipped(xps_context *ctx, fz_matrix ctm, fz_rect viewbox, struct closure *c) -{ - fz_path *path = fz_new_path(); - fz_moveto(path, viewbox.x0, viewbox.y0); - fz_lineto(path, viewbox.x0, viewbox.y1); - fz_lineto(path, viewbox.x1, viewbox.y1); - fz_lineto(path, viewbox.x1, viewbox.y0); - fz_closepath(path); - fz_clip_path(ctx->dev, path, NULL, 0, ctm); - fz_free_path(path); - c->func(ctx, ctm, viewbox, c->base_uri, c->dict, c->root, c->user); - fz_pop_clip(ctx->dev); -} - -static void -xps_paint_tiling_brush(xps_context *ctx, fz_matrix ctm, fz_rect viewbox, int tile_mode, struct closure *c) -{ - fz_matrix ttm; - - xps_paint_tiling_brush_clipped(ctx, ctm, viewbox, c); - - if (tile_mode == TILE_FLIP_X || tile_mode == TILE_FLIP_X_Y) - { - ttm = fz_concat(fz_translate(viewbox.x1 * 2, 0), ctm); - ttm = fz_concat(fz_scale(-1, 1), ttm); - xps_paint_tiling_brush_clipped(ctx, ttm, viewbox, c); - } - - if (tile_mode == TILE_FLIP_Y || tile_mode == TILE_FLIP_X_Y) - { - ttm = fz_concat(fz_translate(0, viewbox.y1 * 2), ctm); - ttm = fz_concat(fz_scale(1, -1), ttm); - xps_paint_tiling_brush_clipped(ctx, ttm, viewbox, c); - } - - if (tile_mode == TILE_FLIP_X_Y) - { - ttm = fz_concat(fz_translate(viewbox.x1 * 2, viewbox.y1 * 2), ctm); - ttm = fz_concat(fz_scale(-1, -1), ttm); - xps_paint_tiling_brush_clipped(ctx, ttm, viewbox, c); - } -} - -void -xps_parse_tiling_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, - char *base_uri, xps_resource *dict, xml_element *root, - void (*func)(xps_context*, fz_matrix, fz_rect, char*, xps_resource*, xml_element*, void*), void *user) -{ - xml_element *node; - struct closure c; - - char *opacity_att; - char *transform_att; - char *viewbox_att; - char *viewport_att; - char *tile_mode_att; - char *viewbox_units_att; - char *viewport_units_att; - - xml_element *transform_tag = NULL; - - fz_matrix transform; - fz_rect viewbox; - fz_rect viewport; - float xstep, ystep; - float xscale, yscale; - int tile_mode; - - opacity_att = xml_att(root, "Opacity"); - transform_att = xml_att(root, "Transform"); - viewbox_att = xml_att(root, "Viewbox"); - viewport_att = xml_att(root, "Viewport"); - tile_mode_att = xml_att(root, "TileMode"); - viewbox_units_att = xml_att(root, "ViewboxUnits"); - viewport_units_att = xml_att(root, "ViewportUnits"); - - c.base_uri = base_uri; - c.dict = dict; - c.root = root; - c.user = user; - c.func = func; - - for (node = xml_down(root); node; node = xml_next(node)) - { - if (!strcmp(xml_tag(node), "ImageBrush.Transform")) - transform_tag = xml_down(node); - if (!strcmp(xml_tag(node), "VisualBrush.Transform")) - transform_tag = xml_down(node); - } - - xps_resolve_resource_reference(ctx, dict, &transform_att, &transform_tag, NULL); - - 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(transform, ctm); - - viewbox = fz_unit_rect; - if (viewbox_att) - xps_parse_rectangle(ctx, viewbox_att, &viewbox); - - viewport = fz_unit_rect; - if (viewport_att) - xps_parse_rectangle(ctx, viewport_att, &viewport); - - /* some sanity checks on the viewport/viewbox size */ - if (fabsf(viewport.x1 - viewport.x0) < 0.01f) return; - if (fabsf(viewport.y1 - viewport.y0) < 0.01f) return; - if (fabsf(viewbox.x1 - viewbox.x0) < 0.01f) return; - if (fabsf(viewbox.y1 - viewbox.y0) < 0.01f) return; - - xstep = viewbox.x1 - viewbox.x0; - ystep = viewbox.y1 - viewbox.y0; - - xscale = (viewport.x1 - viewport.x0) / xstep; - yscale = (viewport.y1 - viewport.y0) / ystep; - - tile_mode = TILE_NONE; - if (tile_mode_att) - { - if (!strcmp(tile_mode_att, "None")) - tile_mode = TILE_NONE; - if (!strcmp(tile_mode_att, "Tile")) - tile_mode = TILE_TILE; - if (!strcmp(tile_mode_att, "FlipX")) - tile_mode = TILE_FLIP_X; - if (!strcmp(tile_mode_att, "FlipY")) - tile_mode = TILE_FLIP_Y; - if (!strcmp(tile_mode_att, "FlipXY")) - tile_mode = TILE_FLIP_X_Y; - } - - if (tile_mode == TILE_FLIP_X || tile_mode == TILE_FLIP_X_Y) - xstep *= 2; - if (tile_mode == TILE_FLIP_Y || tile_mode == TILE_FLIP_X_Y) - ystep *= 2; - - xps_begin_opacity(ctx, ctm, area, base_uri, dict, opacity_att, NULL); - - ctm = fz_concat(fz_translate(viewport.x0, viewport.y0), ctm); - ctm = fz_concat(fz_scale(xscale, yscale), ctm); - ctm = fz_concat(fz_translate(-viewbox.x0, -viewbox.y0), ctm); - - if (tile_mode != TILE_NONE) - { - int x0, y0, x1, y1; - fz_matrix invctm = fz_invert_matrix(ctm); - area = fz_transform_rect(invctm, area); - x0 = floorf(area.x0 / xstep); - y0 = floorf(area.y0 / ystep); - x1 = ceilf(area.x1 / xstep); - y1 = ceilf(area.y1 / ystep); - -#ifdef TILE - { - int n = (x1 - x0) * (y1 - y0); - fz_rect bigview = viewbox; - bigview.x1 = bigview.x0 + xstep; - bigview.y1 = bigview.y0 + ystep; - if (n > 1) - fz_begin_tile(ctx->dev, area, bigview, xstep, ystep, ctm); - if (n > 0) - xps_paint_tiling_brush(ctx, ctm, viewbox, tile_mode, &c); - if (n > 1) - fz_end_tile(ctx->dev); - } -#else - { - int x, y; - for (y = y0; y < y1; y++) - { - for (x = x0; x < x1; x++) - { - fz_matrix ttm = fz_concat(fz_translate(xstep * x, ystep * y), ctm); - xps_paint_tiling_brush(ctx, ttm, viewbox, tile_mode, &c); - } - } - } -#endif - } - else - { - xps_paint_tiling_brush(ctx, ctm, viewbox, tile_mode, &c); - } - - xps_end_opacity(ctx, base_uri, dict, opacity_att, NULL); -} - -static void -xps_paint_visual_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, - char *base_uri, xps_resource *dict, xml_element *root, void *visual_tag) -{ - xps_parse_element(ctx, ctm, area, base_uri, dict, (xml_element *)visual_tag); -} - -void -xps_parse_visual_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, - char *base_uri, xps_resource *dict, xml_element *root) -{ - xml_element *node; - - char *visual_uri; - char *visual_att; - xml_element *visual_tag = NULL; - - visual_att = xml_att(root, "Visual"); - - for (node = xml_down(root); node; node = xml_next(node)) - { - if (!strcmp(xml_tag(node), "VisualBrush.Visual")) - visual_tag = xml_down(node); - } - - visual_uri = base_uri; - xps_resolve_resource_reference(ctx, dict, &visual_att, &visual_tag, &visual_uri); - - if (visual_tag) - { - xps_parse_tiling_brush(ctx, ctm, area, - visual_uri, dict, root, xps_paint_visual_brush, visual_tag); - } -} - -void -xps_parse_canvas(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *root) -{ - xps_resource *new_dict = NULL; - xml_element *node; - char *opacity_mask_uri; - int code; - - char *transform_att; - char *clip_att; - char *opacity_att; - char *opacity_mask_att; - - xml_element *transform_tag = NULL; - xml_element *clip_tag = NULL; - xml_element *opacity_mask_tag = NULL; - - fz_matrix transform; - - transform_att = xml_att(root, "RenderTransform"); - clip_att = xml_att(root, "Clip"); - opacity_att = xml_att(root, "Opacity"); - opacity_mask_att = xml_att(root, "OpacityMask"); - - for (node = xml_down(root); node; node = xml_next(node)) - { - if (!strcmp(xml_tag(node), "Canvas.Resources") && xml_down(node)) - { - code = xps_parse_resource_dictionary(ctx, &new_dict, base_uri, xml_down(node)); - if (code) - fz_catch(code, "cannot load Canvas.Resources"); - else - { - new_dict->parent = dict; - dict = new_dict; - } - } - - if (!strcmp(xml_tag(node), "Canvas.RenderTransform")) - transform_tag = xml_down(node); - if (!strcmp(xml_tag(node), "Canvas.Clip")) - clip_tag = xml_down(node); - if (!strcmp(xml_tag(node), "Canvas.OpacityMask")) - opacity_mask_tag = xml_down(node); - } - - opacity_mask_uri = base_uri; - xps_resolve_resource_reference(ctx, dict, &transform_att, &transform_tag, NULL); - 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); - - 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(transform, ctm); - - if (clip_att || clip_tag) - xps_clip(ctx, ctm, dict, clip_att, clip_tag); - - xps_begin_opacity(ctx, ctm, area, opacity_mask_uri, dict, opacity_att, opacity_mask_tag); - - for (node = xml_down(root); node; node = xml_next(node)) - { - xps_parse_element(ctx, ctm, area, base_uri, dict, node); - } - - xps_end_opacity(ctx, opacity_mask_uri, dict, opacity_att, opacity_mask_tag); - - if (clip_att || clip_tag) - fz_pop_clip(ctx->dev); - - if (new_dict) - xps_free_resource_dictionary(ctx, new_dict); -} - -void -xps_parse_fixed_page(xps_context *ctx, fz_matrix ctm, xps_page *page) -{ - xml_element *node; - xps_resource *dict; - char base_uri[1024]; - fz_rect area; - char *s; - int code; - - fz_strlcpy(base_uri, page->name, sizeof base_uri); - s = strrchr(base_uri, '/'); - if (s) - s[1] = 0; - - dict = NULL; - - ctx->opacity_top = 0; - ctx->opacity[0] = 1; - - if (!page->root) - return; - - area = fz_transform_rect(fz_scale(page->width, page->height), fz_unit_rect); - - for (node = xml_down(page->root); node; node = xml_next(node)) - { - if (!strcmp(xml_tag(node), "FixedPage.Resources") && xml_down(node)) - { - code = xps_parse_resource_dictionary(ctx, &dict, base_uri, xml_down(node)); - if (code) - fz_catch(code, "cannot load FixedPage.Resources"); - } - xps_parse_element(ctx, ctm, area, base_uri, dict, node); - } - - if (dict) - { - xps_free_resource_dictionary(ctx, dict); - } -} diff --git a/contrib/media/updf/xps/xps_util.c b/contrib/media/updf/xps/xps_util.c deleted file mode 100644 index d6e226b56a..0000000000 --- a/contrib/media/updf/xps/xps_util.c +++ /dev/null @@ -1,94 +0,0 @@ -#include "fitz.h" -#include "muxps.h" - -static inline int xps_tolower(int c) -{ - if (c >= 'A' && c <= 'Z') - return c + 32; - return 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); -} - -#define SEP(x) ((x)=='/' || (x) == 0) - -static char * -xps_clean_path(char *name) -{ - char *p, *q, *dotdot; - int rooted; - - rooted = name[0] == '/'; - - /* - * invariants: - * p points at beginning of path element we're considering. - * q points just past the last path element we wrote (no slash). - * dotdot points just past the point where .. cannot backtrack - * any further (no slash). - */ - p = q = dotdot = name + rooted; - while (*p) - { - if(p[0] == '/') /* null element */ - p++; - else if (p[0] == '.' && SEP(p[1])) - p += 1; /* don't count the separator in case it is nul */ - else if (p[0] == '.' && p[1] == '.' && SEP(p[2])) - { - p += 2; - if (q > dotdot) /* can backtrack */ - { - while(--q > dotdot && *q != '/') - ; - } - else if (!rooted) /* /.. is / but ./../ is .. */ - { - if (q != name) - *q++ = '/'; - *q++ = '.'; - *q++ = '.'; - dotdot = q; - } - } - else /* real path element */ - { - if (q != name+rooted) - *q++ = '/'; - while ((*q = *p) != '/' && *q != 0) - p++, q++; - } - } - - if (q == name) /* empty string is really "." */ - *q++ = '.'; - *q = '\0'; - - return name; -} - -void -xps_absolute_path(char *output, char *base_uri, char *path, int output_size) -{ - if (path[0] == '/') - { - fz_strlcpy(output, path, output_size); - } - else - { - fz_strlcpy(output, base_uri, output_size); - fz_strlcat(output, "/", output_size); - fz_strlcat(output, path, output_size); - } - xps_clean_path(output); -} diff --git a/contrib/media/updf/xps/xps_xml.c b/contrib/media/updf/xps/xps_xml.c deleted file mode 100644 index 8448ecef4f..0000000000 --- a/contrib/media/updf/xps/xps_xml.c +++ /dev/null @@ -1,387 +0,0 @@ -#include "fitz.h" -#include "muxps.h" - -struct attribute -{ - char name[40]; - char *value; - struct attribute *next; -}; - -struct element -{ - char name[40]; - struct attribute *atts; - struct element *up, *down, *next; -}; - -struct parser -{ - struct element *head; -}; - -static inline void indent(int n) -{ - while (n--) putchar(' '); -} - -void xml_print_element(struct element *item, int level) -{ - while (item) { - struct attribute *att; - indent(level); - printf("<%s", item->name); - for (att = item->atts; att; att = att->next) - printf(" %s=\"%s\"", att->name, att->value); - if (item->down) { - printf(">\n"); - xml_print_element(item->down, level + 1); - indent(level); - printf("\n", item->name); - } - else { - printf("/>\n"); - } - item = item->next; - } -} - -struct element *xml_next(struct element *item) -{ - return item->next; -} - -struct element *xml_down(struct element *item) -{ - return item->down; -} - -char *xml_tag(struct element *item) -{ - return item->name; -} - -char *xml_att(struct element *item, const char *name) -{ - struct attribute *att; - for (att = item->atts; att; att = att->next) - if (!strcmp(att->name, name)) - return att->value; - return NULL; -} - -static void xml_free_attribute(struct attribute *att) -{ - while (att) { - struct attribute *next = att->next; - if (att->value) - fz_free(att->value); - fz_free(att); - att = next; - } -} - -void xml_free_element(struct element *item) -{ - while (item) { - struct element *next = item->next; - if (item->atts) - xml_free_attribute(item->atts); - if (item->down) - xml_free_element(item->down); - fz_free(item); - item = next; - } -} - -static int xml_parse_entity(int *c, char *a) -{ - char *b; - if (a[1] == '#') { - if (a[2] == 'x') - *c = strtol(a + 3, &b, 16); - else - *c = strtol(a + 2, &b, 10); - if (*b == ';') - return b - a + 1; - } - else if (a[1] == 'l' && a[2] == 't' && a[3] == ';') { - *c = '<'; - return 4; - } - else if (a[1] == 'g' && a[2] == 't' && a[3] == ';') { - *c = '>'; - return 4; - } - else if (a[1] == 'a' && a[2] == 'm' && a[3] == 'p' && a[4] == ';') { - *c = '&'; - return 5; - } - else if (a[1] == 'a' && a[2] == 'p' && a[3] == 'o' && a[4] == 's' && a[5] == ';') { - *c = '\''; - return 6; - } - else if (a[1] == 'q' && a[2] == 'u' && a[3] == 'o' && a[4] == 't' && a[5] == ';') { - *c = '"'; - return 6; - } - *c = *a++; - return 1; -} - -static void xml_emit_open_tag(struct parser *parser, char *a, char *b) -{ - struct element *head, *tail; - - head = fz_malloc(sizeof(struct element)); - if (b - a > sizeof(head->name)) - b = a + sizeof(head->name); - memcpy(head->name, a, b - a); - head->name[b - a] = 0; - - head->atts = NULL; - head->up = parser->head; - head->down = NULL; - head->next = NULL; - - if (!parser->head->down) { - parser->head->down = head; - } - else { - tail = parser->head->down; - while (tail->next) - tail = tail->next; - tail->next = head; - } - - parser->head = head; -} - -static void xml_emit_att_name(struct parser *parser, char *a, char *b) -{ - struct element *head = parser->head; - struct attribute *att; - - att = fz_malloc(sizeof(struct attribute)); - if (b - a > sizeof(att->name)) - b = a + sizeof(att->name); - memcpy(att->name, a, b - a); - att->name[b - a] = 0; - att->value = NULL; - att->next = head->atts; - head->atts = att; -} - -static void xml_emit_att_value(struct parser *parser, char *a, char *b) -{ - struct element *head = parser->head; - struct attribute *att = head->atts; - char *s; - int c; - - /* entities are all longer than UTFmax so runetochar is safe */ - s = att->value = fz_malloc(b - a + 1); - while (a < b) { - if (*a == '&') { - a += xml_parse_entity(&c, a); - s += runetochar(s, &c); - } - else { - *s++ = *a++; - } - } - *s = 0; -} - -static void xml_emit_close_tag(struct parser *parser) -{ - if (parser->head->up) - parser->head = parser->head->up; -} - -static inline int isname(int c) -{ - return c == '.' || c == '-' || c == '_' || c == ':' || - (c >= '0' && c <= '9') || - (c >= 'A' && c <= 'Z') || - (c >= 'a' && c <= 'z'); -} - -static inline int iswhite(int c) -{ - return c == ' ' || c == '\r' || c == '\n' || c == '\t'; -} - -static char *xml_parse_document_imp(struct parser *x, char *p) -{ - char *mark; - int quote; - -parse_text: - mark = p; - while (*p && *p != '<') ++p; - if (*p == '<') { ++p; goto parse_element; } - return NULL; - -parse_element: - if (*p == '/') { ++p; goto parse_closing_element; } - if (*p == '!') { ++p; goto parse_comment; } - if (*p == '?') { ++p; goto parse_processing_instruction; } - while (iswhite(*p)) ++p; - if (isname(*p)) - goto parse_element_name; - return "syntax error in element"; - -parse_comment: - if (*p == '[') goto parse_cdata; - if (*p++ != '-') return "syntax error in comment (') { - p += 3; - goto parse_text; - } - ++p; - } - return "end of data in comment"; - -parse_cdata: - if (p[1] != 'C' || p[2] != 'D' || p[3] != 'A' || p[4] != 'T' || p[5] != 'A' || p[6] != '[') - return "syntax error in CDATA section"; - p += 7; - mark = p; - while (*p) { - if (p[0] == ']' && p[1] == ']' && p[2] == '>') { - p += 3; - goto parse_text; - } - ++p; - } - return "end of data in CDATA section"; - -parse_processing_instruction: - while (*p) { - if (p[0] == '?' && p[1] == '>') { - p += 2; - goto parse_text; - } - ++p; - } - return "end of data in processing instruction"; - -parse_closing_element: - while (iswhite(*p)) ++p; - mark = p; - while (isname(*p)) ++p; - while (iswhite(*p)) ++p; - if (*p != '>') - return "syntax error in closing element"; - xml_emit_close_tag(x); - ++p; - goto parse_text; - -parse_element_name: - mark = p; - while (isname(*p)) ++p; - xml_emit_open_tag(x, mark, p); - if (*p == '>') { ++p; goto parse_text; } - if (p[0] == '/' && p[1] == '>') { - xml_emit_close_tag(x); - p += 2; - goto parse_text; - } - if (iswhite(*p)) - goto parse_attributes; - return "syntax error after element name"; - -parse_attributes: - while (iswhite(*p)) ++p; - if (isname(*p)) - goto parse_attribute_name; - if (*p == '>') { ++p; goto parse_text; } - if (p[0] == '/' && p[1] == '>') { - xml_emit_close_tag(x); - p += 2; - goto parse_text; - } - return "syntax error in attributes"; - -parse_attribute_name: - mark = p; - while (isname(*p)) ++p; - xml_emit_att_name(x, mark, p); - while (iswhite(*p)) ++p; - if (*p == '=') { ++p; goto parse_attribute_value; } - return "syntax error after attribute name"; - -parse_attribute_value: - while (iswhite(*p)) ++p; - quote = *p++; - if (quote != '"' && quote != '\'') - return "missing quote character"; - mark = p; - while (*p && *p != quote) ++p; - if (*p == quote) { - xml_emit_att_value(x, mark, p++); - goto parse_attributes; - } - return "end of data in attribute value"; -} - -static char *convert_to_utf8(unsigned char *s, int n) -{ - unsigned char *e = s + n; - char *dst, *d; - int c; - - if (s[0] == 0xFE && s[1] == 0xFF) { - dst = d = fz_malloc(n * 2); - while (s + 1 < e) { - c = s[0] << 8 | s[1]; - d += runetochar(d, &c); - s += 2; - } - *d = 0; - return dst; - } - - if (s[0] == 0xFF && s[1] == 0xFE) { - dst = d = fz_malloc(n * 2); - while (s + 1 < e) { - c = s[0] | s[1] << 8; - d += runetochar(d, &c); - s += 2; - } - *d = 0; - return dst; - } - - return (char*)s; -} - -struct element * -xml_parse_document(unsigned char *s, int n) -{ - struct parser parser; - struct element root; - char *p, *error; - - /* s is already null-terminated (see xps_new_part) */ - - memset(&root, 0, sizeof(root)); - parser.head = &root; - - p = convert_to_utf8(s, n); - - error = xml_parse_document_imp(&parser, p); - if (error) { - fz_throw(error); - return NULL; - } - - if (p != (char*)s) - fz_free(p); - - return root.down; -} diff --git a/contrib/media/updf/xps/xps_zip.c b/contrib/media/updf/xps/xps_zip.c deleted file mode 100644 index a0c981bff2..0000000000 --- a/contrib/media/updf/xps/xps_zip.c +++ /dev/null @@ -1,501 +0,0 @@ -#include "fitz.h" -#include "muxps.h" - -#include - -xps_part * -xps_new_part(xps_context *ctx, char *name, int size) -{ - xps_part *part; - - part = fz_malloc(sizeof(xps_part)); - part->name = fz_strdup(name); - part->size = size; - part->data = fz_malloc(size + 1); - part->data[size] = 0; /* null-terminate for xml parser */ - - return part; -} - -void -xps_free_part(xps_context *ctx, xps_part *part) -{ - fz_free(part->name); - fz_free(part->data); - fz_free(part); -} - -static inline int getshort(fz_stream *file) -{ - int a = fz_read_byte(file); - int b = fz_read_byte(file); - return a | b << 8; -} - -static inline int getlong(fz_stream *file) -{ - int a = fz_read_byte(file); - int b = fz_read_byte(file); - int c = fz_read_byte(file); - int d = fz_read_byte(file); - return a | b << 8 | c << 16 | d << 24; -} - -static void * -xps_zip_alloc_items(xps_context *ctx, int items, int size) -{ - return fz_calloc(items, size); -} - -static void -xps_zip_free(xps_context *ctx, void *ptr) -{ - fz_free(ptr); -} - -static int -xps_compare_entries(const void *a0, const void *b0) -{ - xps_entry *a = (xps_entry*) a0; - xps_entry *b = (xps_entry*) b0; - return xps_strcasecmp(a->name, b->name); -} - -static xps_entry * -xps_find_zip_entry(xps_context *ctx, char *name) -{ - int l = 0; - int r = ctx->zip_count - 1; - while (l <= r) - { - int m = (l + r) >> 1; - int c = xps_strcasecmp(name, ctx->zip_table[m].name); - if (c < 0) - r = m - 1; - else if (c > 0) - l = m + 1; - else - return &ctx->zip_table[m]; - } - return NULL; -} - -static int -xps_read_zip_entry(xps_context *ctx, xps_entry *ent, unsigned char *outbuf) -{ - z_stream stream; - unsigned char *inbuf; - int sig; - int version, general, method; - int namelength, extralength; - int code; - - fz_seek(ctx->file, ent->offset, 0); - - sig = getlong(ctx->file); - if (sig != ZIP_LOCAL_FILE_SIG) - return fz_throw("wrong zip local file signature (0x%x)", sig); - - version = getshort(ctx->file); - general = getshort(ctx->file); - method = getshort(ctx->file); - (void) getshort(ctx->file); /* file time */ - (void) getshort(ctx->file); /* file date */ - (void) getlong(ctx->file); /* crc-32 */ - (void) getlong(ctx->file); /* csize */ - (void) getlong(ctx->file); /* usize */ - namelength = getshort(ctx->file); - extralength = getshort(ctx->file); - - fz_seek(ctx->file, namelength + extralength, 1); - - if (method == 0) - { - fz_read(ctx->file, outbuf, ent->usize); - } - else if (method == 8) - { - inbuf = fz_malloc(ent->csize); - - fz_read(ctx->file, inbuf, ent->csize); - - memset(&stream, 0, sizeof(z_stream)); - stream.zalloc = (alloc_func) xps_zip_alloc_items; - stream.zfree = (free_func) xps_zip_free; - stream.opaque = ctx; - stream.next_in = inbuf; - stream.avail_in = ent->csize; - stream.next_out = outbuf; - stream.avail_out = ent->usize; - - code = inflateInit2(&stream, -15); - if (code != Z_OK) - return fz_throw("zlib inflateInit2 error: %s", stream.msg); - code = inflate(&stream, Z_FINISH); - if (code != Z_STREAM_END) - { - inflateEnd(&stream); - return fz_throw("zlib inflate error: %s", stream.msg); - } - code = inflateEnd(&stream); - if (code != Z_OK) - return fz_throw("zlib inflateEnd error: %s", stream.msg); - - fz_free(inbuf); - } - else - { - return fz_throw("unknown compression method (%d)", method); - } - - return fz_okay; -} - -/* - * Read the central directory in a zip file. - */ - -static int -xps_read_zip_dir(xps_context *ctx, int start_offset) -{ - int sig; - int offset, count; - int namesize, metasize, commentsize; - int i; - - fz_seek(ctx->file, start_offset, 0); - - sig = getlong(ctx->file); - if (sig != ZIP_END_OF_CENTRAL_DIRECTORY_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 */ - (void) getshort(ctx->file); /* entries in this disk */ - count = getshort(ctx->file); /* entries in central directory disk */ - (void) getlong(ctx->file); /* size of central directory */ - offset = getlong(ctx->file); /* offset to central directory */ - - ctx->zip_count = count; - ctx->zip_table = fz_calloc(count, sizeof(xps_entry)); - memset(ctx->zip_table, 0, sizeof(xps_entry) * count); - - fz_seek(ctx->file, offset, 0); - - for (i = 0; i < count; i++) - { - sig = getlong(ctx->file); - if (sig != ZIP_CENTRAL_DIRECTORY_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 */ - (void) getshort(ctx->file); /* general */ - (void) getshort(ctx->file); /* method */ - (void) getshort(ctx->file); /* last mod file time */ - (void) getshort(ctx->file); /* last mod file date */ - (void) getlong(ctx->file); /* crc-32 */ - ctx->zip_table[i].csize = getlong(ctx->file); - ctx->zip_table[i].usize = getlong(ctx->file); - namesize = getshort(ctx->file); - metasize = getshort(ctx->file); - commentsize = getshort(ctx->file); - (void) getshort(ctx->file); /* disk number start */ - (void) getshort(ctx->file); /* int file atts */ - (void) getlong(ctx->file); /* ext file atts */ - ctx->zip_table[i].offset = getlong(ctx->file); - - ctx->zip_table[i].name = fz_malloc(namesize + 1); - fz_read(ctx->file, (unsigned char*)ctx->zip_table[i].name, namesize); - ctx->zip_table[i].name[namesize] = 0; - - fz_seek(ctx->file, metasize, 1); - fz_seek(ctx->file, commentsize, 1); - } - - qsort(ctx->zip_table, count, sizeof(xps_entry), xps_compare_entries); - - return fz_okay; -} - -static int -xps_find_and_read_zip_dir(xps_context *ctx) -{ - unsigned char buf[512]; - int file_size, back, maxback; - int i, n; - - fz_seek(ctx->file, 0, SEEK_END); - file_size = fz_tell(ctx->file); - - maxback = MIN(file_size, 0xFFFF + sizeof buf); - back = MIN(maxback, sizeof buf); - - while (back < maxback) - { - fz_seek(ctx->file, file_size - back, 0); - - n = fz_read(ctx->file, buf, sizeof buf); - if (n < 0) - return fz_throw("cannot read end of central directory"); - - for (i = n - 4; i > 0; i--) - if (!memcmp(buf + i, "PK\5\6", 4)) - return xps_read_zip_dir(ctx, file_size - back + i); - - back += sizeof buf - 4; - } - - return fz_throw("cannot find end of central directory"); -} - -/* - * Read and interleave split parts from a ZIP file. - */ -static xps_part * -xps_read_zip_part(xps_context *ctx, char *partname) -{ - char buf[2048]; - xps_entry *ent; - xps_part *part; - int count, size, offset, i; - char *name; - - name = partname; - if (name[0] == '/') - name ++; - - /* All in one piece */ - ent = xps_find_zip_entry(ctx, name); - if (ent) - { - part = xps_new_part(ctx, partname, ent->usize); - xps_read_zip_entry(ctx, ent, part->data); - return part; - } - - /* Count the number of pieces and their total size */ - count = 0; - size = 0; - while (1) - { - sprintf(buf, "%s/[%d].piece", name, count); - ent = xps_find_zip_entry(ctx, buf); - if (!ent) - { - sprintf(buf, "%s/[%d].last.piece", name, count); - ent = xps_find_zip_entry(ctx, buf); - } - if (!ent) - break; - count ++; - size += ent->usize; - } - - /* Inflate the pieces */ - if (count) - { - part = xps_new_part(ctx, partname, size); - offset = 0; - for (i = 0; i < count; i++) - { - if (i < count - 1) - sprintf(buf, "%s/[%d].piece", name, i); - else - sprintf(buf, "%s/[%d].last.piece", name, i); - ent = xps_find_zip_entry(ctx, buf); - xps_read_zip_entry(ctx, ent, part->data + offset); - offset += ent->usize; - } - return part; - } - - return NULL; -} - -/* - * Read and interleave split parts from files in the directory. - */ -static xps_part * -xps_read_dir_part(xps_context *ctx, char *name) -{ - char buf[2048]; - xps_part *part; - FILE *file; - int count, size, offset, i, n; - - fz_strlcpy(buf, ctx->directory, sizeof buf); - fz_strlcat(buf, name, sizeof buf); - - /* All in one piece */ - file = fopen(buf, "rb"); - if (file) - { - fseek(file, 0, SEEK_END); - size = ftell(file); - fseek(file, 0, SEEK_SET); - part = xps_new_part(ctx, name, size); - fread(part->data, 1, size, file); - fclose(file); - return part; - } - - /* Count the number of pieces and their total size */ - count = 0; - size = 0; - while (1) - { - sprintf(buf, "%s%s/[%d].piece", ctx->directory, name, count); - file = fopen(buf, "rb"); - if (!file) - { - sprintf(buf, "%s%s/[%d].last.piece", ctx->directory, name, count); - file = fopen(buf, "rb"); - } - if (!file) - break; - count ++; - fseek(file, 0, SEEK_END); - size += ftell(file); - fclose(file); - } - - /* Inflate the pieces */ - if (count) - { - part = xps_new_part(ctx, name, size); - offset = 0; - for (i = 0; i < count; i++) - { - if (i < count - 1) - sprintf(buf, "%s%s/[%d].piece", ctx->directory, name, i); - else - sprintf(buf, "%s%s/[%d].last.piece", ctx->directory, name, i); - file = fopen(buf, "rb"); - n = fread(part->data + offset, 1, size - offset, file); - offset += n; - fclose(file); - } - return part; - } - - return NULL; -} - -xps_part * -xps_read_part(xps_context *ctx, char *partname) -{ - if (ctx->directory) - return xps_read_dir_part(ctx, partname); - return xps_read_zip_part(ctx, partname); -} - -static int -xps_open_directory(xps_context **ctxp, char *directory) -{ - xps_context *ctx; - int code; - - ctx = fz_malloc(sizeof(xps_context)); - memset(ctx, 0, sizeof(xps_context)); - - ctx->directory = fz_strdup(directory); - - code = xps_read_page_list(ctx); - if (code) - { - xps_free_context(ctx); - return fz_rethrow(code, "cannot read page list"); - } - - *ctxp = ctx; - return fz_okay; -} - -int -xps_open_stream(xps_context **ctxp, fz_stream *file) -{ - xps_context *ctx; - int code; - - ctx = fz_malloc(sizeof(xps_context)); - memset(ctx, 0, sizeof(xps_context)); - - ctx->file = fz_keep_stream(file); - - code = xps_find_and_read_zip_dir(ctx); - if (code < 0) - { - xps_free_context(ctx); - return fz_rethrow(code, "cannot read zip central directory"); - } - - code = xps_read_page_list(ctx); - if (code) - { - xps_free_context(ctx); - return fz_rethrow(code, "cannot read page list"); - } - - *ctxp = ctx; - return fz_okay; -} - -int -xps_open_file(xps_context **ctxp, char *filename) -{ - char buf[2048]; - fz_stream *file; - char *p; - int code; - - if (strstr(filename, "/_rels/.rels") || strstr(filename, "\\_rels\\.rels")) - { - fz_strlcpy(buf, filename, sizeof buf); - p = strstr(buf, "/_rels/.rels"); - if (!p) - p = strstr(buf, "\\_rels\\.rels"); - *p = 0; - return xps_open_directory(ctxp, buf); - } - - file = fz_open_file(filename); - if (!file) - return fz_throw("cannot open file '%s': %s", filename, strerror(errno)); - - code = xps_open_stream(ctxp, file); - fz_close(file); - if (code) - return fz_rethrow(code, "cannot load document '%s'", filename); - return fz_okay; -} - -void -xps_free_context(xps_context *ctx) -{ - xps_font_cache *font, *next; - int i; - - if (ctx->file) - fz_close(ctx->file); - - for (i = 0; i < ctx->zip_count; i++) - fz_free(ctx->zip_table[i].name); - fz_free(ctx->zip_table); - - font = ctx->font_table; - while (font) - { - next = font->next; - fz_drop_font(font->font); - fz_free(font->name); - fz_free(font); - font = next; - } - - xps_free_page_list(ctx); - - fz_free(ctx->start_part); - fz_free(ctx->directory); - fz_free(ctx); -}