summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Vrhel <michael.vrhel@artifex.com>2017-03-14 18:37:25 +0000
committerRobin Watts <robin.watts@artifex.com>2017-06-22 14:59:43 +0100
commitdd58ea5e2ff7e6b61cc5a5b6fd950fb62e92b8be (patch)
treeb22a2dddaae41961f74a88cfafc52a3adb24e263
parent5ab2a7dad585400caef7703e0761264bb03e81b0 (diff)
downloadmupdf-dd58ea5e2ff7e6b61cc5a5b6fd950fb62e92b8be.tar.xz
Add Color Management interface to MuPDF, with LCMS implementation.
This commit adds an interface for a color management engine to MuPDF, together with the internal changes required to use it. We also add an implementation of this interface using the LCMS2 library. This commit is the "lcms" development branch squashed to a single commit. The individual commits that make it up are as follows: ------ Add LCMS2 submodule. Add required source files to MSVC libthirdparty project. Plus changes to the Makefile. ------ Change name of libfont to libresources The library can hold things other than fonts including ICC profiles and eventually halftone screens etc. ------ Generate and include icc profiles on windows solution Makefile for linux needs to be updated ------ Initial cut at interface to little cms Methods for getting profile handles, link handles and transform buffers as well as individual colors. ------ Install ICC profiles from source When the source color space is an ICC profile install the ICC space. Use alternative color space if ICC is invalid. ------ Rename ICC resources The way that fontdump generates the names was causing some redundant prefix/suffix combinations. ------ Make resource ICC profiles usable This brings in the resource profiles for use with the target device. When mudraw is invoked with the icc color type, it will set up the target pixmap to have an icc based color space. ------ Make Default ICC color spaces not storable The ICC color spaces in the color context should not be put into the store. ICC color spaces that are contained in the source document are however storable. ------ Add in support for single color conversion This adds in the selection of the icc single color converter. Note that we may want to look at using the float conversion in lcms here since we are going from and to float. The down side is that the creation of such converters may be expensive. ------ Pixmap ICC conversion Also clean up and further simplify some of the code. Use common dst, src in function parameters instead of src, dst. ------ Add md5 calculation for profiles Compare md5 of source and destination. If they are the same set link as identity and do not bother creating link from cmm. ------ Initial attempt at adding links to store Next need to make sure I have all the dropping set up correctly and that the links are getting freed when we are all done with them. ------ Add drop for link Make sure that we drop the links when we are done with them. ------ Fix icc link store ref. counting + rendering intent The key allocations, rc and removal was wrong for the icc links. Also added in support on the graphic state for rendering intent. ------ Add ICC profiles to Makefile. ------ Move ICC profile loading to colorspace.c ------ Fix build on linux. ------ Use hexdump in creating icc profiles ------ First cut at CalRGB CalGray handling These color spaces are converted to equivalent ICC profiles when the drawing operation occurs. ToDo still is avoid creating brand new CalGray, CalRGB or ICC color spaces when we encounter the same object in the source file. Instead we should make use of the store. ------ Adding fz_color_params into device API Stroke and fill of paths and text which will have color rendering related settings including overprint, overprint mode, rendering intent and black point settings. Images have a fz_color_params member added to them. ------ Rendering intent support for graphic and text Graphic fills and strokes as well as text fill and strokes handle the rendering intent settings. This works through the display list. The parameters related to color rendering, ri, bp, op, opm are packed in the flags bits through the display list. To do: Add support for images and shadings. ------ Add support for rendering intent with images Required change to fill_image api, hence the large number of files touched. ------ Add support for shadings rendering intent and DeviceN This adds support for the rendering intent in shading fills. Also, adds in support for color management of DeviceN and Separation color spaces where the base space is defined to be ICC. ------ Add clamping proc to colorspace-imp.h In the head of mupdf, the index color values were not being clamped properly. I moved the clamping operation to be performed by a procedure in of the color space. The a*, b* values in LAB will need to include a range value for proper clamping as well as the ICC color space at some point. ------ Fix assert test with index images ------ Support for DeviceN images color managed The base space for DeviceN and separation images is now color managed when the ICC work flow is used. ------ Add DefaultGray etc to names.txt The DefaultGray, DefaultRGB, and DefaultCMYK settings in the pdf page resource dictionary need to be parsed and handled if present. ------ Remove methods for setting color space in context The methods that existed for setting the color spaces in the color space context were broken and we will not be changing them from their initial setting at startup. ------ Add front end support for default color spaces PDF can specify in the resource dictionary color spaces that should be used for DeviceGray, DeviceRGB and DeviceCMYK. This commit handles the extraction of these color spaces and passes them through the display list and gets them into a structure on a draw device (if one is used). Next step is to have the draw device make use of them. ------ Backend of default color spaces This handles the use of page level definitions for DefaultGray, DefaultRGB, DefaultCMYK in the draw device. The interface for the pixmap color conversion had to be expanded a bit to pass the default_cs object. This was needed due to the fact that the image could be DeviceN or Separation and have a base space that needs to be replaced by a page level Default color space. Tested this with a file that had two pages each with an common reference image object but different DefaultCMYK definitions in the page resource dictionary. Proper rendering was obtained. ------ Add icc support to band-writer and png output For image viewers that support icc profiles, it is important that we include the icc profile into those formats that support. Currently the only output format we have that supports it is PNG. But if we decide to do tiff, jpeg or psd those also support the embedding of icc profiles. ------ Work toward multithreading Each cloned context creates a new cmm context to reduce contention. This may not be optimal though as it may create conflicts in any shared store. ------ Add missing files. Failed to check in icc-imp.h and icc34.h ------ Fix default device color calls copy and paste errors. ------ Fixes ------ Fix clamping of lab colors The lab colors when used with the lab resource profile need to be properly clamped and scaled. ------ Turn off ICC create debug define ------ Fix memory leak issues ------ Set clamp proc in color context color spaces When NO_ICC is enabled there was an issue as the default spaces did not have the clamp proc (which was added in the lcms branch). ------ Fix several issues after rebase During rebase of the branch there were several issues that came up. In addition there was a fix related to the use of the lcms2 context branch that did not make it in for some reason. ------ Fix for fz_store_type structure changes ------ Fixes for multithreaded This fixes a few issues. One issue is that we can not be changing the input and output formatter for the links if they are being shared among threads. This adds the format as part of the link definition. Next step is to create a link clone operation in lcms so that we can readily create a different one with everything the same except the formatter. Also, this shares the profiles that exist in the color context among the threads. When a context is cloned, it will use the profiles in the current context but it will create a new cmm context.c ------ Fix NO_ICC issues There were a few issues that occurred when we compiled and ran with the NO_ICC setting. ------ Change CMM to use lower resolution tables in links The table resolution greatly affects the performance for some files. I don't see any significant color rendering issues going with a lower resolution. Selecting cmsFLAGS_LOWRESPRECALC uses a MLUT resolution of 17. This is going to be sufficient color wise and gives a large improvement performance wise especially for files where the color link creation is significant compared to the rendering. ------ Fix link key creation to populate alpha and bit depth. The store key for icc links needs to include the bit depth and if the transform has to handle an alpha value. This is needed due to the fact that we can't change the formatter when we are sharing links among different threads. ------ Pull in some MSVC 2005 fixes for lcms2 ------ Fix non-prototype prototype. ------ Miscellaneous typos, whitespace fixes. ------ Tidy colorspace creation API. Rather than pass a magic implementation reference count value (-1 for static, 1 for normal), pass a boolean "is_static" flag. This gives a nicer API (IMAO etc). ------ Make all colorspaces use an fz_buffer. ------ Fix internal naming of MSVC project file. ------ Fix some error handling. ------ Add some consts. ------ Tweak fz_color_params and fz_store_hash. Use uint8_t for fz_color_param entries - no need to use larger. Same change in fz_store_hash. This limits the size required for the hash table too. ------ Throw on errors, rather than returning NULL. fz_cmm_transform_pixmap should throw if it's fed pixmaps incompatible with its transforms. fz_cmm_new_ctx should throw if the cmm fails to initialise. ------ Ensure LCMS2_OBJs are built/linked using Makefile. Also ensure that ICC_OBJs are included. ------ Fix some unused variable warnings. ------ cs_params fixes. Use the ones that are passed. ------ fz_color_params tweaks. Make them const in many places. Cope with cs_params == NULL meaning default (i.e. fz_cs_param(ctx)). Minimise the places we call fz_cs_params(ctx). Consistently use cs_params rather than a mix of cs_param and cs_params. ------ Improve PDF color params handling. PDF allows different OP settings for strokes and fills. This means that either we need to keep separate entries in each fz_color_param structure for the stroke one or the fill one, OR we need to duplicate the fz_color_param structure. It seems neatest to do the latter (not least because this means we don't pass more information to each device function than it actually needs). Accordingly, we put an fz_color_param in each pdf_material. We update the code that reads ExtGStates to set the values appropriately. We take the opportunity to add support for the PDF 2.0 UseBlackPtComp option too. ------ Fix colorspace ref count problems. 1) Don't drop colorspace until we've finished using it. 2) Don't drop it twice. ------ Convert NULL deref into a thrown error. Seen with: mutool draw -D -o out.png ../tests_private/comparefiles/Bug689760.pdf We seem to have a pdf-cal space with no profile. Talk to Michael about this. ------ Avoid using colorspace names to distinguish colorspaces. Using strcmp is slow. ------ Cope with failure to parse default colorspaces during PDF page load. ------ Avoid SEGV due to to pdf_cal space with no profile. As seen in: tests_private/pdf/PDFIA1.7_SUBSET/CATX4879.pdf ------ Handle cases where base space of sep is pdf-cal We handled this for images, but not for solid fills. ------ Accelerate ICC color conversion. ------ Cope with indexed images in the color management. Some images (JPX images) come to the cm code still in the indexed color space. Their base space could be DevN so we need to cope with multiple base decodes. This continues the decode until we get to a space for which we can create an ICC link. ------ Ignore alpha presence in component count check ------ Eliminate recursion in fz_source_colorspace_cm. ------ Cope with bare ICCBased colorspace defs. Bug692137.pdf has ICCBased colorspaced definitions given directly as a stream, rather than as [ /ICCBased <stream reference> ] Acrobat copes with these, as does gs. We therefore update our code to cope too. Also, the PDF spec says that any problems found when reading the Default spaces should be ignored (or at least not to abort rendering). Update our code to do that too. ------ Tweak color converter logic for speed. When we are using an icc profile based conversion, avoid ever having to lookup the color converter for each conversion call; do it at the lookup stage. ------ Harden us against failures during ICC link creation. Seen with corrupted profiles. ------ Fix for handling alpha with lcms. Note that this currently maintains an alpha when it is present. We may need to do some work for the gray scale conversion to alpha mask. ------ Delay pdf-cal profile creation Put the creation of the pdf cal profile into the link creation function (rather than have it scattered). Also be robust in the condition of failure to create the profile. ------ Proper clamping with embedded CIELAB ICC profile If the ICC profiles alternate color space is LAB then use the LAB clamping proc. ------ Use the color space clamp when converting to base color spaces In many of the Ghent test files, we have a DeviceN image whose alternate color space is CIELAB. We need to make sure to use the CIELAB clamping operation in this case. ------ Make ICC runtime configurable. Add fz_icc_flowflow, fz_set_icc_workflow functions to read ICC workflow state, and set the ICC workflow state. The latter will throw an error if trying to enable ICC workflow in a NO_ICC build. Add -N flag to mutool to disable ICC. Incorporates build fixes from Michael. ------ Ensure fz_draw_fill_image uses the pixmap colorspace It appears that the image colorspace historically has been able to differ from the pixmap colorspace. While we've fixed the cases that we know about for this (see the previous commits), tweak fz_draw_fill_image to work the way it always has in the past. ------ Add support for output intent PDF documents can have an ICC profile defined in their Catalog which defines the output color space and the color space to use for one of the Device color spaces (e.g. DeviceGray, DeviceRGB or DeviceCMYK). ------ Catch errors in default color spaces Before setting the default color space contained in the file, make sure it is the correct type. Bug692213.pdf ------ Clamp to base space during sep color conversion This was the source of a problem when the base space was CIELAB. ------ Rename some functions to be more MuPDFy drop rather than free etc. ------ Fix "casting away const" warning. srcv is a const *. Do the clamping operation on src_map (the same value) before it is assigned into the const variable. ------ Rejig top level color management interface slightly. Same code, just change the encapsulation. ------ Remove pre-multiplied alpha prior to color management The pixmaps in mupdf use a premultiplied alpha format. Prior to doing any color management we need to undo the alpha and then reapply after color management. ------ Remove global output intent as unused. ------ Move fz_color_params to be the final arg in dev calls. Frequently this will be NULL, and it doesn't form part of the colorspace/color/alpha triple. ------ Rename fz_default_xxx static variables. Remove fz prefix, to prepare for a later renaming that would conflict. ------ Rename cs_params to color_params. ------ Rename lcms branch identifiers. ------ Return device colorspaces if the default colorspace is NULL. ------ Clean up device call function for set_default_colorspaces. ------ Add missing rethrow. ------ Load page default colorspaces lazily. ------ murun: Add color params device argument. Stubbed to always be NULL at the moment. ------ Rename extgstate processor ops. ------ Fix a few minor issues from Tor Removes icc-imp.h Rename color-icccreate.c Add context to some methods ------ Fix javalib with recent lcms dev changes. ------ Update lcms2 with sub project fixes. ------ Fix build failure. ------ Add icc profile into other PNG output methods ------ Fix some ints that should be size_t's. ------ Tweak fz_new_icc_data_from_icc_colorspace. Ensure that the colorspace is const, and that we set size to 0 if we don't find any data. ------ Combine band writer methods for header and ICC writing For many formats (like PSD), we need to delay writing some of the header until we know whether we are getting an ICC profile to write or not. Makes more sense to just write them at the same time. ------ Miscellaneous tweaks in colorspace.c Mainly to avoid pointer aliasing, "nicer" whitespace, and a leak on error. ------ Avoid rightward drift in get_base_icc. ------ Ensure that pdf_load_output_intent copes with exceptions. If load_icc_based throws and exception, warn and continue. Don't not render a file just because the inbuilt default profiles are broken. ------ Revert change in pdf-page.c The page resources load had been moved so we could get the default colorspaces, but this has been moved into run_contents, so putting stuff back as it was before. ------ Revert changes in mudraw. We had added some colorspages in mudraw, and then later removed them. Revert the changes to accomodate this to make the overall branch diffs smaller. ------ Use fz_buffer in color-icc-create.c ------ Force mapping through proof icc profile always. ------ Fix behaviour on fz_cmm_new_profile failure. If the profile fails to be made, return an error code, and have the callers take sane steps. ------ Tweak load_icc_based Cope better with errors in reading the ICC space not stopping us loading the alternate. ------ Remove unused variable. ------ Get page resource for DefaultCS look-up res = pdf_dict_get(ctx, PDF_NAME_Resources, page->obj); was not returning resource. Replaced with res = pdf_page_resources(ctx, page); ------ Move default color space set up to pdf_run_page_contents_with_usage ------ Review fixes for lcms branch. ------ Fixes for calibrated colorspace loading. ------ Add fz_document_output_intent wrapper. Lazy load intent for PDF. ------ Copy DefaultCS logic into pdf_run_annot_with_usage. Same code as from pdf_run_page_contents_with_usage. ------ More review fixes. ------ Avoid rightward drift in pdf_load_cal_common ------ Rename color_converter functions to be find/drop. Better than than lookup/discard. lookup suggests something that doesn't need dropping, and we use drop rather than discard by convention. ------ Move cmm from context into colorspace context. ------ Review fixes: Remove recursion and rename functions. ------ Don't access doc->oi directly in pdf_load_default_colorspaces. ------ Rename fz_colorspace_is_pdf_cal to fz_colorspace_is_cal and make it public. ------ Tweak function naming to be more consistent. ------ fz_md5_icc can be implemented using fz_md5_buffer. ------ Print full md5 checksums in link key debug prints. ------ Make fz_md5_buffer NULL safe. ------ Simplify debug saving of ICC profiles. ------ Rename fz_cmm_new/drop_profile to init/fin. ------ Indentation cleanups. ------ Move CMM static inline functions from private header to C file. ------ Tweak fz_icc_data_from_icc_colorspace to return a buffer. Also, remove the _new_ from the name to reflect the fact that we are passed a borrowed handle, not given a new reference. ------ java: Add ColorParams.pack() function. ------ Generate one C file for the embedded ICC profiles. ------ Return const pointer from fz_default_color_params. ------ Change misleading argument names to fz_new_colorspace. ------ Rename fz_cmm_new/drop_link to fz_cmm_init/fin_link. ------ Change definition of fz_cmm_instance. Rather than void, use an undefined struct in keeping with the rest of the code. ------ Add support for color managed bgr color space ------ Return unsigned char array from fz_lookup_icc. ------ Make default_color_params immutable. Changing the defaults used by the draw device should happen via a device call, should we need the functionality in the future. ------ Clean up error handling in color-lcms.c ------ Fix signed/unsigned warning.
-rw-r--r--.gitmodules3
-rw-r--r--Makefile24
-rw-r--r--Makerules5
-rw-r--r--Makethird47
-rw-r--r--include/mupdf/fitz.h1
-rw-r--r--include/mupdf/fitz/band-writer.h6
-rw-r--r--include/mupdf/fitz/buffer.h2
-rw-r--r--include/mupdf/fitz/color-management.h115
-rw-r--r--include/mupdf/fitz/colorspace.h120
-rw-r--r--include/mupdf/fitz/config.h3
-rw-r--r--include/mupdf/fitz/context.h3
-rw-r--r--include/mupdf/fitz/device.h35
-rw-r--r--include/mupdf/fitz/document.h11
-rw-r--r--include/mupdf/fitz/font.h22
-rw-r--r--include/mupdf/fitz/image.h2
-rw-r--r--include/mupdf/fitz/output-png.h4
-rw-r--r--include/mupdf/fitz/pixmap.h17
-rw-r--r--include/mupdf/fitz/shade.h6
-rw-r--r--include/mupdf/fitz/store.h18
-rw-r--r--include/mupdf/pdf/document.h1
-rw-r--r--include/mupdf/pdf/interpret.h6
-rw-r--r--include/mupdf/pdf/page.h5
-rw-r--r--include/mupdf/pdf/resource.h1
-rw-r--r--platform/java/mupdf_native.c96
-rw-r--r--platform/java/mupdf_native.h676
-rw-r--r--platform/java/src/com/artifex/mupdf/fitz/ColorParams.java51
-rw-r--r--platform/java/src/com/artifex/mupdf/fitz/NativeDevice.java17
-rw-r--r--platform/win32/generate.bat2
-rw-r--r--platform/win32/javaviewerlib.vcproj4
-rw-r--r--platform/win32/libmupdf.vcproj34
-rw-r--r--platform/win32/libresources.vcproj (renamed from platform/win32/libfonts.vcproj)8
-rw-r--r--platform/win32/libthirdparty.vcproj130
-rw-r--r--platform/win32/mupdf.sln2
-rw-r--r--resources/icc/cmyk.iccbin0 -> 187484 bytes
-rw-r--r--resources/icc/gray.iccbin0 -> 416 bytes
-rw-r--r--resources/icc/lab.iccbin0 -> 1972 bytes
-rw-r--r--resources/icc/rgb.iccbin0 -> 2576 bytes
-rw-r--r--resources/pdf/names.txt12
-rw-r--r--scripts/cmapdump.c8
-rw-r--r--source/cbz/mucbz.c2
-rw-r--r--source/cbz/muimg.c2
-rw-r--r--source/cbz/mutiff.c2
-rw-r--r--source/fitz/bbox-device.c16
-rw-r--r--source/fitz/bitmap.c8
-rw-r--r--source/fitz/buffer.c19
-rw-r--r--source/fitz/color-icc-create.c448
-rw-r--r--source/fitz/color-lcms.c345
-rw-r--r--source/fitz/colorspace-imp.h57
-rw-r--r--source/fitz/colorspace.c1396
-rw-r--r--source/fitz/context.c3
-rw-r--r--source/fitz/device.c39
-rw-r--r--source/fitz/document.c8
-rw-r--r--source/fitz/draw-device.c177
-rw-r--r--source/fitz/draw-mesh.c7
-rw-r--r--source/fitz/fitz-imp.h2
-rw-r--r--source/fitz/icc34.h1022
-rw-r--r--source/fitz/list-device.c146
-rw-r--r--source/fitz/output-cbz.c2
-rw-r--r--source/fitz/output-pcl.c8
-rw-r--r--source/fitz/output-png.c79
-rw-r--r--source/fitz/output-pnm.c12
-rw-r--r--source/fitz/output-ps.c4
-rw-r--r--source/fitz/output-pwg.c8
-rw-r--r--source/fitz/output-tga.c4
-rw-r--r--source/fitz/output.c4
-rw-r--r--source/fitz/pixmap.c9
-rw-r--r--source/fitz/stext-device.c10
-rw-r--r--source/fitz/stext-output.c2
-rw-r--r--source/fitz/svg-device.c76
-rw-r--r--source/fitz/test-device.c82
-rw-r--r--source/fitz/trace-device.c16
-rw-r--r--source/gprf/gprf-doc.c2
-rw-r--r--source/html/html-layout.c12
-rw-r--r--source/pdf/pdf-appearance.c22
-rw-r--r--source/pdf/pdf-colorspace.c310
-rw-r--r--source/pdf/pdf-device.c30
-rw-r--r--source/pdf/pdf-image.c2
-rw-r--r--source/pdf/pdf-interpret.c22
-rw-r--r--source/pdf/pdf-op-buffer.c26
-rw-r--r--source/pdf/pdf-op-filter.c42
-rw-r--r--source/pdf/pdf-op-run.c98
-rw-r--r--source/pdf/pdf-page.c55
-rw-r--r--source/pdf/pdf-run.c10
-rw-r--r--source/pdf/pdf-xref.c3
-rw-r--r--source/svg/svg-run.c4
-rw-r--r--source/tools/mudraw.c27
-rw-r--r--source/tools/muraster.c4
-rw-r--r--source/tools/murun.c100
-rw-r--r--source/tools/pdfextract.c2
-rw-r--r--source/xps/xps-common.c2
-rw-r--r--source/xps/xps-glyphs.c2
-rw-r--r--source/xps/xps-gradient.c6
-rw-r--r--source/xps/xps-image.c2
-rw-r--r--source/xps/xps-path.c4
m---------thirdparty/lcms20
95 files changed, 5273 insertions, 1026 deletions
diff --git a/.gitmodules b/.gitmodules
index 943bf948..8d5899c4 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -25,3 +25,6 @@
[submodule "thirdparty/curl"]
path = thirdparty/curl
url = ../thirdparty-curl.git
+[submodule "thirdparty/lcms2"]
+ path = thirdparty/lcms2
+ url = ../thirdparty-lcms2.git
diff --git a/Makefile b/Makefile
index 837b450c..b306c5df 100644
--- a/Makefile
+++ b/Makefile
@@ -21,6 +21,7 @@ LIBS += $(FREETYPE_LIBS)
LIBS += $(HARFBUZZ_LIBS)
LIBS += $(JBIG2DEC_LIBS)
LIBS += $(JPEGXR_LIB)
+LIBS += $(LCMS2_LIBS)
LIBS += $(LIBCRYPTO_LIBS)
LIBS += $(LIBJPEG_LIBS)
LIBS += $(LURATECH_LIBS)
@@ -32,6 +33,7 @@ CFLAGS += $(FREETYPE_CFLAGS)
CFLAGS += $(HARFBUZZ_CFLAGS)
CFLAGS += $(JBIG2DEC_CFLAGS)
CFLAGS += $(JPEGXR_CFLAGS)
+CFLAGS += $(LCMS2_CFLAGS)
CFLAGS += $(LIBCRYPTO_CFLAGS)
CFLAGS += $(LIBJPEG_CFLAGS)
CFLAGS += $(LURATECH_CFLAGS)
@@ -218,6 +220,22 @@ endif
generate: $(FONT_GEN)
+# --- Generated ICC profiles ---
+
+ICC_BIN := resources/icc/gray.icc resources/icc/rgb.icc resources/icc/cmyk.icc resources/icc/lab.icc
+ICC_GEN := generated/icc-profiles.c
+ICC_OBJ := $(ICC_GEN:%.c=$(OUT)/%.o)
+
+$(ICC_OBJ) : $(ICC_GEN)
+$(ICC_GEN) : $(ICC_BIN) | generated
+ $(QUIET_GEN) $(HEXDUMP_EXE) $@ $(ICC_BIN)
+
+ifneq "$(CROSSCOMPILE)" "yes"
+$(ICC_GEN) : $(HEXDUMP_EXE)
+endif
+
+generate: $(ICC_GEN)
+
# --- Generated CMap files ---
CMAPDUMP_EXE := $(OUT)/scripts/cmapdump.exe
@@ -303,7 +321,8 @@ MUPDF_OBJ := \
$(SVG_OBJ) \
$(CBZ_OBJ) \
$(HTML_OBJ) \
- $(GPRF_OBJ)
+ $(GPRF_OBJ) \
+ $(ICC_OBJ)
THIRD_OBJ := \
$(FREETYPE_OBJ) \
@@ -314,7 +333,8 @@ THIRD_OBJ := \
$(LURATECH_OBJ) \
$(MUJS_OBJ) \
$(OPENJPEG_OBJ) \
- $(ZLIB_OBJ)
+ $(ZLIB_OBJ) \
+ $(LCMS2_OBJ)
THREAD_OBJ := $(THREAD_OBJ)
diff --git a/Makerules b/Makerules
index 8616f2fb..b28c5ab0 100644
--- a/Makerules
+++ b/Makerules
@@ -155,6 +155,11 @@ SYS_OPENJPEG_CFLAGS := $(shell pkg-config --cflags libopenjp2)
SYS_OPENJPEG_LIBS := $(shell pkg-config --libs libopenjp2)
endif
+ifeq "$(shell pkg-config --exists lcms2 && echo yes)" "yes"
+SYS_LCMS2_CFLAGS := $(shell pkg-config --cflags lcms2)
+SYS_LCMS2_LIBS := $(shell pkg-config --libs lcms2)
+endif
+
SYS_JBIG2DEC_LIBS := -ljbig2dec
SYS_LIBJPEG_LIBS := -ljpeg
SYS_ZLIB_LIBS := -lz
diff --git a/Makethird b/Makethird
index b5ae6a65..a2de97db 100644
--- a/Makethird
+++ b/Makethird
@@ -10,6 +10,7 @@ FREETYPE_DIR := thirdparty/freetype
HARFBUZZ_DIR := thirdparty/harfbuzz
JBIG2DEC_DIR := thirdparty/jbig2dec
JPEGXR_DIR := thirdparty/jpegxr
+LCMS2_DIR := thirdparty/lcms2
LIBJPEG_DIR := thirdparty/libjpeg
LURATECH_DIR := thirdparty/luratech
MUJS_DIR := thirdparty/mujs
@@ -532,6 +533,52 @@ ZLIB_CFLAGS := $(SYS_ZLIB_CFLAGS)
ZLIB_LIBS := $(SYS_ZLIB_LIBS)
endif
+# --- LCMS2 ---
+
+ifneq "$(wildcard $(LCMS2_DIR)/INSTALL)" ""
+
+LCMS2_OUT := $(OUT)/lcms2
+LCMS2_SRC := \
+ cmsalpha.c \
+ cmscam02.c \
+ cmscgats.c \
+ cmscnvrt.c \
+ cmserr.c \
+ cmsgamma.c \
+ cmsgmt.c \
+ cmshalf.c \
+ cmsintrp.c \
+ cmsio0.c \
+ cmsio1.c \
+ cmslut.c \
+ cmsmd5.c \
+ cmsmtrx.c \
+ cmsnamed.c \
+ cmsopt.c \
+ cmspack.c \
+ cmspcs.c \
+ cmsplugin.c \
+ cmsps2.c \
+ cmssamp.c \
+ cmssm.c \
+ cmstypes.c \
+ cmsvirt.c \
+ cmswtpnt.c \
+ cmsxform.c \
+
+LCMS2_OBJ := $(addprefix $(LCMS2_OUT)/, $(LCMS2_SRC:%.c=%.o))
+
+$(LCMS2_OUT):
+ $(MKDIR_CMD)
+$(LCMS2_OUT)/%.o: $(LCMS2_DIR)/src/%.c | $(LCMS2_OUT)
+ $(CC_CMD) -I$(LCMS2_DIR)/include
+
+LCMS2_CFLAGS := -I$(LCMS2_DIR)/include
+else
+LCMS2_CFLAGS := $(SYS_LCMS2_CFLAGS)
+LCMS2_LIBS := $(SYS_LCMS2_LIBS)
+endif
+
# --- cURL ---
ifneq "$(wildcard $(CURL_DIR)/README)" ""
diff --git a/include/mupdf/fitz.h b/include/mupdf/fitz.h
index 20f0edaa..c616e72c 100644
--- a/include/mupdf/fitz.h
+++ b/include/mupdf/fitz.h
@@ -40,6 +40,7 @@ extern "C" {
#include "mupdf/fitz/path.h"
#include "mupdf/fitz/text.h"
#include "mupdf/fitz/separation.h"
+#include "mupdf/fitz/color-management.h"
#include "mupdf/fitz/device.h"
#include "mupdf/fitz/display-list.h"
diff --git a/include/mupdf/fitz/band-writer.h b/include/mupdf/fitz/band-writer.h
index 06f885c3..95385d5f 100644
--- a/include/mupdf/fitz/band-writer.h
+++ b/include/mupdf/fitz/band-writer.h
@@ -10,7 +10,7 @@
*/
typedef struct fz_band_writer_s fz_band_writer;
-typedef void (fz_write_header_fn)(fz_context *ctx, fz_band_writer *writer);
+typedef void (fz_write_header_fn)(fz_context *ctx, fz_band_writer *writer, const fz_colorspace *cs);
typedef void (fz_write_band_fn)(fz_context *ctx, fz_band_writer *writer, int stride, int band_start, int band_height, const unsigned char *samples);
typedef void (fz_write_trailer_fn)(fz_context *ctx, fz_band_writer *writer);
typedef void (fz_drop_band_writer_fn)(fz_context *ctx, fz_band_writer *writer);
@@ -51,9 +51,11 @@ fz_band_writer *fz_new_band_writer_of_size(fz_context *ctx, size_t size, fz_outp
pagenum: Page number
+ cs: Colorspace (NULL for bitmaps)
+
Throws exception if incompatible data format.
*/
-void fz_write_header(fz_context *ctx, fz_band_writer *writer, int w, int h, int n, int alpha, int xres, int yres, int pagenum);
+void fz_write_header(fz_context *ctx, fz_band_writer *writer, int w, int h, int n, int alpha, int xres, int yres, int pagenum, const fz_colorspace *cs);
/*
fz_write_band: Cause a band writer to write the next band
diff --git a/include/mupdf/fitz/buffer.h b/include/mupdf/fitz/buffer.h
index 73f254a3..c6f4c2a4 100644
--- a/include/mupdf/fitz/buffer.h
+++ b/include/mupdf/fitz/buffer.h
@@ -110,6 +110,8 @@ void fz_append_byte(fz_context *ctx, fz_buffer *buf, int c);
void fz_append_rune(fz_context *ctx, fz_buffer *buf, int c);
void fz_append_int32_le(fz_context *ctx, fz_buffer *buf, int x);
void fz_append_int16_le(fz_context *ctx, fz_buffer *buf, int x);
+void fz_append_int32_be(fz_context *ctx, fz_buffer *buf, int x);
+void fz_append_int16_be(fz_context *ctx, fz_buffer *buf, int x);
void fz_append_bits(fz_context *ctx, fz_buffer *buf, int value, int count);
void fz_append_bits_pad(fz_context *ctx, fz_buffer *buf);
void fz_append_printf(fz_context *ctx, fz_buffer *buffer, const char *fmt, ...);
diff --git a/include/mupdf/fitz/color-management.h b/include/mupdf/fitz/color-management.h
new file mode 100644
index 00000000..6c3ac356
--- /dev/null
+++ b/include/mupdf/fitz/color-management.h
@@ -0,0 +1,115 @@
+#ifndef MUPDF_FITZ_COLOR_MANAGEMENT_H
+#define MUPDF_FITZ_COLOR_MANAGEMENT_H
+
+#include "mupdf/fitz/colorspace.h"
+#include "mupdf/fitz/context.h"
+#include "mupdf/fitz/pixmap.h"
+
+/*
+ MuPDF can either run with or without color management. By default
+ MuPDF runs without color management. To enable color management,
+ a color management engine must be given to the context.
+
+ The context will then create one 'instance' of this engine per
+ cloned context. Every instance is tied to the particular context
+ in which it is created.
+
+ Profiles and links can be shared between instances.
+*/
+
+/*
+ fz_cmm_new_instance_fn: Create a new instance of the color
+ management engine, tied to the given context.
+*/
+typedef fz_cmm_instance *(fz_cmm_new_instance_fn)(fz_context *ctx);
+
+/*
+ fz_cmm_drop_instance_fn: Drop a given instance of the color
+ management engine. No further calls will be made to this
+ instance.
+*/
+typedef void (fz_cmm_drop_instance_fn)(fz_cmm_instance *instance);
+
+/*
+ fz_cmm_transform_pixmap_fn: Transform a pixmap according
+ to a link.
+*/
+typedef void (fz_cmm_transform_pixmap_fn)(fz_cmm_instance *ctx, fz_icclink *link, fz_pixmap *dst, fz_pixmap *src);
+
+/*
+ fz_cmm_transform_color_fn: Transform some color values according
+ to a link.
+*/
+typedef void (fz_cmm_transform_color_fn)(fz_cmm_instance *ctx, fz_icclink *link, unsigned short *dst, const unsigned short *src);
+
+/*
+ fz_cmm_init_link_fn: Create a new link between icc profiles.
+*/
+typedef void (fz_cmm_init_link_fn)(fz_cmm_instance *ctx, fz_icclink *link, const fz_color_params *rend, int cmm_flags, int num_bytes, int alpha, const fz_iccprofile *src, const fz_iccprofile *prf, const fz_iccprofile *des);
+
+/*
+ fz_cmm_fin_link_fn: Drop a link.
+*/
+typedef void (fz_cmm_fin_link_fn)(fz_cmm_instance *ctx, fz_icclink *link);
+
+/*
+ fz_cmm_init_profile_fn: Create the cmm specific data for the given
+ profile. The cmm handle is stored to profile->cmm_handle.
+*/
+typedef void (fz_cmm_init_profile_fn)(fz_cmm_instance *ctx, fz_iccprofile *profile);
+
+/*
+ fz_cmm_fin_profile_fn: Drop the cmm specific data for the given
+ profile.
+*/
+typedef void (fz_cmm_fin_profile_fn)(fz_cmm_instance *ctx, fz_iccprofile *profile);
+
+/*
+ Encapsulate details for a given color management engine into a single
+ structure.
+*/
+struct fz_cmm_engine_s {
+ fz_cmm_new_instance_fn *new_instance;
+ fz_cmm_drop_instance_fn *drop_instance;
+ fz_cmm_transform_pixmap_fn *transform_pixmap;
+ fz_cmm_transform_color_fn *transform_color;
+ fz_cmm_init_link_fn *init_link;
+ fz_cmm_fin_link_fn *fin_link;
+ fz_cmm_init_profile_fn *init_profile;
+ fz_cmm_fin_profile_fn *fin_profile;
+ int avoid_white_fix_flag;
+};
+
+/*
+ fz_get_cmm_engine: Read details of the current color
+ management engine. If NULL, we are working without
+ color management.
+*/
+const fz_cmm_engine *fz_get_cmm_engine(fz_context *ctx);
+
+/*
+ fz_set_cmm_engine: Set the color management engine to
+ be used. This should only ever be called on the "base"
+ context before cloning it, and before opening any files.
+
+ Attempting to change the engine in use once a file has
+ been opened, or to use different color management engine
+ for the same file in different threads will lead to
+ undefined behaviour, including crashing.
+
+ Using different ICC engines for different files using
+ different sets of fz_contexts should theoretically be
+ possible.
+*/
+void fz_set_cmm_engine(fz_context *ctx, const fz_cmm_engine *engine);
+
+/*
+ Currently we only provide a single color management
+ engine, based on a (modified) LCMS2.
+
+ An unmodified LCMS2 should work too, but only when restricted
+ to a single thread.
+*/
+extern fz_cmm_engine fz_cmm_engine_lcms;
+
+#endif
diff --git a/include/mupdf/fitz/colorspace.h b/include/mupdf/fitz/colorspace.h
index e7453f6c..289955c9 100644
--- a/include/mupdf/fitz/colorspace.h
+++ b/include/mupdf/fitz/colorspace.h
@@ -7,6 +7,29 @@
enum { FZ_MAX_COLORS = 32 };
+enum
+{
+ /* Same order as needed by lcms */
+ FZ_RI_PERCEPTUAL,
+ FZ_RI_RELATIVE_COLORIMETRIC,
+ FZ_RI_SATURATION,
+ FZ_RI_ABSOLUTE_COLORIMETRIC,
+};
+
+typedef struct fz_color_params_s fz_color_params;
+
+struct fz_color_params_s
+{
+ uint8_t ri;
+ uint8_t bp;
+ uint8_t op;
+ uint8_t opm;
+};
+
+
+int fz_lookup_rendering_intent(const char *name);
+char *fz_rendering_intent_name(int ri);
+
/*
A fz_colorspace object represents an abstract colorspace. While
this should be treated as a black box by callers of the library at
@@ -17,16 +40,21 @@ enum { FZ_MAX_COLORS = 32 };
typedef struct fz_colorspace_s fz_colorspace;
/*
- fz_colorspace_is_indexed: Return true, iff a given colorspace is
- indexed.
+ A fz_iccprofile object encapsulates details about the icc profile. It
+ also includes the profile handle provided by the cmm and as such is used
+ in the creation of links between color spaces.
+*/
+typedef struct fz_iccprofile_s fz_iccprofile;
+
+/*
+ A fz_icclink object encapsulates details about the link between profiles.
*/
-int fz_colorspace_is_indexed(fz_context *ctx, fz_colorspace *cs);
+typedef struct fz_icclink_s fz_icclink;
/*
- fz_colorspace_is_lab: Return true, iff a given colorspace is
- lab.
+ Used to communicate any document internal page specific default color spaces.
*/
-int fz_colorspace_is_lab(fz_context *ctx, fz_colorspace *cs);
+typedef struct fz_default_colorspaces_s fz_default_colorspaces;
/*
fz_colorspace_is_subtractive: Return true if a colorspace is subtractive.
@@ -61,40 +89,33 @@ fz_colorspace *fz_device_cmyk(fz_context *ctx);
fz_colorspace *fz_device_lab(fz_context *ctx);
/*
- fz_set_device_gray: Set colorspace representing device specific gray.
+ fz_default_color_params: Get default color params for general color conversion.
*/
-void fz_set_device_gray(fz_context *ctx, fz_colorspace *cs);
-
-/*
- fz_set_device_rgb: Set colorspace representing device specific rgb.
-*/
-void fz_set_device_rgb(fz_context *ctx, fz_colorspace *cs);
-
-/*
- fz_set_device_bgr: Set colorspace representing device specific bgr.
-*/
-void fz_set_device_bgr(fz_context *ctx, fz_colorspace *cs);
-
-/*
- fz_set_device_cmyk: Set colorspace representing device specific CMYK.
-*/
-void fz_set_device_cmyk(fz_context *ctx, fz_colorspace *cs);
+const fz_color_params *fz_default_color_params(fz_context *ctx);
typedef void (fz_colorspace_convert_fn)(fz_context *ctx, fz_colorspace *cs, const float *src, float *dst);
typedef void (fz_colorspace_destruct_fn)(fz_context *ctx, fz_colorspace *cs);
-fz_colorspace *fz_new_colorspace(fz_context *ctx, char *name, int n, int is_subtractive, fz_colorspace_convert_fn *to_rgb, fz_colorspace_convert_fn *from_rgb, fz_colorspace_destruct_fn *destruct, void *data, size_t size);
+typedef fz_colorspace *(fz_colorspace_base_fn)(const fz_colorspace *cs);
+
+typedef void (fz_colorspace_clamp_fn)(const fz_colorspace *cs, const float *src, float *dst);
+
+fz_colorspace *fz_new_colorspace(fz_context *ctx, char *name, int is_static, int n, int is_subtractive, fz_colorspace_convert_fn *to_ccs, fz_colorspace_convert_fn *from_ccs, fz_colorspace_base_fn *base, fz_colorspace_clamp_fn *clamp, fz_colorspace_destruct_fn *destruct, void *data, size_t size);
fz_colorspace *fz_new_indexed_colorspace(fz_context *ctx, fz_colorspace *base, int high, unsigned char *lookup);
fz_colorspace *fz_keep_colorspace(fz_context *ctx, fz_colorspace *colorspace);
void fz_drop_colorspace(fz_context *ctx, fz_colorspace *colorspace);
void fz_drop_colorspace_imp(fz_context *ctx, fz_storable *colorspace);
-int fz_colorspace_is(fz_context *ctx, const fz_colorspace *cs, fz_colorspace_convert_fn *to_rgb);
+fz_colorspace *fz_colorspace_base(fz_context *ctx, const fz_colorspace *cs);
+int fz_colorspace_is_icc(fz_context *ctx, const fz_colorspace *cs);
+int fz_colorspace_is_lab_icc(fz_context *ctx, const fz_colorspace *cs);
+int fz_colorspace_is_cal(fz_context *ctx, const fz_colorspace *cs);
+int fz_colorspace_is_indexed(fz_context *ctx, const fz_colorspace *cs);
int fz_colorspace_n(fz_context *ctx, const fz_colorspace *cs);
const char *fz_colorspace_name(fz_context *ctx, const fz_colorspace *cs);
-
-void fz_convert_color(fz_context *ctx, fz_colorspace *dsts, float *dstv, fz_colorspace *srcs, const float *srcv);
+void fz_clamp_color(fz_context *ctx, const fz_colorspace *cs, const float *in, float *out);
+void fz_convert_color(fz_context *ctx, const fz_color_params *params, fz_colorspace *intcs, fz_colorspace *dscs, float *dstv, fz_colorspace *srcs, const float *srcv);
typedef struct fz_color_converter_s fz_color_converter;
@@ -107,12 +128,51 @@ struct fz_color_converter_s
void (*convert)(fz_context *, fz_color_converter *, float *, const float *);
fz_colorspace *ds;
fz_colorspace *ss;
+ fz_colorspace *is;
void *opaque;
+ void *link;
+ int n;
};
-void fz_lookup_color_converter(fz_context *ctx, fz_color_converter *cc, fz_colorspace *ds, fz_colorspace *ss);
-
-void fz_init_cached_color_converter(fz_context *ctx, fz_color_converter *cc, fz_colorspace *ds, fz_colorspace *ss);
+void fz_find_color_converter(fz_context *ctx, fz_color_converter *cc, fz_colorspace *is, fz_colorspace *ds, fz_colorspace *ss, const fz_color_params *params);
+void fz_drop_color_converter(fz_context *ctx, fz_color_converter *cc);
+void fz_init_cached_color_converter(fz_context *ctx, fz_color_converter *cc, fz_colorspace *is, fz_colorspace *ds, fz_colorspace *ss, const fz_color_params *params);
void fz_fin_cached_color_converter(fz_context *ctx, fz_color_converter *cc);
+/* Public to allow use in icc creation */
+typedef struct fz_cal_colorspace_s fz_cal_colorspace;
+
+struct fz_cal_colorspace_s {
+ float wp[3];
+ float bp[3];
+ float gamma[3];
+ float matrix[9];
+ int n;
+ fz_iccprofile *profile;
+};
+
+/*
+ icc methods
+*/
+fz_colorspace *fz_new_icc_colorspace(fz_context *ctx, int is_static, int num, fz_buffer *buf, const char *name);
+fz_colorspace *fz_new_cal_colorspace(fz_context *ctx, float *wp, float *bp, float *gamma, float *matrix);
+fz_buffer *fz_new_icc_data_from_cal_colorspace(fz_context *ctx, fz_cal_colorspace *cal);
+fz_buffer *fz_icc_data_from_icc_colorspace(fz_context *ctx, const fz_colorspace *cs);
+
+/* Default cs */
+fz_default_colorspaces *fz_new_default_colorspaces(fz_context *ctx);
+fz_default_colorspaces* fz_keep_default_colorspaces(fz_context *ctx, fz_default_colorspaces *default_cs);
+void fz_drop_default_colorspaces(fz_context *ctx, fz_default_colorspaces *default_cs);
+
+/* Do we want to make fz_default_colorspaces public and get rid of these? */
+void fz_set_default_gray(fz_context *ctx, fz_default_colorspaces *default_cs, fz_colorspace *cs);
+void fz_set_default_rgb(fz_context *ctx, fz_default_colorspaces *default_cs, fz_colorspace *cs);
+void fz_set_default_cmyk(fz_context *ctx, fz_default_colorspaces *default_cs, fz_colorspace *cs);
+void fz_set_default_output_intent(fz_context *ctx, fz_default_colorspaces *default_cs, fz_colorspace *cs);
+
+fz_colorspace *fz_default_gray(fz_context *ctx, fz_default_colorspaces *default_cs);
+fz_colorspace *fz_default_rgb(fz_context *ctx, fz_default_colorspaces *default_cs);
+fz_colorspace *fz_default_cmyk(fz_context *ctx, fz_default_colorspaces *default_cs);
+fz_colorspace *fz_default_output_intent(fz_context *ctx, fz_default_colorspaces *default_cs);
+
#endif
diff --git a/include/mupdf/fitz/config.h b/include/mupdf/fitz/config.h
index 97d399b9..c7bf5244 100644
--- a/include/mupdf/fitz/config.h
+++ b/include/mupdf/fitz/config.h
@@ -75,6 +75,9 @@
/* To skip the SIL fonts, enable: */
/* #define TOFU_SIL */
+/* To skip the ICC profiles, enable: */
+/* #define NO_ICC */
+
/* To skip the Base14 fonts, enable: */
/* #define TOFU_BASE14 */
/* (You probably really don't want to do that except for measurement purposes!) */
diff --git a/include/mupdf/fitz/context.h b/include/mupdf/fitz/context.h
index 35f4f74f..78e64bbc 100644
--- a/include/mupdf/fitz/context.h
+++ b/include/mupdf/fitz/context.h
@@ -16,6 +16,8 @@ typedef struct fz_id_context_s fz_id_context;
typedef struct fz_warn_context_s fz_warn_context;
typedef struct fz_font_context_s fz_font_context;
typedef struct fz_colorspace_context_s fz_colorspace_context;
+typedef struct fz_cmm_engine_s fz_cmm_engine;
+typedef struct fz_cmm_instance_s fz_cmm_instance;
typedef struct fz_aa_context_s fz_aa_context;
typedef struct fz_style_context_s fz_style_context;
typedef struct fz_locks_context_s fz_locks_context;
@@ -118,6 +120,7 @@ struct fz_context_s
fz_warn_context *warn;
fz_font_context *font;
fz_colorspace_context *colorspace;
+ fz_cmm_instance *cmm_instance;
fz_aa_context *aa;
fz_style_context *style;
fz_store *store;
diff --git a/include/mupdf/fitz/device.h b/include/mupdf/fitz/device.h
index 7e7efb43..2f7971c0 100644
--- a/include/mupdf/fitz/device.h
+++ b/include/mupdf/fitz/device.h
@@ -86,25 +86,25 @@ struct fz_device_s
void (*close_device)(fz_context *, fz_device *);
void (*drop_device)(fz_context *, fz_device *);
- void (*fill_path)(fz_context *, fz_device *, const fz_path *, int even_odd, const fz_matrix *, fz_colorspace *, const float *color, float alpha);
- void (*stroke_path)(fz_context *, fz_device *, const fz_path *, const fz_stroke_state *, const fz_matrix *, fz_colorspace *, const float *color, float alpha);
+ void (*fill_path)(fz_context *, fz_device *, const fz_path *, int even_odd, const fz_matrix *, fz_colorspace *, const float *color, float alpha, const fz_color_params *);
+ void (*stroke_path)(fz_context *, fz_device *, const fz_path *, const fz_stroke_state *, const fz_matrix *, fz_colorspace *, const float *color, float alpha, const fz_color_params *);
void (*clip_path)(fz_context *, fz_device *, const fz_path *, int even_odd, const fz_matrix *, const fz_rect *scissor);
void (*clip_stroke_path)(fz_context *, fz_device *, const fz_path *, const fz_stroke_state *, const fz_matrix *, const fz_rect *scissor);
- void (*fill_text)(fz_context *, fz_device *, const fz_text *, const fz_matrix *, fz_colorspace *, const float *color, float alpha);
- void (*stroke_text)(fz_context *, fz_device *, const fz_text *, const fz_stroke_state *, const fz_matrix *, fz_colorspace *, const float *color, float alpha);
+ void (*fill_text)(fz_context *, fz_device *, const fz_text *, const fz_matrix *, fz_colorspace *, const float *color, float alpha, const fz_color_params *);
+ void (*stroke_text)(fz_context *, fz_device *, const fz_text *, const fz_stroke_state *, const fz_matrix *, fz_colorspace *, const float *color, float alpha, const fz_color_params *);
void (*clip_text)(fz_context *, fz_device *, const fz_text *, const fz_matrix *, const fz_rect *scissor);
void (*clip_stroke_text)(fz_context *, fz_device *, const fz_text *, const fz_stroke_state *, const fz_matrix *, const fz_rect *scissor);
void (*ignore_text)(fz_context *, fz_device *, const fz_text *, const fz_matrix *);
- void (*fill_shade)(fz_context *, fz_device *, fz_shade *shd, const fz_matrix *ctm, float alpha);
- void (*fill_image)(fz_context *, fz_device *, fz_image *img, const fz_matrix *ctm, float alpha);
- void (*fill_image_mask)(fz_context *, fz_device *, fz_image *img, const fz_matrix *ctm, fz_colorspace *, const float *color, float alpha);
+ void (*fill_shade)(fz_context *, fz_device *, fz_shade *shd, const fz_matrix *ctm, float alpha, const fz_color_params *color_params);
+ void (*fill_image)(fz_context *, fz_device *, fz_image *img, const fz_matrix *ctm, float alpha, const fz_color_params *color_params);
+ void (*fill_image_mask)(fz_context *, fz_device *, fz_image *img, const fz_matrix *ctm, fz_colorspace *, const float *color, float alpha, const fz_color_params *color_params);
void (*clip_image_mask)(fz_context *, fz_device *, fz_image *img, const fz_matrix *ctm, const fz_rect *scissor);
void (*pop_clip)(fz_context *, fz_device *);
- void (*begin_mask)(fz_context *, fz_device *, const fz_rect *, int luminosity, fz_colorspace *, const float *bc);
+ void (*begin_mask)(fz_context *, fz_device *, const fz_rect *, int luminosity, fz_colorspace *, const float *bc, const fz_color_params *);
void (*end_mask)(fz_context *, fz_device *);
void (*begin_group)(fz_context *, fz_device *, const fz_rect *, int isolated, int knockout, int blendmode, float alpha);
void (*end_group)(fz_context *, fz_device *);
@@ -113,6 +113,7 @@ struct fz_device_s
void (*end_tile)(fz_context *, fz_device *);
void (*render_flags)(fz_context *, fz_device *, int set, int clear);
+ void (*set_default_colorspaces)(fz_context *, fz_device *, fz_default_colorspaces *);
fz_rect d1_rect;
@@ -124,21 +125,21 @@ struct fz_device_s
fz_device_container_stack *container;
};
-void fz_fill_path(fz_context *ctx, fz_device *dev, const fz_path *path, int even_odd, const fz_matrix *ctm, fz_colorspace *colorspace, const float *color, float alpha);
-void fz_stroke_path(fz_context *ctx, fz_device *dev, const fz_path *path, const fz_stroke_state *stroke, const fz_matrix *ctm, fz_colorspace *colorspace, const float *color, float alpha);
+void fz_fill_path(fz_context *ctx, fz_device *dev, const fz_path *path, int even_odd, const fz_matrix *ctm, fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params);
+void fz_stroke_path(fz_context *ctx, fz_device *dev, const fz_path *path, const fz_stroke_state *stroke, const fz_matrix *ctm, fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params);
void fz_clip_path(fz_context *ctx, fz_device *dev, const fz_path *path, int even_odd, const fz_matrix *ctm, const fz_rect *scissor);
void fz_clip_stroke_path(fz_context *ctx, fz_device *dev, const fz_path *path, const fz_stroke_state *stroke, const fz_matrix *ctm, const fz_rect *scissor);
-void fz_fill_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_matrix *ctm, fz_colorspace *colorspace, const float *color, float alpha);
-void fz_stroke_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_stroke_state *stroke, const fz_matrix *ctm, fz_colorspace *colorspace, const float *color, float alpha);
+void fz_fill_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_matrix *ctm, fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params);
+void fz_stroke_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_stroke_state *stroke, const fz_matrix *ctm, fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params);
void fz_clip_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_matrix *ctm, const fz_rect *scissor);
void fz_clip_stroke_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_stroke_state *stroke, const fz_matrix *ctm, const fz_rect *scissor);
void fz_ignore_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_matrix *ctm);
void fz_pop_clip(fz_context *ctx, fz_device *dev);
-void fz_fill_shade(fz_context *ctx, fz_device *dev, fz_shade *shade, const fz_matrix *ctm, float alpha);
-void fz_fill_image(fz_context *ctx, fz_device *dev, fz_image *image, const fz_matrix *ctm, float alpha);
-void fz_fill_image_mask(fz_context *ctx, fz_device *dev, fz_image *image, const fz_matrix *ctm, fz_colorspace *colorspace, const float *color, float alpha);
+void fz_fill_shade(fz_context *ctx, fz_device *dev, fz_shade *shade, const fz_matrix *ctm, float alpha, const fz_color_params *color_params);
+void fz_fill_image(fz_context *ctx, fz_device *dev, fz_image *image, const fz_matrix *ctm, float alpha, const fz_color_params *color_params);
+void fz_fill_image_mask(fz_context *ctx, fz_device *dev, fz_image *image, const fz_matrix *ctm, fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params);
void fz_clip_image_mask(fz_context *ctx, fz_device *dev, fz_image *image, const fz_matrix *ctm, const fz_rect *scissor);
-void fz_begin_mask(fz_context *ctx, fz_device *dev, const fz_rect *area, int luminosity, fz_colorspace *colorspace, const float *bc);
+void fz_begin_mask(fz_context *ctx, fz_device *dev, const fz_rect *area, int luminosity, fz_colorspace *colorspace, const float *bc, const fz_color_params *color_params);
void fz_end_mask(fz_context *ctx, fz_device *dev);
void fz_begin_group(fz_context *ctx, fz_device *dev, const fz_rect *area, int isolated, int knockout, int blendmode, float alpha);
void fz_end_group(fz_context *ctx, fz_device *dev);
@@ -146,7 +147,7 @@ void fz_begin_tile(fz_context *ctx, fz_device *dev, const fz_rect *area, const f
int fz_begin_tile_id(fz_context *ctx, fz_device *dev, const fz_rect *area, const fz_rect *view, float xstep, float ystep, const fz_matrix *ctm, int id);
void fz_end_tile(fz_context *ctx, fz_device *dev);
void fz_render_flags(fz_context *ctx, fz_device *dev, int set, int clear);
-
+void fz_set_default_colorspaces(fz_context *ctx, fz_device *dev, fz_default_colorspaces *default_cs);
fz_device *fz_new_device_of_size(fz_context *ctx, int size);
#define fz_new_derived_device(CTX, TYPE) \
diff --git a/include/mupdf/fitz/document.h b/include/mupdf/fitz/document.h
index 128087a8..23fc4b1d 100644
--- a/include/mupdf/fitz/document.h
+++ b/include/mupdf/fitz/document.h
@@ -98,6 +98,11 @@ typedef fz_page *(fz_document_load_page_fn)(fz_context *ctx, fz_document *doc, i
typedef int (fz_document_lookup_metadata_fn)(fz_context *ctx, fz_document *doc, const char *key, char *buf, int size);
/*
+ fz_document_output_intent_fn: Return output intent color space if it exists
+*/
+typedef fz_colorspace* (fz_document_output_intent_fn)(fz_context *ctx, fz_document *doc);
+
+/*
fz_document_make_bookmark_fn: Type for a function to make
a bookmark. See fz_make_bookmark for more information.
*/
@@ -237,6 +242,7 @@ struct fz_document_s
fz_document_count_pages_fn *count_pages;
fz_document_load_page_fn *load_page;
fz_document_lookup_metadata_fn *lookup_metadata;
+ fz_document_output_intent_fn *get_output_intent;
int did_layout;
int is_reflowable;
};
@@ -609,6 +615,11 @@ int fz_lookup_metadata(fz_context *ctx, fz_document *doc, const char *key, char
#define FZ_META_INFO_TITLE "info:Title"
/*
+ Find the output intent colorspace if the document has defined one.
+*/
+fz_colorspace *fz_document_output_intent(fz_context *ctx, fz_document *doc);
+
+/*
Get the number of separations on a page (including CMYK). This will
be 0, unless the format specifically supports separations (such as
gproof files).
diff --git a/include/mupdf/fitz/font.h b/include/mupdf/fitz/font.h
index 7c71ca05..1a736084 100644
--- a/include/mupdf/fitz/font.h
+++ b/include/mupdf/fitz/font.h
@@ -266,13 +266,25 @@ const char *fz_lookup_builtin_font(fz_context *ctx, const char *name, int bold,
*/
const char *fz_lookup_base14_font(fz_context *ctx, const char *name, int *len);
+/* ToDo: Share fz_lookup_builtin_font and fz_lookup_icc? Check with Tor */
+/*
+ fz_lookup_icc: Search for icc profile.
+
+ name: The name of the profile desired (gray-icc, rgb-icc, cmyk-icc or lab-icc).
+
+ len: Pointer to a place to receive the length of the discovered.
+
+ Returns a pointer to the icc file data, or NULL if not present.
+*/
+const unsigned char *fz_lookup_icc(fz_context *ctx, const char *name, size_t *len);
+
/*
fz_lookup_cjk_font: Search the builtin cjk fonts for a match.
Whether a font is present or not will depend on the
configuration in which MuPDF is built.
registry: The desired registry to lookup in (e.g.
- FZ_ADOBE_KOREA_1)
+ FZ_ADOBE_KOREA_1).
serif: 1 if serif desired, 0 otherwise.
@@ -293,9 +305,9 @@ const char *fz_lookup_cjk_font(fz_context *ctx, int registry, int serif, int wmo
Whether a font is present or not will depend on the
configuration in which MuPDF is built.
- script: The script desired (e.g. UCDN_SCRIPT_KATAKANA)
+ script: The script desired (e.g. UCDN_SCRIPT_KATAKANA).
- lang: The language desired (e.g. FZ_LANG_ja)
+ lang: The language desired (e.g. FZ_LANG_ja).
serif: 1 if serif desired, 0 otherwise.
@@ -336,9 +348,9 @@ const char *fz_lookup_noto_emoji_font(fz_context *ctx, int *len);
present or not will depend on the configuration in which
MuPDF is built.
- script: The script desired (e.g. UCDN_SCRIPT_KATAKANA)
+ script: The script desired (e.g. UCDN_SCRIPT_KATAKANA).
- language: The language desired (e.g. FZ_LANG_ja)
+ language: The language desired (e.g. FZ_LANG_ja).
serif: 1 if serif desired, 0 otherwise.
diff --git a/include/mupdf/fitz/image.h b/include/mupdf/fitz/image.h
index 8a8f5007..13aee534 100644
--- a/include/mupdf/fitz/image.h
+++ b/include/mupdf/fitz/image.h
@@ -26,6 +26,8 @@ typedef struct fz_pixmap_image_s fz_pixmap_image;
image: The image to retrieve a pixmap from.
+ color_params: The color parameters (or NULL for defaults).
+
subarea: The subarea of the image that we actually care about (or NULL
to indicate the whole image).
diff --git a/include/mupdf/fitz/output-png.h b/include/mupdf/fitz/output-png.h
index 8342aead..5c299114 100644
--- a/include/mupdf/fitz/output-png.h
+++ b/include/mupdf/fitz/output-png.h
@@ -30,7 +30,7 @@ fz_band_writer *fz_new_png_band_writer(fz_context *ctx, fz_output *out);
/*
Create a new buffer containing the image/pixmap in PNG format.
*/
-fz_buffer *fz_new_buffer_from_image_as_png(fz_context *ctx, fz_image *image);
-fz_buffer *fz_new_buffer_from_pixmap_as_png(fz_context *ctx, fz_pixmap *pixmap);
+fz_buffer *fz_new_buffer_from_image_as_png(fz_context *ctx, fz_image *image, const fz_color_params *color_params);
+fz_buffer *fz_new_buffer_from_pixmap_as_png(fz_context *ctx, fz_pixmap *pixmap, const fz_color_params *color_params);
#endif
diff --git a/include/mupdf/fitz/pixmap.h b/include/mupdf/fitz/pixmap.h
index 302038ae..5b784c09 100644
--- a/include/mupdf/fitz/pixmap.h
+++ b/include/mupdf/fitz/pixmap.h
@@ -15,6 +15,7 @@
*/
typedef struct fz_pixmap_s fz_pixmap;
+
/*
fz_pixmap_bbox: Return the bounding box for a pixmap.
*/
@@ -275,12 +276,19 @@ fz_pixmap *fz_ensure_pixmap_is_additive(fz_context *ctx, fz_pixmap *pix);
pix: The pixmap to convert.
- cs: Desired colorspace, may be NULL to denote alpha-only.
+ default_cs: If NULL pix->colorspace is used. It is possible that the data
+ may need to be interpreted as one of the color spaces in default_cs.
+
+ cs_des: Desired colorspace, may be NULL to denote alpha-only.
+
+ prf: Proofing color space through which we need to convert.
+
+ color_params: Parameters that may be used in conversion (e.g. ri).
keep_alpha: If 0 any alpha component is removed, otherwise
alpha is kept if present in the pixmap.
*/
-fz_pixmap *fz_convert_pixmap(fz_context *ctx, fz_pixmap *pix, fz_colorspace *src, int keep_alpha);
+fz_pixmap *fz_convert_pixmap(fz_context *ctx, fz_pixmap *pix, fz_colorspace *cs_des, fz_colorspace *prf, fz_default_colorspaces *default_cs, const fz_color_params *color_params, int keep_alpha);
/*
Pixmaps represent a set of pixels for a 2 dimensional region of a
@@ -357,9 +365,10 @@ void fz_decode_indexed_tile(fz_context *ctx, fz_pixmap *pix, const float *decode
void fz_unpack_tile(fz_context *ctx, fz_pixmap *dst, unsigned char * restrict src, int n, int depth, size_t stride, int scale);
/*
- fz_lookup_pixmap_converter: Color convert a pixmap.
+ fz_pixmap_converter: Color convert a pixmap. The passing of default_cs is needed due to the base cs of the image possibly
+ needing to be treated as being in one of the page default color spaces.
*/
-typedef void (fz_pixmap_converter)(fz_context *ctx, fz_pixmap *dp, fz_pixmap *sp);
+typedef void (fz_pixmap_converter)(fz_context *ctx, fz_pixmap *dp, fz_pixmap *sp, fz_colorspace *prf, fz_default_colorspaces *default_cs, const fz_color_params *color_params);
fz_pixmap_converter *fz_lookup_pixmap_converter(fz_context *ctx, fz_colorspace *ds, fz_colorspace *ss);
/*
diff --git a/include/mupdf/fitz/shade.h b/include/mupdf/fitz/shade.h
index 51130dce..d732b9bc 100644
--- a/include/mupdf/fitz/shade.h
+++ b/include/mupdf/fitz/shade.h
@@ -121,10 +121,14 @@ fz_rect *fz_bound_shade(fz_context *ctx, fz_shade *shade, const fz_matrix *ctm,
dest: The pixmap to render into.
+ prf: Proofing color space.
+
+ color_params: The color rendering settings
+
bbox: Pointer to a bounding box to limit the rendering
of the shade.
*/
-void fz_paint_shade(fz_context *ctx, fz_shade *shade, const fz_matrix *ctm, fz_pixmap *dest, const fz_irect *bbox);
+void fz_paint_shade(fz_context *ctx, fz_shade *shade, const fz_matrix *ctm, fz_pixmap *dest, fz_colorspace *prf, const fz_color_params *color_params, const fz_irect *bbox);
/*
* Handy routine for processing mesh based shades
diff --git a/include/mupdf/fitz/store.h b/include/mupdf/fitz/store.h
index 6eab5064..d014378c 100644
--- a/include/mupdf/fitz/store.h
+++ b/include/mupdf/fitz/store.h
@@ -123,20 +123,30 @@ typedef struct fz_store_hash_s
{
const void *ptr;
int i;
- } pi;
+ } pi; /* 8 or 12 bytes */
struct
{
const void *ptr;
int i;
fz_irect r;
- } pir;
+ } pir; /* 24 or 28 bytes */
struct
{
int id;
float m[4];
- } im;
+ } im; /* 20 bytes */
+ struct
+ {
+ unsigned char src_md5[16];
+ unsigned char dst_md5[16];
+ uint8_t ri;
+ uint8_t bp;
+ uint8_t depth;
+ uint8_t alpha;
+ uint8_t proof;
+ } link; /* 36 bytes */
} u;
-} fz_store_hash;
+} fz_store_hash; /* 40 or 44 bytes */
typedef struct fz_store_type_s
{
diff --git a/include/mupdf/pdf/document.h b/include/mupdf/pdf/document.h
index 91324690..c6f5a81a 100644
--- a/include/mupdf/pdf/document.h
+++ b/include/mupdf/pdf/document.h
@@ -576,6 +576,7 @@ struct pdf_document_s
pdf_ocg_descriptor *ocg;
pdf_portfolio *portfolio;
pdf_hotspot hotspot;
+ fz_colorspace *oi;
int max_xref_len;
int num_xref_sections;
diff --git a/include/mupdf/pdf/interpret.h b/include/mupdf/pdf/interpret.h
index ad4807ec..b069da0a 100644
--- a/include/mupdf/pdf/interpret.h
+++ b/include/mupdf/pdf/interpret.h
@@ -123,6 +123,12 @@ struct pdf_processor_s
void (*op_BX)(fz_context *ctx, pdf_processor *proc);
void (*op_EX)(fz_context *ctx, pdf_processor *proc);
+ /* Virtual ops for ExtGState entries */
+ void (*op_gs_OP)(fz_context *ctx, pdf_processor *proc, int b);
+ void (*op_gs_op)(fz_context *ctx, pdf_processor *proc, int b);
+ void (*op_gs_OPM)(fz_context *ctx, pdf_processor *proc, int i);
+ void (*op_gs_UseBlackPtComp)(fz_context *ctx, pdf_processor *proc, pdf_obj *name);
+
/* END is used to signify end of stream (finalise and close down) */
void (*op_END)(fz_context *ctx, pdf_processor *proc);
diff --git a/include/mupdf/pdf/page.h b/include/mupdf/pdf/page.h
index 52d2a4ad..3a077e37 100644
--- a/include/mupdf/pdf/page.h
+++ b/include/mupdf/pdf/page.h
@@ -170,6 +170,11 @@ void pdf_clean_annot_contents(fz_context *ctx, pdf_document *doc, pdf_annot *ann
fz_transition *pdf_page_presentation(fz_context *ctx, pdf_page *page, fz_transition *transition, float *duration);
/*
+ Load default colorspaces for a page.
+*/
+fz_default_colorspaces *pdf_load_default_colorspaces(fz_context *ctx, pdf_document *doc, pdf_page *page);
+
+/*
* Page tree, pages and related objects
*/
diff --git a/include/mupdf/pdf/resource.h b/include/mupdf/pdf/resource.h
index 0b7b9161..36eeb91b 100644
--- a/include/mupdf/pdf/resource.h
+++ b/include/mupdf/pdf/resource.h
@@ -35,6 +35,7 @@ void pdf_drop_function(fz_context *ctx, pdf_function *func);
size_t pdf_function_size(fz_context *ctx, pdf_function *func);
pdf_function *pdf_load_function(fz_context *ctx, pdf_obj *ref, int in, int out);
+fz_colorspace *pdf_document_output_intent(fz_context *ctx, pdf_document *doc);
fz_colorspace *pdf_load_colorspace(fz_context *ctx, pdf_obj *obj);
int pdf_is_tint_colorspace(fz_context *ctx, fz_colorspace *cs);
diff --git a/platform/java/mupdf_native.c b/platform/java/mupdf_native.c
index 137a1c1a..7e88822c 100644
--- a/platform/java/mupdf_native.c
+++ b/platform/java/mupdf_native.c
@@ -1154,6 +1154,14 @@ static inline jobject to_Annotation_safe(fz_context *ctx, JNIEnv *env, fz_annot
return jannot;
}
+static inline jint to_ColorParams_safe(fz_context *ctx, JNIEnv *env, const fz_color_params *cp)
+{
+ if (!ctx || !cp)
+ return 0;
+
+ return (((!!cp->bp)<<5) | ((!!cp->op)<<6) || ((!!cp->opm)<<7) || (cp->ri & 31));
+}
+
static inline jobject to_ColorSpace_safe(fz_context *ctx, JNIEnv *env, fz_colorspace *cs)
{
jobject jcs;
@@ -1700,6 +1708,18 @@ static inline fz_buffer *from_Buffer_safe(JNIEnv *env, jobject jobj)
return CAST(fz_buffer *, (*env)->GetLongField(env, jobj, fid_Buffer_pointer));
}
+static inline fz_color_params from_ColorParams_safe(JNIEnv *env, jint params)
+{
+ fz_color_params p;
+
+ p.bp = (params>>5) & 1;
+ p.op = (params>>6) & 1;
+ p.opm = (params>>7) & 1;
+ p.ri = (params & 31);
+
+ return p;
+}
+
static inline fz_colorspace *from_ColorSpace_safe(JNIEnv *env, jobject jobj)
{
if (!jobj) return NULL;
@@ -1837,7 +1857,7 @@ typedef struct
fz_java_device;
static void
-fz_java_device_fill_path(fz_context *ctx, fz_device *dev, const fz_path *path, int even_odd, const fz_matrix *ctm, fz_colorspace *cs, const float *color, float alpha)
+fz_java_device_fill_path(fz_context *ctx, fz_device *dev, const fz_path *path, int even_odd, const fz_matrix *ctm, fz_colorspace *cs, const float *color, float alpha, const fz_color_params *cs_params)
{
fz_java_device *jdev = (fz_java_device *)dev;
JNIEnv *env = jdev->env;
@@ -1845,14 +1865,15 @@ fz_java_device_fill_path(fz_context *ctx, fz_device *dev, const fz_path *path, i
jobject jcs = to_ColorSpace(ctx, env, cs);
jobject jctm = to_Matrix(ctx, env, ctm);
jfloatArray jcolor = to_jfloatArray(ctx, env, color, cs ? fz_colorspace_n(ctx, cs) : FZ_MAX_COLORS);
+ int jcp = to_ColorParams_safe(ctx, env, cs_params);
- (*env)->CallVoidMethod(env, jdev->self, mid_Device_fillPath, jpath, (jboolean)even_odd, jctm, jcs, jcolor, alpha);
+ (*env)->CallVoidMethod(env, jdev->self, mid_Device_fillPath, jpath, (jboolean)even_odd, jctm, jcs, jcolor, alpha, jcp);
if ((*env)->ExceptionCheck(env))
fz_throw_java(ctx, env);
}
static void
-fz_java_device_stroke_path(fz_context *ctx, fz_device *dev, const fz_path *path, const fz_stroke_state *state, const fz_matrix *ctm, fz_colorspace *cs, const float *color, float alpha)
+fz_java_device_stroke_path(fz_context *ctx, fz_device *dev, const fz_path *path, const fz_stroke_state *state, const fz_matrix *ctm, fz_colorspace *cs, const float *color, float alpha, const fz_color_params *cs_params)
{
fz_java_device *jdev = (fz_java_device *)dev;
JNIEnv *env = jdev->env;
@@ -1861,8 +1882,9 @@ fz_java_device_stroke_path(fz_context *ctx, fz_device *dev, const fz_path *path,
jobject jcs = to_ColorSpace(ctx, env, cs);
jobject jctm = to_Matrix(ctx, env, ctm);
jfloatArray jcolor = to_jfloatArray(ctx, env, color, cs ? fz_colorspace_n(ctx, cs) : FZ_MAX_COLORS);
+ int jcp = to_ColorParams_safe(ctx, env, cs_params);
- (*env)->CallVoidMethod(env, jdev->self, mid_Device_strokePath, jpath, jstate, jctm, jcs, jcolor, alpha);
+ (*env)->CallVoidMethod(env, jdev->self, mid_Device_strokePath, jpath, jstate, jctm, jcs, jcolor, alpha, jcp);
if ((*env)->ExceptionCheck(env))
fz_throw_java(ctx, env);
}
@@ -1895,7 +1917,7 @@ fz_java_device_clip_stroke_path(fz_context *ctx, fz_device *dev, const fz_path *
}
static void
-fz_java_device_fill_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_matrix *ctm, fz_colorspace *cs, const float *color, float alpha)
+fz_java_device_fill_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_matrix *ctm, fz_colorspace *cs, const float *color, float alpha, const fz_color_params *cs_params)
{
fz_java_device *jdev = (fz_java_device *)dev;
JNIEnv *env = jdev->env;
@@ -1903,14 +1925,15 @@ fz_java_device_fill_text(fz_context *ctx, fz_device *dev, const fz_text *text, c
jobject jctm = to_Matrix(ctx, env, ctm);
jobject jcs = to_ColorSpace(ctx, env, cs);
jfloatArray jcolor = to_jfloatArray(ctx, env, color, cs ? fz_colorspace_n(ctx, cs) : FZ_MAX_COLORS);
+ int jcp = to_ColorParams_safe(ctx, env, cs_params);
- (*env)->CallVoidMethod(env, jdev->self, mid_Device_fillText, jtext, jctm, jcs, jcolor, alpha);
+ (*env)->CallVoidMethod(env, jdev->self, mid_Device_fillText, jtext, jctm, jcs, jcolor, alpha, jcp);
if ((*env)->ExceptionCheck(env))
fz_throw_java(ctx, env);
}
static void
-fz_java_device_stroke_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_stroke_state *state, const fz_matrix *ctm, fz_colorspace *cs, const float *color, float alpha)
+fz_java_device_stroke_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_stroke_state *state, const fz_matrix *ctm, fz_colorspace *cs, const float *color, float alpha, const fz_color_params *cs_params)
{
fz_java_device *jdev = (fz_java_device *)dev;
JNIEnv *env = jdev->env;
@@ -1919,8 +1942,9 @@ fz_java_device_stroke_text(fz_context *ctx, fz_device *dev, const fz_text *text,
jobject jctm = to_Matrix(ctx, env, ctm);
jobject jcs = to_ColorSpace(ctx, env, cs);
jfloatArray jcolor = to_jfloatArray(ctx, env, color, cs ? fz_colorspace_n(ctx, cs) : FZ_MAX_COLORS);
+ int jcp = to_ColorParams_safe(ctx, env, cs_params);
- (*env)->CallVoidMethod(env, jdev->self, mid_Device_strokeText, jtext, jstate, jctm, jcs, jcolor, alpha);
+ (*env)->CallVoidMethod(env, jdev->self, mid_Device_strokeText, jtext, jstate, jctm, jcs, jcolor, alpha, jcp);
if ((*env)->ExceptionCheck(env))
fz_throw_java(ctx, env);
}
@@ -1966,7 +1990,7 @@ fz_java_device_ignore_text(fz_context *ctx, fz_device *dev, const fz_text *text,
}
static void
-fz_java_device_fill_shade(fz_context *ctx, fz_device *dev, fz_shade *shd, const fz_matrix *ctm, float alpha)
+fz_java_device_fill_shade(fz_context *ctx, fz_device *dev, fz_shade *shd, const fz_matrix *ctm, float alpha, const fz_color_params *color_params)
{
fz_java_device *jdev = (fz_java_device *)dev;
JNIEnv *env = jdev->env;
@@ -1979,7 +2003,7 @@ fz_java_device_fill_shade(fz_context *ctx, fz_device *dev, fz_shade *shd, const
}
static void
-fz_java_device_fill_image(fz_context *ctx, fz_device *dev, fz_image *img, const fz_matrix *ctm, float alpha)
+fz_java_device_fill_image(fz_context *ctx, fz_device *dev, fz_image *img, const fz_matrix *ctm, float alpha, const fz_color_params *color_params)
{
fz_java_device *jdev = (fz_java_device *)dev;
JNIEnv *env = jdev->env;
@@ -1992,7 +2016,7 @@ fz_java_device_fill_image(fz_context *ctx, fz_device *dev, fz_image *img, const
}
static void
-fz_java_device_fill_image_mask(fz_context *ctx, fz_device *dev, fz_image *img, const fz_matrix *ctm, fz_colorspace *cs, const float *color, float alpha)
+fz_java_device_fill_image_mask(fz_context *ctx, fz_device *dev, fz_image *img, const fz_matrix *ctm, fz_colorspace *cs, const float *color, float alpha, const fz_color_params *cs_params)
{
fz_java_device *jdev = (fz_java_device *)dev;
JNIEnv *env = jdev->env;
@@ -2000,8 +2024,9 @@ fz_java_device_fill_image_mask(fz_context *ctx, fz_device *dev, fz_image *img, c
jobject jctm = to_Matrix(ctx, env, ctm);
jobject jcs = to_ColorSpace(ctx, env, cs);
jfloatArray jcolor = to_jfloatArray(ctx, env, color, cs ? fz_colorspace_n(ctx, cs) : FZ_MAX_COLORS);
+ int jcp = to_ColorParams_safe(ctx, env, cs_params);
- (*env)->CallVoidMethod(env, jdev->self, mid_Device_fillImageMask, jimg, jctm, jcs, jcolor, alpha);
+ (*env)->CallVoidMethod(env, jdev->self, mid_Device_fillImageMask, jimg, jctm, jcs, jcolor, alpha, jcp);
if ((*env)->ExceptionCheck(env))
fz_throw_java(ctx, env);
}
@@ -2031,15 +2056,16 @@ fz_java_device_pop_clip(fz_context *ctx, fz_device *dev)
}
static void
-fz_java_device_begin_mask(fz_context *ctx, fz_device *dev, const fz_rect *rect, int luminosity, fz_colorspace *cs, const float *bc)
+fz_java_device_begin_mask(fz_context *ctx, fz_device *dev, const fz_rect *rect, int luminosity, fz_colorspace *cs, const float *bc, const fz_color_params *cs_params)
{
fz_java_device *jdev = (fz_java_device *)dev;
JNIEnv *env = jdev->env;
jobject jrect = to_Rect(ctx, env, rect);
jobject jcs = to_ColorSpace(ctx, env, cs);
jfloatArray jbc = to_jfloatArray(ctx, env, bc, cs ? fz_colorspace_n(ctx, cs) : FZ_MAX_COLORS);
+ int jcp = to_ColorParams_safe(ctx, env, cs_params);
- (*env)->CallVoidMethod(env, jdev->self, mid_Device_beginMask, jrect, (jint)luminosity, jcs, jbc);
+ (*env)->CallVoidMethod(env, jdev->self, mid_Device_beginMask, jrect, (jint)luminosity, jcs, jbc, jcp);
if ((*env)->ExceptionCheck(env))
fz_throw_java(ctx, env);
}
@@ -2290,7 +2316,7 @@ FUN(NativeDevice_close)(JNIEnv *env, jobject self)
}
JNIEXPORT void JNICALL
-FUN(NativeDevice_fillPath)(JNIEnv *env, jobject self, jobject jpath, jboolean even_odd, jobject jctm, jobject jcs, jfloatArray jcolor, jfloat alpha)
+FUN(NativeDevice_fillPath)(JNIEnv *env, jobject self, jobject jpath, jboolean even_odd, jobject jctm, jobject jcs, jfloatArray jcolor, jfloat alpha, jint jcp)
{
fz_context *ctx = get_context(env);
fz_device *dev = from_Device(env, self);
@@ -2299,6 +2325,7 @@ FUN(NativeDevice_fillPath)(JNIEnv *env, jobject self, jobject jpath, jboolean ev
fz_colorspace *cs = from_ColorSpace(env, jcs);
float color[FZ_MAX_COLORS];
NativeDeviceInfo *info;
+ fz_color_params cp = from_ColorParams_safe(env, jcp);
if (!ctx || !dev) return;
if (!path) { jni_throw_arg(env, "path must not be null"); return; }
@@ -2306,7 +2333,7 @@ FUN(NativeDevice_fillPath)(JNIEnv *env, jobject self, jobject jpath, jboolean ev
info = lockNativeDevice(env, self);
fz_try(ctx)
- fz_fill_path(ctx, dev, path, even_odd, &ctm, cs, color, alpha);
+ fz_fill_path(ctx, dev, path, even_odd, &ctm, cs, color, alpha, &cp);
fz_always(ctx)
unlockNativeDevice(env, info);
fz_catch(ctx)
@@ -2314,7 +2341,7 @@ FUN(NativeDevice_fillPath)(JNIEnv *env, jobject self, jobject jpath, jboolean ev
}
JNIEXPORT void JNICALL
-FUN(NativeDevice_strokePath)(JNIEnv *env, jobject self, jobject jpath, jobject jstroke, jobject jctm, jobject jcs, jfloatArray jcolor, jfloat alpha)
+FUN(NativeDevice_strokePath)(JNIEnv *env, jobject self, jobject jpath, jobject jstroke, jobject jctm, jobject jcs, jfloatArray jcolor, jfloat alpha, jint jcp)
{
fz_context *ctx = get_context(env);
fz_device *dev = from_Device(env, self);
@@ -2322,6 +2349,7 @@ FUN(NativeDevice_strokePath)(JNIEnv *env, jobject self, jobject jpath, jobject j
fz_stroke_state *stroke = from_StrokeState(env, jstroke);
fz_matrix ctm = from_Matrix(env, jctm);
fz_colorspace *cs = from_ColorSpace(env, jcs);
+ fz_color_params cp = from_ColorParams_safe(env, jcp);
float color[FZ_MAX_COLORS];
NativeDeviceInfo *info;
@@ -2332,7 +2360,7 @@ FUN(NativeDevice_strokePath)(JNIEnv *env, jobject self, jobject jpath, jobject j
info = lockNativeDevice(env, self);
fz_try(ctx)
- fz_stroke_path(ctx, dev, path, stroke, &ctm, cs, color, alpha);
+ fz_stroke_path(ctx, dev, path, stroke, &ctm, cs, color, alpha, &cp);
fz_always(ctx)
unlockNativeDevice(env, info);
fz_catch(ctx)
@@ -2384,13 +2412,14 @@ FUN(NativeDevice_clipStrokePath)(JNIEnv *env, jobject self, jobject jpath, jobje
}
JNIEXPORT void JNICALL
-FUN(NativeDevice_fillText)(JNIEnv *env, jobject self, jobject jtext, jobject jctm, jobject jcs, jfloatArray jcolor, jfloat alpha)
+FUN(NativeDevice_fillText)(JNIEnv *env, jobject self, jobject jtext, jobject jctm, jobject jcs, jfloatArray jcolor, jfloat alpha, jint jcp)
{
fz_context *ctx = get_context(env);
fz_device *dev = from_Device(env, self);
fz_text *text = from_Text(env, jtext);
fz_matrix ctm = from_Matrix(env, jctm);
fz_colorspace *cs = from_ColorSpace(env, jcs);
+ fz_color_params cp = from_ColorParams_safe(env, jcp);
float color[FZ_MAX_COLORS];
NativeDeviceInfo *info;
@@ -2400,7 +2429,7 @@ FUN(NativeDevice_fillText)(JNIEnv *env, jobject self, jobject jtext, jobject jct
info = lockNativeDevice(env, self);
fz_try(ctx)
- fz_fill_text(ctx, dev, text, &ctm, cs, color, alpha);
+ fz_fill_text(ctx, dev, text, &ctm, cs, color, alpha, &cp);
fz_always(ctx)
unlockNativeDevice(env, info);
fz_catch(ctx)
@@ -2408,7 +2437,7 @@ FUN(NativeDevice_fillText)(JNIEnv *env, jobject self, jobject jtext, jobject jct
}
JNIEXPORT void JNICALL
-FUN(NativeDevice_strokeText)(JNIEnv *env, jobject self, jobject jtext, jobject jstroke, jobject jctm, jobject jcs, jfloatArray jcolor, jfloat alpha)
+FUN(NativeDevice_strokeText)(JNIEnv *env, jobject self, jobject jtext, jobject jstroke, jobject jctm, jobject jcs, jfloatArray jcolor, jfloat alpha, jint jcp)
{
fz_context *ctx = get_context(env);
fz_device *dev = from_Device(env, self);
@@ -2416,6 +2445,7 @@ FUN(NativeDevice_strokeText)(JNIEnv *env, jobject self, jobject jtext, jobject j
fz_stroke_state *stroke = from_StrokeState(env, jstroke);
fz_matrix ctm = from_Matrix(env, jctm);
fz_colorspace *cs = from_ColorSpace(env, jcs);
+ fz_color_params cp = from_ColorParams_safe(env, jcp);
float color[FZ_MAX_COLORS];
NativeDeviceInfo *info;
@@ -2426,7 +2456,7 @@ FUN(NativeDevice_strokeText)(JNIEnv *env, jobject self, jobject jtext, jobject j
info = lockNativeDevice(env, self);
fz_try(ctx)
- fz_stroke_text(ctx, dev, text, stroke, &ctm, cs, color, alpha);
+ fz_stroke_text(ctx, dev, text, stroke, &ctm, cs, color, alpha, &cp);
fz_always(ctx)
unlockNativeDevice(env, info);
fz_catch(ctx)
@@ -2499,12 +2529,13 @@ FUN(NativeDevice_ignoreText)(JNIEnv *env, jobject self, jobject jtext, jobject j
}
JNIEXPORT void JNICALL
-FUN(NativeDevice_fillShade)(JNIEnv *env, jobject self, jobject jshd, jobject jctm, jfloat alpha)
+FUN(NativeDevice_fillShade)(JNIEnv *env, jobject self, jobject jshd, jobject jctm, jfloat alpha, jint jcp)
{
fz_context *ctx = get_context(env);
fz_device *dev = from_Device(env, self);
fz_shade *shd = from_Shade(env, jshd);
fz_matrix ctm = from_Matrix(env, jctm);
+ fz_color_params cp = from_ColorParams_safe(env, jcp);
NativeDeviceInfo *info;
if (!ctx || !dev) return;
@@ -2512,7 +2543,7 @@ FUN(NativeDevice_fillShade)(JNIEnv *env, jobject self, jobject jshd, jobject jct
info = lockNativeDevice(env, self);
fz_try(ctx)
- fz_fill_shade(ctx, dev, shd, &ctm, alpha);
+ fz_fill_shade(ctx, dev, shd, &ctm, alpha, &cp);
fz_always(ctx)
unlockNativeDevice(env, info);
fz_catch(ctx)
@@ -2520,12 +2551,13 @@ FUN(NativeDevice_fillShade)(JNIEnv *env, jobject self, jobject jshd, jobject jct
}
JNIEXPORT void JNICALL
-FUN(NativeDevice_fillImage)(JNIEnv *env, jobject self, jobject jimg, jobject jctm, jfloat alpha)
+FUN(NativeDevice_fillImage)(JNIEnv *env, jobject self, jobject jimg, jobject jctm, jfloat alpha, jint jcp)
{
fz_context *ctx = get_context(env);
fz_device *dev = from_Device(env, self);
fz_image *img = from_Image(env, jimg);
fz_matrix ctm = from_Matrix(env, jctm);
+ fz_color_params cp = from_ColorParams_safe(env, jcp);
NativeDeviceInfo *info;
if (!ctx || !dev) return;
@@ -2533,7 +2565,7 @@ FUN(NativeDevice_fillImage)(JNIEnv *env, jobject self, jobject jimg, jobject jct
info = lockNativeDevice(env, self);
fz_try(ctx)
- fz_fill_image(ctx, dev, img, &ctm, alpha);
+ fz_fill_image(ctx, dev, img, &ctm, alpha, &cp);
fz_always(ctx)
unlockNativeDevice(env, info);
fz_catch(ctx)
@@ -2541,13 +2573,14 @@ FUN(NativeDevice_fillImage)(JNIEnv *env, jobject self, jobject jimg, jobject jct
}
JNIEXPORT void JNICALL
-FUN(NativeDevice_fillImageMask)(JNIEnv *env, jobject self, jobject jimg, jobject jctm, jobject jcs, jfloatArray jcolor, jfloat alpha)
+FUN(NativeDevice_fillImageMask)(JNIEnv *env, jobject self, jobject jimg, jobject jctm, jobject jcs, jfloatArray jcolor, jfloat alpha, jint jcp)
{
fz_context *ctx = get_context(env);
fz_device *dev = from_Device(env, self);
fz_image *img = from_Image(env, jimg);
fz_matrix ctm = from_Matrix(env, jctm);
fz_colorspace *cs = from_ColorSpace(env, jcs);
+ fz_color_params cp = from_ColorParams_safe(env, jcp);
float color[FZ_MAX_COLORS];
NativeDeviceInfo *info;
@@ -2557,7 +2590,7 @@ FUN(NativeDevice_fillImageMask)(JNIEnv *env, jobject self, jobject jimg, jobject
info = lockNativeDevice(env, self);
fz_try(ctx)
- fz_fill_image_mask(ctx, dev, img, &ctm, cs, color, alpha);
+ fz_fill_image_mask(ctx, dev, img, &ctm, cs, color, alpha, &cp);
fz_always(ctx)
unlockNativeDevice(env, info);
fz_catch(ctx)
@@ -2604,12 +2637,13 @@ FUN(NativeDevice_popClip)(JNIEnv *env, jobject self)
}
JNIEXPORT void JNICALL
-FUN(NativeDevice_beginMask)(JNIEnv *env, jobject self, jobject jrect, jboolean luminosity, jobject jcs, jfloatArray jcolor)
+FUN(NativeDevice_beginMask)(JNIEnv *env, jobject self, jobject jrect, jboolean luminosity, jobject jcs, jfloatArray jcolor, jint jcp)
{
fz_context *ctx = get_context(env);
fz_device *dev = from_Device(env, self);
fz_rect rect = from_Rect(env, jrect);
fz_colorspace *cs = from_ColorSpace(env, jcs);
+ fz_color_params cp = from_ColorParams_safe(env, jcp);
float color[FZ_MAX_COLORS];
NativeDeviceInfo *info;
@@ -2618,7 +2652,7 @@ FUN(NativeDevice_beginMask)(JNIEnv *env, jobject self, jobject jrect, jboolean l
info = lockNativeDevice(env, self);
fz_try(ctx)
- fz_begin_mask(ctx, dev, &rect, luminosity, cs, color);
+ fz_begin_mask(ctx, dev, &rect, luminosity, cs, color, &cp);
fz_always(ctx)
unlockNativeDevice(env, info);
fz_catch(ctx)
@@ -8123,7 +8157,7 @@ FUN(PDFGraftMap_graftObject)(JNIEnv *env, jobject self, jobject jobj)
/* PDFPage interface */
JNIEXPORT jobject JNICALL
-FUN(PDFPage_createAnnotation)(JNIEnv *env, jobject self, int subtype)
+FUN(PDFPage_createAnnotation)(JNIEnv *env, jobject self, jint subtype)
{
fz_context *ctx = get_context(env);
pdf_page *page = from_PDFPage(env, self);
diff --git a/platform/java/mupdf_native.h b/platform/java/mupdf_native.h
index cdcebc50..d7355376 100644
--- a/platform/java/mupdf_native.h
+++ b/platform/java/mupdf_native.h
@@ -208,6 +208,34 @@ extern "C" {
}
#endif
#endif
+/* Header for class com_artifex_mupdf_fitz_ColorParams_RenderingIntent */
+
+#ifndef _Included_com_artifex_mupdf_fitz_ColorParams_RenderingIntent
+#define _Included_com_artifex_mupdf_fitz_ColorParams_RenderingIntent
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class com_artifex_mupdf_fitz_ColorParams */
+
+#ifndef _Included_com_artifex_mupdf_fitz_ColorParams
+#define _Included_com_artifex_mupdf_fitz_ColorParams
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef com_artifex_mupdf_fitz_ColorParams_BP
+#define com_artifex_mupdf_fitz_ColorParams_BP 32L
+#undef com_artifex_mupdf_fitz_ColorParams_OP
+#define com_artifex_mupdf_fitz_ColorParams_OP 64L
+#undef com_artifex_mupdf_fitz_ColorParams_OPM
+#define com_artifex_mupdf_fitz_ColorParams_OPM 128L
+#ifdef __cplusplus
+}
+#endif
+#endif
/* Header for class com_artifex_mupdf_fitz_ColorSpace */
#ifndef _Included_com_artifex_mupdf_fitz_ColorSpace
@@ -1121,18 +1149,18 @@ JNIEXPORT void JNICALL Java_com_artifex_mupdf_fitz_NativeDevice_close
/*
* Class: com_artifex_mupdf_fitz_NativeDevice
* Method: fillPath
- * Signature: (Lcom/artifex/mupdf/fitz/Path;ZLcom/artifex/mupdf/fitz/Matrix;Lcom/artifex/mupdf/fitz/ColorSpace;[FF)V
+ * Signature: (Lcom/artifex/mupdf/fitz/Path;ZLcom/artifex/mupdf/fitz/Matrix;Lcom/artifex/mupdf/fitz/ColorSpace;[FFI)V
*/
JNIEXPORT void JNICALL Java_com_artifex_mupdf_fitz_NativeDevice_fillPath
- (JNIEnv *, jobject, jobject, jboolean, jobject, jobject, jfloatArray, jfloat);
+ (JNIEnv *, jobject, jobject, jboolean, jobject, jobject, jfloatArray, jfloat, jint);
/*
* Class: com_artifex_mupdf_fitz_NativeDevice
* Method: strokePath
- * Signature: (Lcom/artifex/mupdf/fitz/Path;Lcom/artifex/mupdf/fitz/StrokeState;Lcom/artifex/mupdf/fitz/Matrix;Lcom/artifex/mupdf/fitz/ColorSpace;[FF)V
+ * Signature: (Lcom/artifex/mupdf/fitz/Path;Lcom/artifex/mupdf/fitz/StrokeState;Lcom/artifex/mupdf/fitz/Matrix;Lcom/artifex/mupdf/fitz/ColorSpace;[FFI)V
*/
JNIEXPORT void JNICALL Java_com_artifex_mupdf_fitz_NativeDevice_strokePath
- (JNIEnv *, jobject, jobject, jobject, jobject, jobject, jfloatArray, jfloat);
+ (JNIEnv *, jobject, jobject, jobject, jobject, jobject, jfloatArray, jfloat, jint);
/*
* Class: com_artifex_mupdf_fitz_NativeDevice
@@ -1153,18 +1181,18 @@ JNIEXPORT void JNICALL Java_com_artifex_mupdf_fitz_NativeDevice_clipStrokePath
/*
* Class: com_artifex_mupdf_fitz_NativeDevice
* Method: fillText
- * Signature: (Lcom/artifex/mupdf/fitz/Text;Lcom/artifex/mupdf/fitz/Matrix;Lcom/artifex/mupdf/fitz/ColorSpace;[FF)V
+ * Signature: (Lcom/artifex/mupdf/fitz/Text;Lcom/artifex/mupdf/fitz/Matrix;Lcom/artifex/mupdf/fitz/ColorSpace;[FFI)V
*/
JNIEXPORT void JNICALL Java_com_artifex_mupdf_fitz_NativeDevice_fillText
- (JNIEnv *, jobject, jobject, jobject, jobject, jfloatArray, jfloat);
+ (JNIEnv *, jobject, jobject, jobject, jobject, jfloatArray, jfloat, jint);
/*
* Class: com_artifex_mupdf_fitz_NativeDevice
* Method: strokeText
- * Signature: (Lcom/artifex/mupdf/fitz/Text;Lcom/artifex/mupdf/fitz/StrokeState;Lcom/artifex/mupdf/fitz/Matrix;Lcom/artifex/mupdf/fitz/ColorSpace;[FF)V
+ * Signature: (Lcom/artifex/mupdf/fitz/Text;Lcom/artifex/mupdf/fitz/StrokeState;Lcom/artifex/mupdf/fitz/Matrix;Lcom/artifex/mupdf/fitz/ColorSpace;[FFI)V
*/
JNIEXPORT void JNICALL Java_com_artifex_mupdf_fitz_NativeDevice_strokeText
- (JNIEnv *, jobject, jobject, jobject, jobject, jobject, jfloatArray, jfloat);
+ (JNIEnv *, jobject, jobject, jobject, jobject, jobject, jfloatArray, jfloat, jint);
/*
* Class: com_artifex_mupdf_fitz_NativeDevice
@@ -1193,26 +1221,26 @@ JNIEXPORT void JNICALL Java_com_artifex_mupdf_fitz_NativeDevice_ignoreText
/*
* Class: com_artifex_mupdf_fitz_NativeDevice
* Method: fillShade
- * Signature: (Lcom/artifex/mupdf/fitz/Shade;Lcom/artifex/mupdf/fitz/Matrix;F)V
+ * Signature: (Lcom/artifex/mupdf/fitz/Shade;Lcom/artifex/mupdf/fitz/Matrix;FI)V
*/
JNIEXPORT void JNICALL Java_com_artifex_mupdf_fitz_NativeDevice_fillShade
- (JNIEnv *, jobject, jobject, jobject, jfloat);
+ (JNIEnv *, jobject, jobject, jobject, jfloat, jint);
/*
* Class: com_artifex_mupdf_fitz_NativeDevice
* Method: fillImage
- * Signature: (Lcom/artifex/mupdf/fitz/Image;Lcom/artifex/mupdf/fitz/Matrix;F)V
+ * Signature: (Lcom/artifex/mupdf/fitz/Image;Lcom/artifex/mupdf/fitz/Matrix;FI)V
*/
JNIEXPORT void JNICALL Java_com_artifex_mupdf_fitz_NativeDevice_fillImage
- (JNIEnv *, jobject, jobject, jobject, jfloat);
+ (JNIEnv *, jobject, jobject, jobject, jfloat, jint);
/*
* Class: com_artifex_mupdf_fitz_NativeDevice
* Method: fillImageMask
- * Signature: (Lcom/artifex/mupdf/fitz/Image;Lcom/artifex/mupdf/fitz/Matrix;Lcom/artifex/mupdf/fitz/ColorSpace;[FF)V
+ * Signature: (Lcom/artifex/mupdf/fitz/Image;Lcom/artifex/mupdf/fitz/Matrix;Lcom/artifex/mupdf/fitz/ColorSpace;[FFI)V
*/
JNIEXPORT void JNICALL Java_com_artifex_mupdf_fitz_NativeDevice_fillImageMask
- (JNIEnv *, jobject, jobject, jobject, jobject, jfloatArray, jfloat);
+ (JNIEnv *, jobject, jobject, jobject, jobject, jfloatArray, jfloat, jint);
/*
* Class: com_artifex_mupdf_fitz_NativeDevice
@@ -1233,10 +1261,10 @@ JNIEXPORT void JNICALL Java_com_artifex_mupdf_fitz_NativeDevice_popClip
/*
* Class: com_artifex_mupdf_fitz_NativeDevice
* Method: beginMask
- * Signature: (Lcom/artifex/mupdf/fitz/Rect;ZLcom/artifex/mupdf/fitz/ColorSpace;[F)V
+ * Signature: (Lcom/artifex/mupdf/fitz/Rect;ZLcom/artifex/mupdf/fitz/ColorSpace;[FI)V
*/
JNIEXPORT void JNICALL Java_com_artifex_mupdf_fitz_NativeDevice_beginMask
- (JNIEnv *, jobject, jobject, jboolean, jobject, jfloatArray);
+ (JNIEnv *, jobject, jobject, jboolean, jobject, jfloatArray, jint);
/*
* Class: com_artifex_mupdf_fitz_NativeDevice
@@ -1293,6 +1321,263 @@ extern "C" {
}
#endif
#endif
+/* Header for class com_artifex_mupdf_fitz_Page */
+
+#ifndef _Included_com_artifex_mupdf_fitz_Page
+#define _Included_com_artifex_mupdf_fitz_Page
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: com_artifex_mupdf_fitz_Page
+ * Method: finalize
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_artifex_mupdf_fitz_Page_finalize
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_artifex_mupdf_fitz_Page
+ * Method: getBounds
+ * Signature: ()Lcom/artifex/mupdf/fitz/Rect;
+ */
+JNIEXPORT jobject JNICALL Java_com_artifex_mupdf_fitz_Page_getBounds
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_artifex_mupdf_fitz_Page
+ * Method: toPixmap
+ * Signature: (Lcom/artifex/mupdf/fitz/Matrix;Lcom/artifex/mupdf/fitz/ColorSpace;Z)Lcom/artifex/mupdf/fitz/Pixmap;
+ */
+JNIEXPORT jobject JNICALL Java_com_artifex_mupdf_fitz_Page_toPixmap
+ (JNIEnv *, jobject, jobject, jobject, jboolean);
+
+/*
+ * Class: com_artifex_mupdf_fitz_Page
+ * Method: run
+ * Signature: (Lcom/artifex/mupdf/fitz/Device;Lcom/artifex/mupdf/fitz/Matrix;Lcom/artifex/mupdf/fitz/Cookie;)V
+ */
+JNIEXPORT void JNICALL Java_com_artifex_mupdf_fitz_Page_run
+ (JNIEnv *, jobject, jobject, jobject, jobject);
+
+/*
+ * Class: com_artifex_mupdf_fitz_Page
+ * Method: runPageContents
+ * Signature: (Lcom/artifex/mupdf/fitz/Device;Lcom/artifex/mupdf/fitz/Matrix;Lcom/artifex/mupdf/fitz/Cookie;)V
+ */
+JNIEXPORT void JNICALL Java_com_artifex_mupdf_fitz_Page_runPageContents
+ (JNIEnv *, jobject, jobject, jobject, jobject);
+
+/*
+ * Class: com_artifex_mupdf_fitz_Page
+ * Method: getAnnotations
+ * Signature: ()[Lcom/artifex/mupdf/fitz/Annotation;
+ */
+JNIEXPORT jobjectArray JNICALL Java_com_artifex_mupdf_fitz_Page_getAnnotations
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_artifex_mupdf_fitz_Page
+ * Method: getLinks
+ * Signature: ()[Lcom/artifex/mupdf/fitz/Link;
+ */
+JNIEXPORT jobjectArray JNICALL Java_com_artifex_mupdf_fitz_Page_getLinks
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_artifex_mupdf_fitz_Page
+ * Method: toDisplayList
+ * Signature: (Z)Lcom/artifex/mupdf/fitz/DisplayList;
+ */
+JNIEXPORT jobject JNICALL Java_com_artifex_mupdf_fitz_Page_toDisplayList
+ (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class: com_artifex_mupdf_fitz_Page
+ * Method: toStructuredText
+ * Signature: (Ljava/lang/String;)Lcom/artifex/mupdf/fitz/StructuredText;
+ */
+JNIEXPORT jobject JNICALL Java_com_artifex_mupdf_fitz_Page_toStructuredText
+ (JNIEnv *, jobject, jstring);
+
+/*
+ * Class: com_artifex_mupdf_fitz_Page
+ * Method: search
+ * Signature: (Ljava/lang/String;)[Lcom/artifex/mupdf/fitz/Rect;
+ */
+JNIEXPORT jobjectArray JNICALL Java_com_artifex_mupdf_fitz_Page_search
+ (JNIEnv *, jobject, jstring);
+
+/*
+ * Class: com_artifex_mupdf_fitz_Page
+ * Method: textAsHtml
+ * Signature: ()[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_com_artifex_mupdf_fitz_Page_textAsHtml
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_artifex_mupdf_fitz_Page
+ * Method: countSeparations
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_artifex_mupdf_fitz_Page_countSeparations
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_artifex_mupdf_fitz_Page
+ * Method: getSeparation
+ * Signature: (I)Lcom/artifex/mupdf/fitz/Separation;
+ */
+JNIEXPORT jobject JNICALL Java_com_artifex_mupdf_fitz_Page_getSeparation
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_artifex_mupdf_fitz_Page
+ * Method: enableSeparation
+ * Signature: (IZ)V
+ */
+JNIEXPORT void JNICALL Java_com_artifex_mupdf_fitz_Page_enableSeparation
+ (JNIEnv *, jobject, jint, jboolean);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class com_artifex_mupdf_fitz_Path */
+
+#ifndef _Included_com_artifex_mupdf_fitz_Path
+#define _Included_com_artifex_mupdf_fitz_Path
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: com_artifex_mupdf_fitz_Path
+ * Method: finalize
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_artifex_mupdf_fitz_Path_finalize
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_artifex_mupdf_fitz_Path
+ * Method: newNative
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_com_artifex_mupdf_fitz_Path_newNative
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_artifex_mupdf_fitz_Path
+ * Method: cloneNative
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_com_artifex_mupdf_fitz_Path_cloneNative
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_artifex_mupdf_fitz_Path
+ * Method: currentPoint
+ * Signature: ()Lcom/artifex/mupdf/fitz/Point;
+ */
+JNIEXPORT jobject JNICALL Java_com_artifex_mupdf_fitz_Path_currentPoint
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_artifex_mupdf_fitz_Path
+ * Method: moveTo
+ * Signature: (FF)V
+ */
+JNIEXPORT void JNICALL Java_com_artifex_mupdf_fitz_Path_moveTo
+ (JNIEnv *, jobject, jfloat, jfloat);
+
+/*
+ * Class: com_artifex_mupdf_fitz_Path
+ * Method: lineTo
+ * Signature: (FF)V
+ */
+JNIEXPORT void JNICALL Java_com_artifex_mupdf_fitz_Path_lineTo
+ (JNIEnv *, jobject, jfloat, jfloat);
+
+/*
+ * Class: com_artifex_mupdf_fitz_Path
+ * Method: curveTo
+ * Signature: (FFFFFF)V
+ */
+JNIEXPORT void JNICALL Java_com_artifex_mupdf_fitz_Path_curveTo
+ (JNIEnv *, jobject, jfloat, jfloat, jfloat, jfloat, jfloat, jfloat);
+
+/*
+ * Class: com_artifex_mupdf_fitz_Path
+ * Method: curveToV
+ * Signature: (FFFF)V
+ */
+JNIEXPORT void JNICALL Java_com_artifex_mupdf_fitz_Path_curveToV
+ (JNIEnv *, jobject, jfloat, jfloat, jfloat, jfloat);
+
+/*
+ * Class: com_artifex_mupdf_fitz_Path
+ * Method: curveToY
+ * Signature: (FFFF)V
+ */
+JNIEXPORT void JNICALL Java_com_artifex_mupdf_fitz_Path_curveToY
+ (JNIEnv *, jobject, jfloat, jfloat, jfloat, jfloat);
+
+/*
+ * Class: com_artifex_mupdf_fitz_Path
+ * Method: rect
+ * Signature: (IIII)V
+ */
+JNIEXPORT void JNICALL Java_com_artifex_mupdf_fitz_Path_rect
+ (JNIEnv *, jobject, jint, jint, jint, jint);
+
+/*
+ * Class: com_artifex_mupdf_fitz_Path
+ * Method: closePath
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_artifex_mupdf_fitz_Path_closePath
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_artifex_mupdf_fitz_Path
+ * Method: transform
+ * Signature: (Lcom/artifex/mupdf/fitz/Matrix;)V
+ */
+JNIEXPORT void JNICALL Java_com_artifex_mupdf_fitz_Path_transform
+ (JNIEnv *, jobject, jobject);
+
+/*
+ * Class: com_artifex_mupdf_fitz_Path
+ * Method: getBounds
+ * Signature: (Lcom/artifex/mupdf/fitz/StrokeState;Lcom/artifex/mupdf/fitz/Matrix;)Lcom/artifex/mupdf/fitz/Rect;
+ */
+JNIEXPORT jobject JNICALL Java_com_artifex_mupdf_fitz_Path_getBounds
+ (JNIEnv *, jobject, jobject, jobject);
+
+/*
+ * Class: com_artifex_mupdf_fitz_Path
+ * Method: walk
+ * Signature: (Lcom/artifex/mupdf/fitz/PathWalker;)V
+ */
+JNIEXPORT void JNICALL Java_com_artifex_mupdf_fitz_Path_walk
+ (JNIEnv *, jobject, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class com_artifex_mupdf_fitz_PathWalker */
+
+#ifndef _Included_com_artifex_mupdf_fitz_PathWalker
+#define _Included_com_artifex_mupdf_fitz_PathWalker
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif
/* Header for class com_artifex_mupdf_fitz_PDFAnnotation */
#ifndef _Included_com_artifex_mupdf_fitz_PDFAnnotation
@@ -1722,7 +2007,7 @@ JNIEXPORT void JNICALL Java_com_artifex_mupdf_fitz_PDFDocument_deleteObject
/*
* Class: com_artifex_mupdf_fitz_PDFDocument
* Method: newPDFGraftMap
- * Signature: (Lcom/artifex/mupdf/fitz/PDFDocument)Lcom/artifex/mupdf/fitz/PDFGraftMap;
+ * Signature: ()Lcom/artifex/mupdf/fitz/PDFGraftMap;
*/
JNIEXPORT jobject JNICALL Java_com_artifex_mupdf_fitz_PDFDocument_newPDFGraftMap
(JNIEnv *, jobject);
@@ -1730,7 +2015,7 @@ JNIEXPORT jobject JNICALL Java_com_artifex_mupdf_fitz_PDFDocument_newPDFGraftMap
/*
* Class: com_artifex_mupdf_fitz_PDFDocument
* Method: graftObject
- * Signature: (Lcom/artifex/mupdf/fitz/PDFDocument;Lcom/artifex/mupdf/fitz/PDFObject)Lcom/artifex/mupdf/fitz/PDFObject;
+ * Signature: (Lcom/artifex/mupdf/fitz/PDFObject;)Lcom/artifex/mupdf/fitz/PDFObject;
*/
JNIEXPORT jobject JNICALL Java_com_artifex_mupdf_fitz_PDFDocument_graftObject
(JNIEnv *, jobject, jobject);
@@ -1853,10 +2138,10 @@ JNIEXPORT void JNICALL Java_com_artifex_mupdf_fitz_PDFGraftMap_finalize
/*
* Class: com_artifex_mupdf_fitz_PDFGraftMap
* Method: graftObject
- * Signature: (Lcom/artifex/mupdf/fitz/PDFGraftMap;Lcom/artifex/mupdf/fitz/PDFObject;)Lcom/artifex/mupdf/fitz/PDFObject;
+ * Signature: (Lcom/artifex/mupdf/fitz/PDFObject;)Lcom/artifex/mupdf/fitz/PDFObject;
*/
JNIEXPORT jobject JNICALL Java_com_artifex_mupdf_fitz_PDFGraftMap_graftObject
- (JNIEnv *, jobject, jobject, jobject);
+ (JNIEnv *, jobject, jobject);
#ifdef __cplusplus
}
@@ -2348,263 +2633,6 @@ JNIEXPORT void JNICALL Java_com_artifex_mupdf_fitz_PDFPage_deleteAnnotation
}
#endif
#endif
-/* Header for class com_artifex_mupdf_fitz_Page */
-
-#ifndef _Included_com_artifex_mupdf_fitz_Page
-#define _Included_com_artifex_mupdf_fitz_Page
-#ifdef __cplusplus
-extern "C" {
-#endif
-/*
- * Class: com_artifex_mupdf_fitz_Page
- * Method: finalize
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_com_artifex_mupdf_fitz_Page_finalize
- (JNIEnv *, jobject);
-
-/*
- * Class: com_artifex_mupdf_fitz_Page
- * Method: getBounds
- * Signature: ()Lcom/artifex/mupdf/fitz/Rect;
- */
-JNIEXPORT jobject JNICALL Java_com_artifex_mupdf_fitz_Page_getBounds
- (JNIEnv *, jobject);
-
-/*
- * Class: com_artifex_mupdf_fitz_Page
- * Method: toPixmap
- * Signature: (Lcom/artifex/mupdf/fitz/Matrix;Lcom/artifex/mupdf/fitz/ColorSpace;Z)Lcom/artifex/mupdf/fitz/Pixmap;
- */
-JNIEXPORT jobject JNICALL Java_com_artifex_mupdf_fitz_Page_toPixmap
- (JNIEnv *, jobject, jobject, jobject, jboolean);
-
-/*
- * Class: com_artifex_mupdf_fitz_Page
- * Method: run
- * Signature: (Lcom/artifex/mupdf/fitz/Device;Lcom/artifex/mupdf/fitz/Matrix;Lcom/artifex/mupdf/fitz/Cookie;)V
- */
-JNIEXPORT void JNICALL Java_com_artifex_mupdf_fitz_Page_run
- (JNIEnv *, jobject, jobject, jobject, jobject);
-
-/*
- * Class: com_artifex_mupdf_fitz_Page
- * Method: runPageContents
- * Signature: (Lcom/artifex/mupdf/fitz/Device;Lcom/artifex/mupdf/fitz/Matrix;Lcom/artifex/mupdf/fitz/Cookie;)V
- */
-JNIEXPORT void JNICALL Java_com_artifex_mupdf_fitz_Page_runPageContents
- (JNIEnv *, jobject, jobject, jobject, jobject);
-
-/*
- * Class: com_artifex_mupdf_fitz_Page
- * Method: getAnnotations
- * Signature: ()[Lcom/artifex/mupdf/fitz/Annotation;
- */
-JNIEXPORT jobjectArray JNICALL Java_com_artifex_mupdf_fitz_Page_getAnnotations
- (JNIEnv *, jobject);
-
-/*
- * Class: com_artifex_mupdf_fitz_Page
- * Method: getLinks
- * Signature: ()[Lcom/artifex/mupdf/fitz/Link;
- */
-JNIEXPORT jobjectArray JNICALL Java_com_artifex_mupdf_fitz_Page_getLinks
- (JNIEnv *, jobject);
-
-/*
- * Class: com_artifex_mupdf_fitz_Page
- * Method: toDisplayList
- * Signature: (Z)Lcom/artifex/mupdf/fitz/DisplayList;
- */
-JNIEXPORT jobject JNICALL Java_com_artifex_mupdf_fitz_Page_toDisplayList
- (JNIEnv *, jobject, jboolean);
-
-/*
- * Class: com_artifex_mupdf_fitz_Page
- * Method: toStructuredText
- * Signature: (Ljava/lang/String;)Lcom/artifex/mupdf/fitz/StructuredText;
- */
-JNIEXPORT jobject JNICALL Java_com_artifex_mupdf_fitz_Page_toStructuredText
- (JNIEnv *, jobject, jstring);
-
-/*
- * Class: com_artifex_mupdf_fitz_Page
- * Method: search
- * Signature: (Ljava/lang/String;)[Lcom/artifex/mupdf/fitz/Rect;
- */
-JNIEXPORT jobjectArray JNICALL Java_com_artifex_mupdf_fitz_Page_search
- (JNIEnv *, jobject, jstring);
-
-/*
- * Class: com_artifex_mupdf_fitz_Page
- * Method: textAsHtml
- * Signature: ()[B
- */
-JNIEXPORT jbyteArray JNICALL Java_com_artifex_mupdf_fitz_Page_textAsHtml
- (JNIEnv *, jobject);
-
-/*
- * Class: com_artifex_mupdf_fitz_Page
- * Method: countSeparations
- * Signature: ()I
- */
-JNIEXPORT jint JNICALL Java_com_artifex_mupdf_fitz_Page_countSeparations
- (JNIEnv *, jobject);
-
-/*
- * Class: com_artifex_mupdf_fitz_Page
- * Method: getSeparation
- * Signature: (I)Lcom/artifex/mupdf/fitz/Separation;
- */
-JNIEXPORT jobject JNICALL Java_com_artifex_mupdf_fitz_Page_getSeparation
- (JNIEnv *, jobject, jint);
-
-/*
- * Class: com_artifex_mupdf_fitz_Page
- * Method: enableSeparation
- * Signature: (IZ)V
- */
-JNIEXPORT void JNICALL Java_com_artifex_mupdf_fitz_Page_enableSeparation
- (JNIEnv *, jobject, jint, jboolean);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
-/* Header for class com_artifex_mupdf_fitz_Path */
-
-#ifndef _Included_com_artifex_mupdf_fitz_Path
-#define _Included_com_artifex_mupdf_fitz_Path
-#ifdef __cplusplus
-extern "C" {
-#endif
-/*
- * Class: com_artifex_mupdf_fitz_Path
- * Method: finalize
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_com_artifex_mupdf_fitz_Path_finalize
- (JNIEnv *, jobject);
-
-/*
- * Class: com_artifex_mupdf_fitz_Path
- * Method: newNative
- * Signature: ()J
- */
-JNIEXPORT jlong JNICALL Java_com_artifex_mupdf_fitz_Path_newNative
- (JNIEnv *, jobject);
-
-/*
- * Class: com_artifex_mupdf_fitz_Path
- * Method: cloneNative
- * Signature: ()J
- */
-JNIEXPORT jlong JNICALL Java_com_artifex_mupdf_fitz_Path_cloneNative
- (JNIEnv *, jobject);
-
-/*
- * Class: com_artifex_mupdf_fitz_Path
- * Method: currentPoint
- * Signature: ()Lcom/artifex/mupdf/fitz/Point;
- */
-JNIEXPORT jobject JNICALL Java_com_artifex_mupdf_fitz_Path_currentPoint
- (JNIEnv *, jobject);
-
-/*
- * Class: com_artifex_mupdf_fitz_Path
- * Method: moveTo
- * Signature: (FF)V
- */
-JNIEXPORT void JNICALL Java_com_artifex_mupdf_fitz_Path_moveTo
- (JNIEnv *, jobject, jfloat, jfloat);
-
-/*
- * Class: com_artifex_mupdf_fitz_Path
- * Method: lineTo
- * Signature: (FF)V
- */
-JNIEXPORT void JNICALL Java_com_artifex_mupdf_fitz_Path_lineTo
- (JNIEnv *, jobject, jfloat, jfloat);
-
-/*
- * Class: com_artifex_mupdf_fitz_Path
- * Method: curveTo
- * Signature: (FFFFFF)V
- */
-JNIEXPORT void JNICALL Java_com_artifex_mupdf_fitz_Path_curveTo
- (JNIEnv *, jobject, jfloat, jfloat, jfloat, jfloat, jfloat, jfloat);
-
-/*
- * Class: com_artifex_mupdf_fitz_Path
- * Method: curveToV
- * Signature: (FFFF)V
- */
-JNIEXPORT void JNICALL Java_com_artifex_mupdf_fitz_Path_curveToV
- (JNIEnv *, jobject, jfloat, jfloat, jfloat, jfloat);
-
-/*
- * Class: com_artifex_mupdf_fitz_Path
- * Method: curveToY
- * Signature: (FFFF)V
- */
-JNIEXPORT void JNICALL Java_com_artifex_mupdf_fitz_Path_curveToY
- (JNIEnv *, jobject, jfloat, jfloat, jfloat, jfloat);
-
-/*
- * Class: com_artifex_mupdf_fitz_Path
- * Method: rect
- * Signature: (IIII)V
- */
-JNIEXPORT void JNICALL Java_com_artifex_mupdf_fitz_Path_rect
- (JNIEnv *, jobject, jint, jint, jint, jint);
-
-/*
- * Class: com_artifex_mupdf_fitz_Path
- * Method: closePath
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_com_artifex_mupdf_fitz_Path_closePath
- (JNIEnv *, jobject);
-
-/*
- * Class: com_artifex_mupdf_fitz_Path
- * Method: transform
- * Signature: (Lcom/artifex/mupdf/fitz/Matrix;)V
- */
-JNIEXPORT void JNICALL Java_com_artifex_mupdf_fitz_Path_transform
- (JNIEnv *, jobject, jobject);
-
-/*
- * Class: com_artifex_mupdf_fitz_Path
- * Method: getBounds
- * Signature: (Lcom/artifex/mupdf/fitz/StrokeState;Lcom/artifex/mupdf/fitz/Matrix;)Lcom/artifex/mupdf/fitz/Rect;
- */
-JNIEXPORT jobject JNICALL Java_com_artifex_mupdf_fitz_Path_getBounds
- (JNIEnv *, jobject, jobject, jobject);
-
-/*
- * Class: com_artifex_mupdf_fitz_Path
- * Method: walk
- * Signature: (Lcom/artifex/mupdf/fitz/PathWalker;)V
- */
-JNIEXPORT void JNICALL Java_com_artifex_mupdf_fitz_Path_walk
- (JNIEnv *, jobject, jobject);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
-/* Header for class com_artifex_mupdf_fitz_PathWalker */
-
-#ifndef _Included_com_artifex_mupdf_fitz_PathWalker
-#define _Included_com_artifex_mupdf_fitz_PathWalker
-#ifdef __cplusplus
-extern "C" {
-#endif
-#ifdef __cplusplus
-}
-#endif
-#endif
/* Header for class com_artifex_mupdf_fitz_Pixmap */
#ifndef _Included_com_artifex_mupdf_fitz_Pixmap
@@ -2938,6 +2966,50 @@ JNIEXPORT jfloatArray JNICALL Java_com_artifex_mupdf_fitz_StrokeState_getDashes
}
#endif
#endif
+/* Header for class com_artifex_mupdf_fitz_StructuredText_TextBlock */
+
+#ifndef _Included_com_artifex_mupdf_fitz_StructuredText_TextBlock
+#define _Included_com_artifex_mupdf_fitz_StructuredText_TextBlock
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class com_artifex_mupdf_fitz_StructuredText_TextChar */
+
+#ifndef _Included_com_artifex_mupdf_fitz_StructuredText_TextChar
+#define _Included_com_artifex_mupdf_fitz_StructuredText_TextChar
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class com_artifex_mupdf_fitz_StructuredText_TextLine */
+
+#ifndef _Included_com_artifex_mupdf_fitz_StructuredText_TextLine
+#define _Included_com_artifex_mupdf_fitz_StructuredText_TextLine
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class com_artifex_mupdf_fitz_StructuredText_TextSpan */
+
+#ifndef _Included_com_artifex_mupdf_fitz_StructuredText_TextSpan
+#define _Included_com_artifex_mupdf_fitz_StructuredText_TextSpan
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif
/* Header for class com_artifex_mupdf_fitz_StructuredText */
#ifndef _Included_com_artifex_mupdf_fitz_StructuredText
@@ -2989,50 +3061,6 @@ JNIEXPORT jobjectArray JNICALL Java_com_artifex_mupdf_fitz_StructuredText_getBlo
}
#endif
#endif
-/* Header for class com_artifex_mupdf_fitz_StructuredText_TextChar */
-
-#ifndef _Included_com_artifex_mupdf_fitz_StructuredText_TextChar
-#define _Included_com_artifex_mupdf_fitz_StructuredText_TextChar
-#ifdef __cplusplus
-extern "C" {
-#endif
-#ifdef __cplusplus
-}
-#endif
-#endif
-/* Header for class com_artifex_mupdf_fitz_StructuredText_TextSpan */
-
-#ifndef _Included_com_artifex_mupdf_fitz_StructuredText_TextSpan
-#define _Included_com_artifex_mupdf_fitz_StructuredText_TextSpan
-#ifdef __cplusplus
-extern "C" {
-#endif
-#ifdef __cplusplus
-}
-#endif
-#endif
-/* Header for class com_artifex_mupdf_fitz_StructuredText_TextLine */
-
-#ifndef _Included_com_artifex_mupdf_fitz_StructuredText_TextLine
-#define _Included_com_artifex_mupdf_fitz_StructuredText_TextLine
-#ifdef __cplusplus
-extern "C" {
-#endif
-#ifdef __cplusplus
-}
-#endif
-#endif
-/* Header for class com_artifex_mupdf_fitz_StructuredText_TextBlock */
-
-#ifndef _Included_com_artifex_mupdf_fitz_StructuredText_TextBlock
-#define _Included_com_artifex_mupdf_fitz_StructuredText_TextBlock
-#ifdef __cplusplus
-extern "C" {
-#endif
-#ifdef __cplusplus
-}
-#endif
-#endif
/* Header for class com_artifex_mupdf_fitz_Text */
#ifndef _Included_com_artifex_mupdf_fitz_Text
@@ -3119,11 +3147,11 @@ extern "C" {
extern "C" {
#endif
#undef com_artifex_mupdf_fitz_TryLaterException_serialVersionUID
-#define com_artifex_mupdf_fitz_TryLaterException_serialVersionUID -3042686055658047285LL
+#define com_artifex_mupdf_fitz_TryLaterException_serialVersionUID -3042686055658047285i64
#undef com_artifex_mupdf_fitz_TryLaterException_serialVersionUID
-#define com_artifex_mupdf_fitz_TryLaterException_serialVersionUID -3387516993124229948LL
+#define com_artifex_mupdf_fitz_TryLaterException_serialVersionUID -3387516993124229948i64
#undef com_artifex_mupdf_fitz_TryLaterException_serialVersionUID
-#define com_artifex_mupdf_fitz_TryLaterException_serialVersionUID -7034897190745766939LL
+#define com_artifex_mupdf_fitz_TryLaterException_serialVersionUID -7034897190745766939i64
#ifdef __cplusplus
}
#endif
diff --git a/platform/java/src/com/artifex/mupdf/fitz/ColorParams.java b/platform/java/src/com/artifex/mupdf/fitz/ColorParams.java
new file mode 100644
index 00000000..2a8d781b
--- /dev/null
+++ b/platform/java/src/com/artifex/mupdf/fitz/ColorParams.java
@@ -0,0 +1,51 @@
+package com.artifex.mupdf.fitz;
+
+public final class ColorParams
+{
+ public enum RenderingIntent {
+ PERCEPTUAL,
+ RELATIVE_COLORIMETRIC,
+ SATURATION,
+ ABSOLUTE_COLORIMETRIC
+ }
+ public static final int BP = 32;
+ public static final int OP = 64;
+ public static final int OPM = 128;
+
+ public static RenderingIntent RI(int flags) {
+ switch (flags>>3) {
+ default:
+ case 0: return RenderingIntent.PERCEPTUAL;
+ case 1: return RenderingIntent.RELATIVE_COLORIMETRIC;
+ case 2: return RenderingIntent.SATURATION;
+ case 3: return RenderingIntent.ABSOLUTE_COLORIMETRIC;
+ }
+ }
+
+ public static boolean BP(int flags) {
+ return (flags & BP) != 0;
+ }
+
+ public static boolean OP(int flags) {
+ return (flags & OP) != 0;
+ }
+
+ public static boolean OPM(int flags) {
+ return (flags & OPM) != 0;
+ }
+
+ public static int pack(RenderingIntent ri, boolean bp, boolean op, boolean opm) {
+ int flags;
+ switch (ri) {
+ default:
+ case PERCEPTUAL: flags = 0; break;
+ case RELATIVE_COLORIMETRIC: flags = 1; break;
+ case SATURATION: flags = 2; break;
+ case ABSOLUTE_COLORIMETRIC: flags = 3; break;
+ }
+ if (bp) flags |= BP;
+ if (op) flags |= OP;
+ if (opm) flags |= OPM;
+ return flags;
+ }
+}
diff --git a/platform/java/src/com/artifex/mupdf/fitz/NativeDevice.java b/platform/java/src/com/artifex/mupdf/fitz/NativeDevice.java
index 0d2b9159..910b8ec8 100644
--- a/platform/java/src/com/artifex/mupdf/fitz/NativeDevice.java
+++ b/platform/java/src/com/artifex/mupdf/fitz/NativeDevice.java
@@ -19,25 +19,26 @@ public class NativeDevice extends Device
public native final void close();
- public native final void fillPath(Path path, boolean evenOdd, Matrix ctm, ColorSpace cs, float color[], float alpha);
- public native final void strokePath(Path path, StrokeState stroke, Matrix ctm, ColorSpace cs, float color[], float alpha);
+ public native final void fillPath(Path path, boolean evenOdd, Matrix ctm, ColorSpace cs, float color[], float alpha, int cp);
+ public native final void strokePath(Path path, StrokeState stroke, Matrix ctm, ColorSpace cs, float color[], float alpha, int cp);
public native final void clipPath(Path path, boolean evenOdd, Matrix ctm);
public native final void clipStrokePath(Path path, StrokeState stroke, Matrix ctm);
- public native final void fillText(Text text, Matrix ctm, ColorSpace cs, float color[], float alpha);
- public native final void strokeText(Text text, StrokeState stroke, Matrix ctm, ColorSpace cs, float color[], float alpha);
+ public native final void fillText(Text text, Matrix ctm, ColorSpace cs, float color[], float alpha, int cp);
+ public native final void strokeText(Text text, StrokeState stroke, Matrix ctm, ColorSpace cs, float color[], float alpha, int cp);
public native final void clipText(Text text, Matrix ctm);
public native final void clipStrokeText(Text text, StrokeState stroke, Matrix ctm);
public native final void ignoreText(Text text, Matrix ctm);
- public native final void fillShade(Shade shd, Matrix ctm, float alpha);
- public native final void fillImage(Image img, Matrix ctm, float alpha);
- public native final void fillImageMask(Image img, Matrix ctm, ColorSpace cs, float color[], float alpha);
+ public native final void fillShade(Shade shd, Matrix ctm, float alpha, int cp);
+ public native final void fillImage(Image img, Matrix ctm, float alpha, int cp);
+ public native final void fillImageMask(Image img, Matrix ctm, ColorSpace cs, float color[], float alpha, int cp);
+ /* FIXME: Why no scissor? */
public native final void clipImageMask(Image img, Matrix ctm);
public native final void popClip();
- public native final void beginMask(Rect rect, boolean luminosity, ColorSpace cs, float bc[]);
+ public native final void beginMask(Rect rect, boolean luminosity, ColorSpace cs, float bc[], int cp);
public native final void endMask();
public native final void beginGroup(Rect rect, boolean isolated, boolean knockout, int blendmode, float alpha);
public native final void endGroup();
diff --git a/platform/win32/generate.bat b/platform/win32/generate.bat
index 502cc35a..ebc619f4 100644
--- a/platform/win32/generate.bat
+++ b/platform/win32/generate.bat
@@ -157,6 +157,8 @@ if not exist generated/NotoSerifTamil-Regular.c hexdump.exe generated/NotoSerifT
if not exist generated/NotoSerifTelugu-Regular.c hexdump.exe generated/NotoSerifTelugu-Regular.c resources/fonts/noto/NotoSerifTelugu-Regular.ttf
if not exist generated/NotoSerifThai-Regular.c hexdump.exe generated/NotoSerifThai-Regular.c resources/fonts/noto/NotoSerifThai-Regular.ttf
+if not exist generated/icc-profiles.c hexdump.exe generated/icc-profiles.c resources/icc/gray.icc resources/icc/rgb.icc resources/icc/cmyk.icc resources/icc/lab.icc
+
del namedump.obj cmapdump.obj hexdump.obj
del namedump.exe cmapdump.exe hexdump.exe
diff --git a/platform/win32/javaviewerlib.vcproj b/platform/win32/javaviewerlib.vcproj
index be1aa5ba..74749a25 100644
--- a/platform/win32/javaviewerlib.vcproj
+++ b/platform/win32/javaviewerlib.vcproj
@@ -352,6 +352,10 @@
>
</File>
<File
+ RelativePath="..\java\src\com\artifex\mupdf\fitz\ColorParams.java"
+ >
+ </File>
+ <File
RelativePath="..\java\src\com\artifex\mupdf\fitz\ColorSpace.java"
>
</File>
diff --git a/platform/win32/libmupdf.vcproj b/platform/win32/libmupdf.vcproj
index 80b4fcb8..03784226 100644
--- a/platform/win32/libmupdf.vcproj
+++ b/platform/win32/libmupdf.vcproj
@@ -42,7 +42,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
- AdditionalIncludeDirectories="..\..\scripts\freetype;..\..\scripts\libjpeg;..\..\include;..\..\thirdparty\jbig2dec;..\..\thirdparty\libjpeg;..\..\thirdparty\openjpeg/src/lib/openjp2;..\..\thirdparty\zlib;..\..\thirdparty\freetype\include;..\..\thirdparty\mujs;..\..\thirdparty\harfbuzz\src"
+ AdditionalIncludeDirectories="..\..\scripts\freetype;..\..\scripts\libjpeg;..\..\include;..\..\thirdparty\jbig2dec;..\..\thirdparty\libjpeg;..\..\thirdparty\openjpeg/src/lib/openjp2;..\..\thirdparty\zlib;..\..\thirdparty\freetype\include;..\..\thirdparty\mujs;..\..\thirdparty\harfbuzz\src;..\..\thirdparty\lcms2\include"
PreprocessorDefinitions="WIN32;_DEBUG"
MinimalRebuild="true"
BasicRuntimeChecks="3"
@@ -170,7 +170,7 @@
Optimization="2"
EnableIntrinsicFunctions="true"
WholeProgramOptimization="false"
- AdditionalIncludeDirectories="..\..\scripts\freetype;..\..\scripts\libjpeg;..\..\include;..\..\thirdparty\jbig2dec;..\..\thirdparty\libjpeg;..\..\thirdparty\openjpeg\src\lib\openjp2;..\..\thirdparty\zlib;..\..\thirdparty\freetype\include;..\..\thirdparty\mujs;..\..\thirdparty\harfbuzz\src"
+ AdditionalIncludeDirectories="..\..\scripts\freetype;..\..\scripts\libjpeg;..\..\include;..\..\thirdparty\jbig2dec;..\..\thirdparty\libjpeg;..\..\thirdparty\openjpeg\src\lib\openjp2;..\..\thirdparty\zlib;..\..\thirdparty\freetype\include;..\..\thirdparty\mujs;..\..\thirdparty\harfbuzz\src;..\..\thirdparty\lcms2\include"
PreprocessorDefinitions="WIN32;NDEBUG"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
@@ -296,7 +296,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
- AdditionalIncludeDirectories="..\..\scripts\freetype;..\..\scripts\libjpeg;..\..\include;..\..\thirdparty\jbig2dec;..\..\thirdparty\libjpeg;..\..\thirdparty\openjpeg\src\lib\openjp2;..\..\thirdparty\zlib;..\..\thirdparty\freetype\include;..\..\thirdparty\mujs;..\..\thirdparty\harfbuzz\src"
+ AdditionalIncludeDirectories="..\..\scripts\freetype;..\..\scripts\libjpeg;..\..\include;..\..\thirdparty\jbig2dec;..\..\thirdparty\libjpeg;..\..\thirdparty\openjpeg\src\lib\openjp2;..\..\thirdparty\zlib;..\..\thirdparty\freetype\include;..\..\thirdparty\mujs;..\..\thirdparty\harfbuzz\src;..\..\thirdparty\lcms2\include"
PreprocessorDefinitions="WIN32;_DEBUG;MEMENTO=1"
MinimalRebuild="true"
BasicRuntimeChecks="3"
@@ -421,7 +421,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
- AdditionalIncludeDirectories="..\..\scripts\freetype;..\..\scripts\libjpeg;..\..\include;..\..\thirdparty\jbig2dec;..\..\thirdparty\libjpeg;..\..\thirdparty\openjpeg\src\lib\openjp2;..\..\thirdparty\zlib;..\..\thirdparty\freetype\include;..\..\thirdparty\openssl\include;..\..\thirdparty\mujs;..\..\thirdparty\harfbuzz\src"
+ AdditionalIncludeDirectories="..\..\scripts\freetype;..\..\scripts\libjpeg;..\..\include;..\..\thirdparty\jbig2dec;..\..\thirdparty\libjpeg;..\..\thirdparty\openjpeg\src\lib\openjp2;..\..\thirdparty\zlib;..\..\thirdparty\freetype\include;..\..\thirdparty\openssl\include;..\..\thirdparty\mujs;..\..\thirdparty\harfbuzz\src;..\..\thirdparty\lcms2\include"
PreprocessorDefinitions="WIN32;_DEBUG;HAVE_LIBCRYPTO"
MinimalRebuild="true"
BasicRuntimeChecks="3"
@@ -549,7 +549,7 @@
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
- AdditionalIncludeDirectories="..\..\scripts\freetype;..\..\scripts\libjpeg;..\..\include;..\..\thirdparty\jbig2dec;..\..\thirdparty\libjpeg;..\..\thirdparty\openjpeg\src\lib\openjp2;..\..\thirdparty\zlib;..\..\thirdparty\freetype\include;..\..\thirdparty\mujs;..\..\thirdparty\harfbuzz\src;..\..\thirdparty\openssl\include"
+ AdditionalIncludeDirectories="..\..\scripts\freetype;..\..\scripts\libjpeg;..\..\include;..\..\thirdparty\jbig2dec;..\..\thirdparty\libjpeg;..\..\thirdparty\openjpeg\src\lib\openjp2;..\..\thirdparty\zlib;..\..\thirdparty\freetype\include;..\..\thirdparty\mujs;..\..\thirdparty\harfbuzz\src;..\..\thirdparty\openssl\include;..\..\thirdparty\lcms2\include"
PreprocessorDefinitions="WIN32;NDEBUG;HAVE_LIBCRYPTO"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
@@ -675,7 +675,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
- AdditionalIncludeDirectories="..\..\scripts\freetype;..\..\scripts\libjpeg;..\..\include;..\..\thirdparty\jbig2dec;..\..\thirdparty\libjpeg;..\..\thirdparty\openjpeg/src/lib/openjp2;..\..\thirdparty\zlib;..\..\thirdparty\freetype\include;..\..\thirdparty\mujs;..\..\thirdparty\harfbuzz\src"
+ AdditionalIncludeDirectories="..\..\scripts\freetype;..\..\scripts\libjpeg;..\..\include;..\..\thirdparty\jbig2dec;..\..\thirdparty\libjpeg;..\..\thirdparty\openjpeg/src/lib/openjp2;..\..\thirdparty\zlib;..\..\thirdparty\freetype\include;..\..\thirdparty\mujs;..\..\thirdparty\harfbuzz\src;..\..\thirdparty\lcms2\include"
PreprocessorDefinitions="WIN32;_DEBUG;FZ_ENABLE_GPRF=1"
MinimalRebuild="true"
BasicRuntimeChecks="3"
@@ -800,7 +800,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
- AdditionalIncludeDirectories="..\..\scripts\freetype;..\..\scripts\libjpeg;..\..\include;..\..\thirdparty\jbig2dec;..\..\thirdparty\libjpeg;..\..\thirdparty\openjpeg/src/lib/openjp2;..\..\thirdparty\zlib;..\..\thirdparty\freetype\include;..\..\thirdparty\mujs;..\..\thirdparty\harfbuzz\src"
+ AdditionalIncludeDirectories="..\..\scripts\freetype;..\..\scripts\libjpeg;..\..\include;..\..\thirdparty\jbig2dec;..\..\thirdparty\libjpeg;..\..\thirdparty\openjpeg/src/lib/openjp2;..\..\thirdparty\zlib;..\..\thirdparty\freetype\include;..\..\thirdparty\mujs;..\..\thirdparty\harfbuzz\src;..\..\thirdparty\lcms2\include"
PreprocessorDefinitions="WIN32;_DEBUG"
MinimalRebuild="true"
BasicRuntimeChecks="3"
@@ -929,7 +929,7 @@
Optimization="2"
EnableIntrinsicFunctions="true"
WholeProgramOptimization="false"
- AdditionalIncludeDirectories="..\..\scripts\freetype;..\..\scripts\libjpeg;..\..\include;..\..\thirdparty\jbig2dec;..\..\thirdparty\libjpeg;..\..\thirdparty\openjpeg\src\lib\openjp2;..\..\thirdparty\zlib;..\..\thirdparty\freetype\include;..\..\thirdparty\mujs;..\..\thirdparty\harfbuzz\src"
+ AdditionalIncludeDirectories="..\..\scripts\freetype;..\..\scripts\libjpeg;..\..\include;..\..\thirdparty\jbig2dec;..\..\thirdparty\libjpeg;..\..\thirdparty\openjpeg\src\lib\openjp2;..\..\thirdparty\zlib;..\..\thirdparty\freetype\include;..\..\thirdparty\mujs;..\..\thirdparty\harfbuzz\src;..\..\thirdparty\lcms2\include"
PreprocessorDefinitions="WIN32;NDEBUG"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
@@ -1055,7 +1055,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
- AdditionalIncludeDirectories="..\..\scripts\freetype;..\..\scripts\libjpeg;..\..\include;..\..\thirdparty\jbig2dec;..\..\thirdparty\libjpeg;..\..\thirdparty\openjpeg\src\lib\openjp2;..\..\thirdparty\zlib;..\..\thirdparty\freetype\include;..\..\thirdparty\mujs;..\..\thirdparty\harfbuzz\src;..\..\thirdparty\luratech\ldf_jb2\source\common;..\..\thirdparty\luratech\ldf_jb2\source\libraries;..\..\thirdparty\luratech\ldf_jb2\source\compress;..\..\thirdparty\luratech\lwf_jp2\library\source"
+ AdditionalIncludeDirectories="..\..\scripts\freetype;..\..\scripts\libjpeg;..\..\include;..\..\thirdparty\jbig2dec;..\..\thirdparty\libjpeg;..\..\thirdparty\openjpeg\src\lib\openjp2;..\..\thirdparty\zlib;..\..\thirdparty\freetype\include;..\..\thirdparty\mujs;..\..\thirdparty\harfbuzz\src;..\..\thirdparty\luratech\ldf_jb2\source\common;..\..\thirdparty\luratech\ldf_jb2\source\libraries;..\..\thirdparty\luratech\ldf_jb2\source\compress;..\..\thirdparty\luratech\lwf_jp2\library\source;..\..\thirdparty\lcms2\include"
PreprocessorDefinitions="WIN32;_DEBUG;MEMENTO=1;HAVE_LURATECH"
MinimalRebuild="true"
BasicRuntimeChecks="3"
@@ -1180,7 +1180,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
- AdditionalIncludeDirectories="..\..\scripts\freetype;..\..\scripts\libjpeg;..\..\include;..\..\thirdparty\jbig2dec;..\..\thirdparty\libjpeg;..\..\thirdparty\openjpeg/src/lib/openjp2;..\..\thirdparty\zlib;..\..\thirdparty\freetype\include;..\..\thirdparty\mujs;..\..\thirdparty\harfbuzz\src;..\..\thirdparty\luratech\ldf_jb2\source\common;..\..\thirdparty\luratech\ldf_jb2\source\libraries;..\..\thirdparty\luratech\ldf_jb2\source\compress;..\..\thirdparty\luratech\lwf_jp2\library\source"
+ AdditionalIncludeDirectories="..\..\scripts\freetype;..\..\scripts\libjpeg;..\..\include;..\..\thirdparty\jbig2dec;..\..\thirdparty\libjpeg;..\..\thirdparty\openjpeg/src/lib/openjp2;..\..\thirdparty\zlib;..\..\thirdparty\freetype\include;..\..\thirdparty\mujs;..\..\thirdparty\harfbuzz\src;..\..\thirdparty\luratech\ldf_jb2\source\common;..\..\thirdparty\luratech\ldf_jb2\source\libraries;..\..\thirdparty\luratech\ldf_jb2\source\compress;..\..\thirdparty\luratech\lwf_jp2\library\source;..\..\thirdparty\lcms2\include"
PreprocessorDefinitions="WIN32;_DEBUG;HAVE_LURATECH"
MinimalRebuild="true"
BasicRuntimeChecks="3"
@@ -1309,7 +1309,7 @@
Optimization="2"
EnableIntrinsicFunctions="true"
WholeProgramOptimization="false"
- AdditionalIncludeDirectories="..\..\scripts\freetype;..\..\scripts\libjpeg;..\..\include;..\..\thirdparty\jbig2dec;..\..\thirdparty\libjpeg;..\..\thirdparty\openjpeg\src\lib\openjp2;..\..\thirdparty\zlib;..\..\thirdparty\freetype\include;..\..\thirdparty\mujs;..\..\thirdparty\harfbuzz\src;..\..\thirdparty\luratech\ldf_jb2\source\common;..\..\thirdparty\luratech\ldf_jb2\source\libraries;..\..\thirdparty\luratech\ldf_jb2\source\compress;..\..\thirdparty\luratech\lwf_jp2\library\source;..\..\thirdparty\luratech\lwf_jp2\library\source"
+ AdditionalIncludeDirectories="..\..\scripts\freetype;..\..\scripts\libjpeg;..\..\include;..\..\thirdparty\jbig2dec;..\..\thirdparty\libjpeg;..\..\thirdparty\openjpeg\src\lib\openjp2;..\..\thirdparty\zlib;..\..\thirdparty\freetype\include;..\..\thirdparty\mujs;..\..\thirdparty\harfbuzz\src;..\..\thirdparty\luratech\ldf_jb2\source\common;..\..\thirdparty\luratech\ldf_jb2\source\libraries;..\..\thirdparty\luratech\ldf_jb2\source\compress;..\..\thirdparty\luratech\lwf_jp2\library\source;..\..\thirdparty\luratech\lwf_jp2\library\source;..\..\thirdparty\lcms2\include"
PreprocessorDefinitions="WIN32;NDEBUG;HAVE_LURATECH"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
@@ -1529,6 +1529,14 @@
>
</File>
<File
+ RelativePath="..\..\source\fitz\color-icc-create.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\fitz\color-lcms.c"
+ >
+ </File>
+ <File
RelativePath="..\..\source\fitz\colorspace-imp.h"
>
</File>
@@ -2296,6 +2304,10 @@
>
</File>
<File
+ RelativePath="..\..\include\mupdf\fitz\color-management.h"
+ >
+ </File>
+ <File
RelativePath="..\..\include\mupdf\fitz\colorspace.h"
>
</File>
diff --git a/platform/win32/libfonts.vcproj b/platform/win32/libresources.vcproj
index dfbf5b3d..a7d825ee 100644
--- a/platform/win32/libfonts.vcproj
+++ b/platform/win32/libresources.vcproj
@@ -2,9 +2,9 @@
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
- Name="libfonts"
+ Name="libresources"
ProjectGUID="{52DCAB29-C8EE-4422-954C-29AFA6B33E22}"
- RootNamespace="libfonts"
+ RootNamespace="libresources"
>
<Platforms>
<Platform
@@ -656,6 +656,10 @@
RelativePath="..\..\generated\StandardSymbolsPS.c"
>
</File>
+ <File
+ RelativePath="..\..\generated\icc-profiles.c"
+ >
+ </File>
</Files>
<Globals>
</Globals>
diff --git a/platform/win32/libthirdparty.vcproj b/platform/win32/libthirdparty.vcproj
index ef85358a..7192841d 100644
--- a/platform/win32/libthirdparty.vcproj
+++ b/platform/win32/libthirdparty.vcproj
@@ -42,7 +42,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
- AdditionalIncludeDirectories="..\..\scripts\freetype;..\..\scripts\libjpeg;..\..\thirdparty\jbig2dec;..\..\thirdparty\libjpeg;..\..\thirdparty\openjpeg\src\lib\openjp2;..\..\thirdparty\zlib;..\..\thirdparty\freetype\include;..\..\thirdparty\freetype\include\freetype;..\..\include\"
+ AdditionalIncludeDirectories="..\..\thirdparty\lcms2\include;..\..\scripts\freetype;..\..\scripts\libjpeg;..\..\thirdparty\jbig2dec;..\..\thirdparty\libjpeg;..\..\thirdparty\openjpeg\src\lib\openjp2;..\..\thirdparty\zlib;..\..\thirdparty\freetype\include;..\..\thirdparty\freetype\include\freetype;..\..\include\"
PreprocessorDefinitions="WIN32;_DEBUG;_CRT_SECURE_NO_WARNINGS;FT2_BUILD_LIBRARY;OPJ_STATIC;USE_JPIP=1;FT_CONFIG_MODULES_H=\&quot;slimftmodules.h\&quot;;FT_CONFIG_OPTIONS_H=\&quot;slimftoptions.h\&quot;;verbose=-1;JBIG_EXTERNAL_MEMENTO_H=\&quot;memento.h\&quot;;HAVE_OT;HAVE_UCDN;HB_NO_MT;hb_malloc_impl=hb_malloc;hb_calloc_impl=hb_calloc;hb_realloc_impl=hb_realloc;hb_free_impl=hb_free"
MinimalRebuild="true"
BasicRuntimeChecks="3"
@@ -167,7 +167,7 @@
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
- AdditionalIncludeDirectories="..\..\scripts\freetype;..\..\scripts\libjpeg;..\..\thirdparty\jbig2dec;..\..\thirdparty\libjpeg;..\..\thirdparty\openjpeg\src\lib\openjp2;..\..\thirdparty\zlib;..\..\thirdparty\freetype\include;..\..\thirdparty\freetype\include\freetype;..\..\include\"
+ AdditionalIncludeDirectories="..\..\thirdparty\lcms2\include;..\..\scripts\freetype;..\..\scripts\libjpeg;..\..\thirdparty\jbig2dec;..\..\thirdparty\libjpeg;..\..\thirdparty\openjpeg\src\lib\openjp2;..\..\thirdparty\zlib;..\..\thirdparty\freetype\include;..\..\thirdparty\freetype\include\freetype;..\..\include\"
PreprocessorDefinitions="WIN32;NDEBUG;_CRT_SECURE_NO_WARNINGS;FT2_BUILD_LIBRARY;OPJ_STATIC;USE_JPIP=1;FT_CONFIG_MODULES_H=\&quot;slimftmodules.h\&quot;;FT_CONFIG_OPTIONS_H=\&quot;slimftoptions.h\&quot;;verbose=-1;JBIG_EXTERNAL_MEMENTO_H=\&quot;memento.h\&quot;;HAVE_OT;HAVE_UCDN;HB_NO_MT;hb_malloc_impl=hb_malloc;hb_calloc_impl=hb_calloc;hb_realloc_impl=hb_realloc;hb_free_impl=hb_free"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
@@ -290,7 +290,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
- AdditionalIncludeDirectories="..\..\scripts\freetype;..\..\scripts\libjpeg;..\..\thirdparty\jbig2dec;..\..\thirdparty\libjpeg;..\..\thirdparty\openjpeg\src\lib\openjp2;..\..\thirdparty\zlib;..\..\thirdparty\freetype\include;..\..\thirdparty\freetype\include\freetype;..\..\include\"
+ AdditionalIncludeDirectories="..\..\thirdparty\lcms2\include;..\..\scripts\freetype;..\..\scripts\libjpeg;..\..\thirdparty\jbig2dec;..\..\thirdparty\libjpeg;..\..\thirdparty\openjpeg\src\lib\openjp2;..\..\thirdparty\zlib;..\..\thirdparty\freetype\include;..\..\thirdparty\freetype\include\freetype;..\..\include\"
PreprocessorDefinitions="WIN32;_DEBUG;_CRT_SECURE_NO_WARNINGS;FT2_BUILD_LIBRARY;OPJ_STATIC;USE_JPIP=1;FT_CONFIG_MODULES_H=\&quot;slimftmodules.h\&quot;;FT_CONFIG_OPTIONS_H=\&quot;slimftoptions.h\&quot;;MEMENTO=1;verbose=-1;JBIG_EXTERNAL_MEMENTO_H=\&quot;memento.h\&quot;;HAVE_OT;HAVE_UCDN;HB_NO_MT;hb_malloc_impl=hb_malloc;hb_calloc_impl=hb_calloc;hb_realloc_impl=hb_realloc;hb_free_impl=hb_free"
MinimalRebuild="true"
BasicRuntimeChecks="3"
@@ -413,7 +413,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
- AdditionalIncludeDirectories="..\..\scripts\freetype;..\..\scripts\libjpeg;..\..\thirdparty\jbig2dec;..\..\thirdparty\libjpeg;..\..\thirdparty\openjpeg\src\lib\openjp2;..\..\thirdparty\zlib;..\..\thirdparty\freetype\include;..\..\thirdparty\freetype\include\freetype;..\..\include\"
+ AdditionalIncludeDirectories="..\..\thirdparty\lcms2\include;..\..\scripts\freetype;..\..\scripts\libjpeg;..\..\thirdparty\jbig2dec;..\..\thirdparty\libjpeg;..\..\thirdparty\openjpeg\src\lib\openjp2;..\..\thirdparty\zlib;..\..\thirdparty\freetype\include;..\..\thirdparty\freetype\include\freetype;..\..\include\"
PreprocessorDefinitions="WIN32;_DEBUG;_CRT_SECURE_NO_WARNINGS;FT2_BUILD_LIBRARY;OPJ_STATIC;USE_JPIP=1;FT_CONFIG_MODULES_H=\&quot;slimftmodules.h\&quot;;FT_CONFIG_OPTIONS_H=\&quot;slimftoptions.h\&quot;;verbose=-1;JBIG_EXTERNAL_MEMENTO_H=\&quot;memento.h\&quot;;HAVE_OT;HAVE_UCDN;HB_NO_MT;hb_malloc_impl=hb_malloc;hb_calloc_impl=hb_calloc;hb_realloc_impl=hb_realloc;hb_free_impl=hb_free"
MinimalRebuild="true"
BasicRuntimeChecks="3"
@@ -538,7 +538,7 @@
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
- AdditionalIncludeDirectories="..\..\scripts\freetype;..\..\scripts\libjpeg;..\..\thirdparty\jbig2dec;..\..\thirdparty\libjpeg;..\..\thirdparty\openjpeg\src\lib\openjp2;..\..\thirdparty\zlib;..\..\thirdparty\freetype\include;..\..\thirdparty\freetype\include\freetype;..\..\include\"
+ AdditionalIncludeDirectories="..\..\thirdparty\lcms2\include;..\..\scripts\freetype;..\..\scripts\libjpeg;..\..\thirdparty\jbig2dec;..\..\thirdparty\libjpeg;..\..\thirdparty\openjpeg\src\lib\openjp2;..\..\thirdparty\zlib;..\..\thirdparty\freetype\include;..\..\thirdparty\freetype\include\freetype;..\..\include\"
PreprocessorDefinitions="WIN32;NDEBUG;_CRT_SECURE_NO_WARNINGS;FT2_BUILD_LIBRARY;OPJ_STATIC;USE_JPIP=1;FT_CONFIG_MODULES_H=\&quot;slimftmodules.h\&quot;;FT_CONFIG_OPTIONS_H=\&quot;slimftoptions.h\&quot;;verbose=-1;JBIG_EXTERNAL_MEMENTO_H=\&quot;memento.h\&quot;;HAVE_OT;HAVE_UCDN;HB_NO_MT;hb_malloc_impl=hb_malloc;hb_calloc_impl=hb_calloc;hb_realloc_impl=hb_realloc;hb_free_impl=hb_free"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
@@ -1752,6 +1752,126 @@
</File>
</Filter>
</Filter>
+ <Filter
+ Name="lcms2"
+ >
+ <File
+ RelativePath="..\..\thirdparty\lcms2\src\cmsalpha.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\thirdparty\lcms2\src\cmscam02.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\thirdparty\lcms2\src\cmscgats.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\thirdparty\lcms2\src\cmscnvrt.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\thirdparty\lcms2\src\cmserr.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\thirdparty\lcms2\src\cmsgamma.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\thirdparty\lcms2\src\cmsgmt.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\thirdparty\lcms2\src\cmshalf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\thirdparty\lcms2\src\cmsintrp.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\thirdparty\lcms2\src\cmsio0.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\thirdparty\lcms2\src\cmsio1.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\thirdparty\lcms2\src\cmslut.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\thirdparty\lcms2\src\cmsmd5.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\thirdparty\lcms2\src\cmsmtrx.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\thirdparty\lcms2\src\cmsnamed.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\thirdparty\lcms2\src\cmsopt.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\thirdparty\lcms2\src\cmspack.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\thirdparty\lcms2\src\cmspcs.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\thirdparty\lcms2\src\cmsplugin.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\thirdparty\lcms2\src\cmsps2.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\thirdparty\lcms2\src\cmssamp.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\thirdparty\lcms2\src\cmssm.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\thirdparty\lcms2\src\cmstypes.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\thirdparty\lcms2\src\cmsvirt.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\thirdparty\lcms2\src\cmswtpnt.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\thirdparty\lcms2\src\cmsxform.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\thirdparty\lcms2\include\lcms2.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\thirdparty\lcms2\src\lcms2_internal.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\thirdparty\lcms2\include\lcms2_plugin.h"
+ >
+ </File>
+ </Filter>
</Files>
<Globals>
</Globals>
diff --git a/platform/win32/mupdf.sln b/platform/win32/mupdf.sln
index dc732c76..91bc3705 100644
--- a/platform/win32/mupdf.sln
+++ b/platform/win32/mupdf.sln
@@ -49,7 +49,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mupdf-gl", "mupdf-gl.vcproj
{5F615F91-DFF8-4F05-BF48-6222B7D86519} = {5F615F91-DFF8-4F05-BF48-6222B7D86519}
EndProjectSection
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libfonts", "libfonts.vcproj", "{52DCAB29-C8EE-4422-954C-29AFA6B33E22}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libresources", "libresources.vcproj", "{52DCAB29-C8EE-4422-954C-29AFA6B33E22}"
ProjectSection(ProjectDependencies) = postProject
{A5053AA7-02E5-4903-B596-04F17AEB1526} = {A5053AA7-02E5-4903-B596-04F17AEB1526}
EndProjectSection
diff --git a/resources/icc/cmyk.icc b/resources/icc/cmyk.icc
new file mode 100644
index 00000000..fce61bf2
--- /dev/null
+++ b/resources/icc/cmyk.icc
Binary files differ
diff --git a/resources/icc/gray.icc b/resources/icc/gray.icc
new file mode 100644
index 00000000..daaa7480
--- /dev/null
+++ b/resources/icc/gray.icc
Binary files differ
diff --git a/resources/icc/lab.icc b/resources/icc/lab.icc
new file mode 100644
index 00000000..df5c56c1
--- /dev/null
+++ b/resources/icc/lab.icc
Binary files differ
diff --git a/resources/icc/rgb.icc b/resources/icc/rgb.icc
new file mode 100644
index 00000000..05599723
--- /dev/null
+++ b/resources/icc/rgb.icc
Binary files differ
diff --git a/resources/pdf/names.txt b/resources/pdf/names.txt
index b8dc89b8..01e0ff35 100644
--- a/resources/pdf/names.txt
+++ b/resources/pdf/names.txt
@@ -38,6 +38,7 @@ BitsPerCoordinate
BitsPerFlag
BitsPerSample
BlackIs1
+BlackPoint
BleedBox
Blinds
Border
@@ -103,11 +104,15 @@ DamagedRowsBeforeError
Decode
DecodeParms
Default
+DefaultCMYK
+DefaultGray
+DefaultRGB
Desc
DescendantFonts
Descent
Design
Dest
+DestOutputProfile
Dests
DeviceCMYK
DeviceGray
@@ -174,6 +179,7 @@ Function
FunctionType
Functions
G
+Gamma
Glitter
GoTo
GoToR
@@ -262,6 +268,8 @@ OCProperties
OE
OFF
ON
+OP
+OPM
ObjStm
Of
Off
@@ -272,6 +280,7 @@ Opt
Order
Ordering
Outlines
+OutputIntents
P
PDF
PS
@@ -371,6 +380,7 @@ Uncover
Underline
Unix
Usage
+UseBlackPtComp
UseCMap
UseOutlines
UserUnit
@@ -385,6 +395,7 @@ W
W2
WMode
Watermark
+WhitePoint
Widget
Width
Widths
@@ -402,3 +413,4 @@ ca
n0
n1
n2
+op
diff --git a/scripts/cmapdump.c b/scripts/cmapdump.c
index 97247e5b..8429747e 100644
--- a/scripts/cmapdump.c
+++ b/scripts/cmapdump.c
@@ -223,6 +223,14 @@ fz_font_context *fz_keep_font_context(fz_context *ctx)
return NULL;
}
+void fz_new_cmm_context(fz_context *ctx)
+{
+}
+
+void fz_drop_cmm_context(fz_context *ctx)
+{
+}
+
void fz_new_colorspace_context(fz_context *ctx)
{
}
diff --git a/source/cbz/mucbz.c b/source/cbz/mucbz.c
index 7000dc8f..2d357b6e 100644
--- a/source/cbz/mucbz.c
+++ b/source/cbz/mucbz.c
@@ -162,7 +162,7 @@ cbz_run_page(fz_context *ctx, fz_page *page_, fz_device *dev, const fz_matrix *c
w = image->w * DPI / xres;
h = image->h * DPI / yres;
fz_pre_scale(&local_ctm, w, h);
- fz_fill_image(ctx, dev, image, &local_ctm, 1);
+ fz_fill_image(ctx, dev, image, &local_ctm, 1, NULL);
}
static void
diff --git a/source/cbz/muimg.c b/source/cbz/muimg.c
index 6fe0687d..4cb8cc4a 100644
--- a/source/cbz/muimg.c
+++ b/source/cbz/muimg.c
@@ -57,7 +57,7 @@ img_run_page(fz_context *ctx, fz_page *page_, fz_device *dev, const fz_matrix *c
w = image->w * DPI / xres;
h = image->h * DPI / yres;
fz_pre_scale(&local_ctm, w, h);
- fz_fill_image(ctx, dev, image, &local_ctm, 1);
+ fz_fill_image(ctx, dev, image, &local_ctm, 1, NULL);
}
static void
diff --git a/source/cbz/mutiff.c b/source/cbz/mutiff.c
index 9cd306f2..b6500159 100644
--- a/source/cbz/mutiff.c
+++ b/source/cbz/mutiff.c
@@ -47,7 +47,7 @@ tiff_run_page(fz_context *ctx, fz_page *page_, fz_device *dev, const fz_matrix *
w = image->w * DPI / xres;
h = image->h * DPI / yres;
fz_pre_scale(&local_ctm, w, h);
- fz_fill_image(ctx, dev, image, &local_ctm, 1);
+ fz_fill_image(ctx, dev, image, &local_ctm, 1, NULL);
}
static void
diff --git a/source/fitz/bbox-device.c b/source/fitz/bbox-device.c
index 99c46953..a288ec45 100644
--- a/source/fitz/bbox-device.c
+++ b/source/fitz/bbox-device.c
@@ -37,7 +37,7 @@ fz_bbox_add_rect(fz_context *ctx, fz_device *dev, const fz_rect *rect, int clip)
static void
fz_bbox_fill_path(fz_context *ctx, fz_device *dev, const fz_path *path, int even_odd, const fz_matrix *ctm,
- fz_colorspace *colorspace, const float *color, float alpha)
+ fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params)
{
fz_rect r;
fz_bbox_add_rect(ctx, dev, fz_bound_path(ctx, path, NULL, ctm, &r), 0);
@@ -45,7 +45,7 @@ fz_bbox_fill_path(fz_context *ctx, fz_device *dev, const fz_path *path, int even
static void
fz_bbox_stroke_path(fz_context *ctx, fz_device *dev, const fz_path *path, const fz_stroke_state *stroke,
- const fz_matrix *ctm, fz_colorspace *colorspace, const float *color, float alpha)
+ const fz_matrix *ctm, fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params)
{
fz_rect r;
fz_bbox_add_rect(ctx, dev, fz_bound_path(ctx, path, stroke, ctm, &r), 0);
@@ -53,7 +53,7 @@ fz_bbox_stroke_path(fz_context *ctx, fz_device *dev, const fz_path *path, const
static void
fz_bbox_fill_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_matrix *ctm,
- fz_colorspace *colorspace, const float *color, float alpha)
+ fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params)
{
fz_rect r;
fz_bbox_add_rect(ctx, dev, fz_bound_text(ctx, text, NULL, ctm, &r), 0);
@@ -61,21 +61,21 @@ fz_bbox_fill_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz
static void
fz_bbox_stroke_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_stroke_state *stroke,
- const fz_matrix *ctm, fz_colorspace *colorspace, const float *color, float alpha)
+ const fz_matrix *ctm, fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params)
{
fz_rect r;
fz_bbox_add_rect(ctx, dev, fz_bound_text(ctx, text, stroke, ctm, &r), 0);
}
static void
-fz_bbox_fill_shade(fz_context *ctx, fz_device *dev, fz_shade *shade, const fz_matrix *ctm, float alpha)
+fz_bbox_fill_shade(fz_context *ctx, fz_device *dev, fz_shade *shade, const fz_matrix *ctm, float alpha, const fz_color_params *color_params)
{
fz_rect r;
fz_bbox_add_rect(ctx, dev, fz_bound_shade(ctx, shade, ctm, &r), 0);
}
static void
-fz_bbox_fill_image(fz_context *ctx, fz_device *dev, fz_image *image, const fz_matrix *ctm, float alpha)
+fz_bbox_fill_image(fz_context *ctx, fz_device *dev, fz_image *image, const fz_matrix *ctm, float alpha, const fz_color_params *color_params)
{
fz_rect r = fz_unit_rect;
fz_bbox_add_rect(ctx, dev, fz_transform_rect(&r, ctm), 0);
@@ -83,7 +83,7 @@ fz_bbox_fill_image(fz_context *ctx, fz_device *dev, fz_image *image, const fz_ma
static void
fz_bbox_fill_image_mask(fz_context *ctx, fz_device *dev, fz_image *image, const fz_matrix *ctm,
- fz_colorspace *colorspace, const float *color, float alpha)
+ fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params)
{
fz_rect r = fz_unit_rect;
fz_bbox_add_rect(ctx, dev, fz_transform_rect(&r, ctm), 0);
@@ -135,7 +135,7 @@ fz_bbox_pop_clip(fz_context *ctx, fz_device *dev)
}
static void
-fz_bbox_begin_mask(fz_context *ctx, fz_device *dev, const fz_rect *rect, int luminosity, fz_colorspace *colorspace, const float *color)
+fz_bbox_begin_mask(fz_context *ctx, fz_device *dev, const fz_rect *rect, int luminosity, fz_colorspace *colorspace, const float *color, const fz_color_params *color_params)
{
fz_bbox_device *bdev = (fz_bbox_device*)dev;
fz_bbox_add_rect(ctx, dev, rect, 1);
diff --git a/source/fitz/bitmap.c b/source/fitz/bitmap.c
index eefaebd7..37aabe7b 100644
--- a/source/fitz/bitmap.c
+++ b/source/fitz/bitmap.c
@@ -306,7 +306,7 @@ fz_clear_bitmap(fz_context *ctx, fz_bitmap *bit)
}
static void
-pbm_write_header(fz_context *ctx, fz_band_writer *writer)
+pbm_write_header(fz_context *ctx, fz_band_writer *writer, const fz_colorspace *cs)
{
fz_output *out = writer->out;
int w = writer->w;
@@ -316,7 +316,7 @@ pbm_write_header(fz_context *ctx, fz_band_writer *writer)
}
static void
-pkm_write_header(fz_context *ctx, fz_band_writer *writer)
+pkm_write_header(fz_context *ctx, fz_band_writer *writer, const fz_colorspace *cs)
{
fz_output *out = writer->out;
int w = writer->w;
@@ -336,7 +336,7 @@ fz_write_bitmap_as_pbm(fz_context *ctx, fz_output *out, fz_bitmap *bitmap)
writer = fz_new_pbm_band_writer(ctx, out);
fz_try(ctx)
{
- fz_write_header(ctx, writer, bitmap->w, bitmap->h, 1, 0, 0, 0, 0);
+ fz_write_header(ctx, writer, bitmap->w, bitmap->h, 1, 0, 0, 0, 0, NULL);
fz_write_band(ctx, writer, bitmap->stride, bitmap->h, bitmap->samples);
}
fz_always(ctx)
@@ -356,7 +356,7 @@ fz_write_bitmap_as_pkm(fz_context *ctx, fz_output *out, fz_bitmap *bitmap)
writer = fz_new_pkm_band_writer(ctx, out);
fz_try(ctx)
{
- fz_write_header(ctx, writer, bitmap->w, bitmap->h, 4, 0, 0, 0, 0);
+ fz_write_header(ctx, writer, bitmap->w, bitmap->h, 4, 0, 0, 0, 0, NULL);
fz_write_band(ctx, writer, bitmap->stride, bitmap->h, bitmap->samples);
}
fz_always(ctx)
diff --git a/source/fitz/buffer.c b/source/fitz/buffer.c
index 8212f782..96aa36a6 100644
--- a/source/fitz/buffer.c
+++ b/source/fitz/buffer.c
@@ -251,6 +251,22 @@ fz_append_rune(fz_context *ctx, fz_buffer *buf, int c)
}
void
+fz_append_int32_be(fz_context *ctx, fz_buffer *buf, int x)
+{
+ fz_append_byte(ctx, buf, (x >> 24) & 0xFF);
+ fz_append_byte(ctx, buf, (x >> 16) & 0xFF);
+ fz_append_byte(ctx, buf, (x >> 8) & 0xFF);
+ fz_append_byte(ctx, buf, (x) & 0xFF);
+}
+
+void
+fz_append_int16_be(fz_context *ctx, fz_buffer *buf, int x)
+{
+ fz_append_byte(ctx, buf, (x >> 8) & 0xFF);
+ fz_append_byte(ctx, buf, (x) & 0xFF);
+}
+
+void
fz_append_int32_le(fz_context *ctx, fz_buffer *buf, int x)
{
fz_append_byte(ctx, buf, (x)&0xFF);
@@ -435,7 +451,8 @@ fz_md5_buffer(fz_context *ctx, fz_buffer *buffer, unsigned char digest[16])
{
fz_md5 state;
fz_md5_init(&state);
- fz_md5_update(&state, buffer->data, buffer->len);
+ if (buffer)
+ fz_md5_update(&state, buffer->data, buffer->len);
fz_md5_final(&state, digest);
}
diff --git a/source/fitz/color-icc-create.c b/source/fitz/color-icc-create.c
new file mode 100644
index 00000000..58acedf5
--- /dev/null
+++ b/source/fitz/color-icc-create.c
@@ -0,0 +1,448 @@
+#include "mupdf/fitz.h"
+#include "icc34.h"
+
+#define SAVEICCPROFILE 0
+#define ICC_HEADER_SIZE 128
+#define ICC_TAG_SIZE 12
+#define ICC_NUMBER_COMMON_TAGS 2
+#define ICC_XYZPT_SIZE 12
+#define ICC_DATATYPE_SIZE 8
+#define D50_X 0.9642f
+#define D50_Y 1.0f
+#define D50_Z 0.8249f
+static const char desc_name[] = "MuPDF Internal Profile";
+static const char copy_right[] = "Copyright Artifex Software 2017";
+#if SAVEICCPROFILE
+unsigned int icc_debug_index = 0;
+#endif
+
+typedef struct fz_icc_tag_s fz_icc_tag;
+
+struct fz_icc_tag_s
+{
+ icTagSignature sig;
+ icUInt32Number offset;
+ icUInt32Number size;
+ unsigned char byte_padding;
+};
+
+#if SAVEICCPROFILE
+static void
+save_profile(fz_context *ctx, fz_buffer *buf, const char *name)
+{
+ char full_file_name[50];
+ fz_snprintf(full_file_name, sizeof full_file_name, "profile%d-%s.icc", icc_debug_index, name);
+ fz_save_buffer(ctx, buf, full_file_name);
+ icc_debug_index++;
+}
+#endif
+
+static void
+fz_append_byte_n(fz_context *ctx, fz_buffer *buf, int c, int n)
+{
+ int k;
+
+ for (k = 0; k < n; k++)
+ fz_append_byte(ctx, buf, c);
+}
+
+static int
+get_padding(int x)
+{
+ return (4 - x % 4) % 4;
+}
+
+static void
+setdatetime(fz_context *ctx, icDateTimeNumber *datetime)
+{
+ datetime->day = 0;
+ datetime->hours = 0;
+ datetime->minutes = 0;
+ datetime->month = 0;
+ datetime->seconds = 0;
+ datetime->year = 0;
+}
+
+static void
+add_gammadata(fz_context *ctx, fz_buffer *buf, unsigned short gamma, icTagTypeSignature curveType)
+{
+ fz_append_int32_be(ctx, buf, curveType);
+ fz_append_byte_n(ctx, buf, 0, 4);
+
+ /* one entry for gamma */
+ fz_append_int32_be(ctx, buf, 1);
+
+ /* The encode (8frac8) gamma, with padding */
+ fz_append_int16_be(ctx, buf, gamma);
+
+ /* pad two bytes */
+ fz_append_byte_n(ctx, buf, 0, 2);
+}
+
+static unsigned short
+float2u8Fixed8(fz_context *ctx, float number_in)
+{
+ return (unsigned short)(number_in * 256);
+}
+
+static void
+add_xyzdata(fz_context *ctx, fz_buffer *buf, icS15Fixed16Number temp_XYZ[])
+{
+ int j;
+
+ fz_append_int32_be(ctx, buf, icSigXYZType);
+ fz_append_byte_n(ctx, buf, 0, 4);
+
+ for (j = 0; j < 3; j++)
+ fz_append_int32_be(ctx, buf, temp_XYZ[j]);
+}
+
+static icS15Fixed16Number
+double2XYZtype(fz_context *ctx, float number_in)
+{
+ short s;
+ unsigned short m;
+
+ if (number_in < 0)
+ number_in = 0;
+ s = (short)number_in;
+ m = (unsigned short)((number_in - s) * 65536);
+ return (icS15Fixed16Number) ((s << 16) | m);
+}
+
+static void
+get_D50(fz_context *ctx, icS15Fixed16Number XYZ[])
+{
+ XYZ[0] = double2XYZtype(ctx, D50_X);
+ XYZ[1] = double2XYZtype(ctx, D50_Y);
+ XYZ[2] = double2XYZtype(ctx, D50_Z);
+}
+
+static void
+get_XYZ_doubletr(fz_context *ctx, icS15Fixed16Number XYZ[], float vector[])
+{
+ XYZ[0] = double2XYZtype(ctx, vector[0]);
+ XYZ[1] = double2XYZtype(ctx, vector[1]);
+ XYZ[2] = double2XYZtype(ctx, vector[2]);
+}
+
+static void
+add_desc_tag(fz_context *ctx, fz_buffer *buf, const char text[], fz_icc_tag tag_list[], int curr_tag)
+{
+ int len = strlen(text);
+
+ fz_append_int32_be(ctx, buf, icSigTextDescriptionType);
+ fz_append_byte_n(ctx, buf, 0, 4);
+ fz_append_int32_be(ctx, buf, len + 1);
+ fz_append_string(ctx, buf, text);
+ /* 1 + 4 + 4 + 2 + 1 + 67 */
+ fz_append_byte_n(ctx, buf, 0, 79);
+ fz_append_byte_n(ctx, buf, 0, tag_list[curr_tag].byte_padding);
+}
+
+static void
+add_text_tag(fz_context *ctx, fz_buffer *buf, const char text[], fz_icc_tag tag_list[], int curr_tag)
+{
+ fz_append_int32_be(ctx, buf, icSigTextType);
+ fz_append_byte_n(ctx, buf, 0, 4);
+ fz_append_string(ctx, buf, text);
+ fz_append_byte(ctx, buf, 0);
+ fz_append_byte_n(ctx, buf, 0, tag_list[curr_tag].byte_padding);
+}
+
+static void
+add_common_tag_data(fz_context *ctx, fz_buffer *buf, fz_icc_tag tag_list[])
+{
+ add_desc_tag(ctx, buf, desc_name, tag_list, 0);
+ add_text_tag(ctx, buf, copy_right, tag_list, 1);
+}
+
+static void
+init_common_tags(fz_context *ctx, fz_icc_tag tag_list[], int num_tags, int *last_tag)
+{
+ int curr_tag, temp_size;
+
+ if (*last_tag < 0)
+ curr_tag = 0;
+ else
+ curr_tag = (*last_tag) + 1;
+
+ tag_list[curr_tag].offset = ICC_HEADER_SIZE + num_tags * ICC_TAG_SIZE + 4;
+ tag_list[curr_tag].sig = icSigProfileDescriptionTag;
+
+ /* temp_size = DATATYPE_SIZE + 4 (zeros) + 4 (len) + strlen(desc_name) + 1 (null) + 4 + 4 + 2 + 1 + 67 + bytepad; */
+ temp_size = strlen(desc_name) + 91;
+
+ tag_list[curr_tag].byte_padding = get_padding(temp_size);
+ tag_list[curr_tag].size = temp_size + tag_list[curr_tag].byte_padding;
+ curr_tag++;
+ tag_list[curr_tag].offset = tag_list[curr_tag - 1].offset + tag_list[curr_tag - 1].size;
+ tag_list[curr_tag].sig = icSigCopyrightTag;
+
+ /* temp_size = DATATYPE_SIZE + 4 (zeros) + strlen(copy_right) + 1 (null); */
+ temp_size = strlen(copy_right) + 9;
+ tag_list[curr_tag].byte_padding = get_padding(temp_size);
+ tag_list[curr_tag].size = temp_size + tag_list[curr_tag].byte_padding;
+ *last_tag = curr_tag;
+}
+
+static void
+copy_header(fz_context *ctx, fz_buffer *buffer, icHeader *header)
+{
+ fz_append_int32_be(ctx, buffer, header->size);
+ fz_append_byte_n(ctx, buffer, 0, 4);
+ fz_append_int32_be(ctx, buffer, header->version);
+ fz_append_int32_be(ctx, buffer, header->deviceClass);
+ fz_append_int32_be(ctx, buffer, header->colorSpace);
+ fz_append_int32_be(ctx, buffer, header->pcs);
+ fz_append_byte_n(ctx, buffer, 0, 12);
+ fz_append_int32_be(ctx, buffer, header->magic);
+ fz_append_int32_be(ctx, buffer, header->platform);
+ fz_append_byte_n(ctx, buffer, 0, 24);
+ fz_append_int32_be(ctx, buffer, header->illuminant.X);
+ fz_append_int32_be(ctx, buffer, header->illuminant.Y);
+ fz_append_int32_be(ctx, buffer, header->illuminant.Z);
+ fz_append_byte_n(ctx, buffer, 0, 48);
+}
+
+static void
+setheader_common(fz_context *ctx, icHeader *header)
+{
+ header->cmmId = 0;
+ header->version = 0x02200000;
+ setdatetime(ctx, &(header->date));
+ header->magic = icMagicNumber;
+ header->platform = icSigMacintosh;
+ header->flags = 0;
+ header->manufacturer = 0;
+ header->model = 0;
+ header->attributes[0] = 0;
+ header->attributes[1] = 0;
+ header->renderingIntent = 3;
+ header->illuminant.X = double2XYZtype(ctx, (float) 0.9642);
+ header->illuminant.Y = double2XYZtype(ctx, (float) 1.0);
+ header->illuminant.Z = double2XYZtype(ctx, (float) 0.8249);
+ header->creator = 0;
+ memset(header->reserved, 0, 44);
+}
+
+static void
+copy_tagtable(fz_context *ctx, fz_buffer *buf, fz_icc_tag *tag_list, int num_tags)
+{
+ int k;
+
+ fz_append_int32_be(ctx, buf, num_tags);
+ for (k = 0; k < num_tags; k++)
+ {
+ fz_append_int32_be(ctx, buf, tag_list[k].sig);
+ fz_append_int32_be(ctx, buf, tag_list[k].offset);
+ fz_append_int32_be(ctx, buf, tag_list[k].size);
+ }
+}
+
+static void
+init_tag(fz_context *ctx, fz_icc_tag tag_list[], int *last_tag, icTagSignature tagsig, int datasize)
+{
+ int curr_tag = (*last_tag) + 1;
+
+ tag_list[curr_tag].offset = tag_list[curr_tag - 1].offset + tag_list[curr_tag - 1].size;
+ tag_list[curr_tag].sig = tagsig;
+ tag_list[curr_tag].byte_padding = get_padding(ICC_DATATYPE_SIZE + datasize);
+ tag_list[curr_tag].size = ICC_DATATYPE_SIZE + datasize + tag_list[curr_tag].byte_padding;
+ *last_tag = curr_tag;
+}
+
+static void
+matrixmult(fz_context *ctx, float leftmatrix[], int nlrow, int nlcol, float rightmatrix[], int nrrow, int nrcol, float result[])
+{
+ float *curr_row;
+ int k, l, j, ncols, nrows;
+ float sum;
+
+ nrows = nlrow;
+ ncols = nrcol;
+ if (nlcol == nrrow)
+ {
+ for (k = 0; k < nrows; k++)
+ {
+ curr_row = &(leftmatrix[k*nlcol]);
+ for (l = 0; l < ncols; l++)
+ {
+ sum = 0.0;
+ for (j = 0; j < nlcol; j++)
+ sum = sum + curr_row[j] * rightmatrix[j*nrcol + l];
+ result[k*ncols + l] = sum;
+ }
+ }
+ }
+}
+
+static void
+apply_adaption(fz_context *ctx, float matrix[], float in[], float out[])
+{
+ out[0] = matrix[0] * in[0] + matrix[1] * in[1] + matrix[2] * in[2];
+ out[1] = matrix[3] * in[0] + matrix[4] * in[1] + matrix[5] * in[2];
+ out[2] = matrix[6] * in[0] + matrix[7] * in[1] + matrix[8] * in[2];
+}
+
+/*
+ Compute the CAT02 transformation to get us from the Cal White point to the
+ D50 white point
+*/
+static void
+gsicc_create_compute_cam(fz_context *ctx, float white_src[], float *cam)
+{
+ float cat02matrix[] = { 0.7328f, 0.4296f, -0.1624f, -0.7036f, 1.6975f, 0.0061f, 0.003f, 0.0136f, 0.9834f };
+ float cat02matrixinv[] = { 1.0961f, -0.2789f, 0.1827f, 0.4544f, 0.4735f, 0.0721f, -0.0096f, -0.0057f, 1.0153f };
+ float vonkries_diag[9];
+ float temp_matrix[9];
+ float lms_wp_src[3], lms_wp_des[3];
+ int k;
+ float d50[3] = { D50_X, D50_Y, D50_Z };
+
+ matrixmult(ctx, cat02matrix, 3, 3, white_src, 3, 1, lms_wp_src);
+ matrixmult(ctx, cat02matrix, 3, 3, d50, 3, 1, lms_wp_des);
+ memset(&(vonkries_diag[0]), 0, sizeof(float) * 9);
+
+ for (k = 0; k < 3; k++)
+ {
+ if (lms_wp_src[k] > 0)
+ vonkries_diag[k * 3 + k] = lms_wp_des[k] / lms_wp_src[k];
+ else
+ vonkries_diag[k * 3 + k] = 1;
+ }
+ matrixmult(ctx, &(vonkries_diag[0]), 3, 3, cat02matrix, 3, 3, temp_matrix);
+ matrixmult(ctx, &(cat02matrixinv[0]), 3, 3, temp_matrix, 3, 3, cam);
+}
+
+/* Create ICC profile from PDF calGray and calRGB definitions */
+fz_buffer *
+fz_new_icc_data_from_cal_colorspace(fz_context *ctx, fz_cal_colorspace *cal)
+{
+ fz_icc_tag *tag_list;
+ icProfile iccprofile;
+ icHeader *header = &(iccprofile.header);
+ fz_buffer *profile;
+ size_t profile_size;
+ int k;
+ int num_tags;
+ unsigned short encode_gamma;
+ int last_tag;
+ icS15Fixed16Number temp_XYZ[3];
+ int tag_location;
+ icTagSignature TRC_Tags[3] = { icSigRedTRCTag, icSigGreenTRCTag, icSigBlueTRCTag };
+ int trc_tag_size;
+ float cat02[9];
+ float black_adapt[3];
+ int n = cal->n;
+
+ /* common */
+ setheader_common(ctx, header);
+ header->pcs = icSigXYZData;
+ profile_size = ICC_HEADER_SIZE;
+ header->deviceClass = icSigInputClass;
+
+ if (n == 3)
+ {
+ header->colorSpace = icSigRgbData;
+ num_tags = 10; /* common (2) + rXYZ, gXYZ, bXYZ, rTRC, gTRC, bTRC, bkpt, wtpt */
+ }
+ else
+ {
+ header->colorSpace = icSigGrayData;
+ num_tags = 5; /* common (2) + GrayTRC, bkpt, wtpt */
+ TRC_Tags[0] = icSigGrayTRCTag;
+ }
+
+ tag_list = fz_malloc(ctx, sizeof(fz_icc_tag) * num_tags);
+
+ /* precompute sizes and offsets */
+ profile_size += ICC_TAG_SIZE * num_tags;
+ profile_size += 4; /* number of tags.... */
+ last_tag = -1;
+ init_common_tags(ctx, tag_list, num_tags, &last_tag);
+ if (n == 3)
+ {
+ init_tag(ctx, tag_list, &last_tag, icSigRedColorantTag, ICC_XYZPT_SIZE);
+ init_tag(ctx, tag_list, &last_tag, icSigGreenColorantTag, ICC_XYZPT_SIZE);
+ init_tag(ctx, tag_list, &last_tag, icSigBlueColorantTag, ICC_XYZPT_SIZE);
+ }
+ init_tag(ctx, tag_list, &last_tag, icSigMediaWhitePointTag, ICC_XYZPT_SIZE);
+ init_tag(ctx, tag_list, &last_tag, icSigMediaBlackPointTag, ICC_XYZPT_SIZE);
+
+ /* 4 for count, 2 for gamma, Extra 2 bytes for 4 byte alignment requirement */
+ trc_tag_size = 8;
+ for (k = 0; k < n; k++)
+ init_tag(ctx, tag_list, &last_tag, TRC_Tags[k], trc_tag_size);
+ for (k = 0; k < num_tags; k++)
+ profile_size += tag_list[k].size;
+
+ /* Allocate buffer */
+ fz_try(ctx)
+ {
+ profile = fz_new_buffer(ctx, profile_size);
+ }
+ fz_catch(ctx)
+ {
+ fz_free(ctx, tag_list);
+ fz_rethrow(ctx);
+ }
+
+ /* Header */
+ header->size = (icUInt32Number)profile_size;
+ copy_header(ctx, profile, header);
+
+ /* Tag table */
+ copy_tagtable(ctx, profile, tag_list, num_tags);
+
+ /* Common tags */
+ add_common_tag_data(ctx, profile, tag_list);
+ tag_location = ICC_NUMBER_COMMON_TAGS;
+
+ /* Get the cat02 matrix */
+ gsicc_create_compute_cam(ctx, cal->wp, cat02);
+
+ /* The matrix */
+ if (n == 3)
+ {
+ float primary[3];
+
+ for (k = 0; k < 3; k++)
+ {
+ /* Apply the cat02 matrix to the primaries */
+ apply_adaption(ctx, cat02, &(cal->matrix[k * 3]), &(primary[0]));
+ get_XYZ_doubletr(ctx, temp_XYZ, &(primary[0]));
+ add_xyzdata(ctx, profile, temp_XYZ);
+ tag_location++;
+ }
+ }
+
+ /* White and black points. WP is D50 */
+ get_D50(ctx, temp_XYZ);
+ add_xyzdata(ctx, profile, temp_XYZ);
+ tag_location++;
+
+ /* Black point. Apply cat02*/
+ apply_adaption(ctx, cat02, cal->bp, &(black_adapt[0]));
+ get_XYZ_doubletr(ctx, temp_XYZ, &(black_adapt[0]));
+ add_xyzdata(ctx, profile, temp_XYZ);
+ tag_location++;
+
+ /* Gamma */
+ for (k = 0; k < n; k++)
+ {
+ encode_gamma = float2u8Fixed8(ctx, cal->gamma[k]);
+ add_gammadata(ctx, profile, encode_gamma, icSigCurveType);
+ tag_location++;
+ }
+
+ fz_free(ctx, tag_list);
+
+#if SAVEICCPROFILE
+ if (n == 3)
+ save_profile(ctx, profile, "calRGB");
+ else
+ save_profile(ctx, profile, "calGray");
+#endif
+ return profile;
+}
diff --git a/source/fitz/color-lcms.c b/source/fitz/color-lcms.c
new file mode 100644
index 00000000..4e75850f
--- /dev/null
+++ b/source/fitz/color-lcms.c
@@ -0,0 +1,345 @@
+#include "mupdf/fitz.h"
+#include "lcms2.h"
+#include "lcms2_plugin.h"
+#include "colorspace-imp.h"
+
+#define LCMS_BYTES_MASK 0x7
+/* #define DEBUG_LCMS_MEM(A) do { printf A; fflush(stdout); } while (0) */
+#define DEBUG_LCMS_MEM(A) do { } while (0)
+
+static void
+fz_lcms_log_error(cmsContext id, cmsUInt32Number error_code, const char *error_text)
+{
+ fz_context *ctx = (fz_context *)cmsGetContextUserData(id);
+ fz_warn(ctx, "lcms error: %s", error_text);
+}
+
+static void
+*fz_lcms_malloc(cmsContext id, unsigned int size)
+{
+ void *result;
+ fz_context *ctx = (fz_context *)cmsGetContextUserData(id);
+ result = fz_malloc_no_throw(ctx, size);
+ DEBUG_LCMS_MEM(("Allocation:: mupdf ctx = %p lcms ctx = %p allocation = %p \n", (void*) ctx, (void*) id, (void*) result));
+ return result;
+}
+
+static void
+fz_lcms_free(cmsContext id, void *ptr)
+{
+ fz_context *ctx = (fz_context *)cmsGetContextUserData(id);
+ DEBUG_LCMS_MEM(("Free:: mupdf ctx = %p lcms ctx = %p allocation = %p \n", (void*) ctx, (void*) id, (void*) ptr));
+ fz_free(ctx, ptr);
+}
+
+static void*
+fz_lcms_realloc(cmsContext id, void *ptr, unsigned int size)
+{
+ fz_context *ctx = (fz_context *)cmsGetContextUserData(id);
+ DEBUG_LCMS_MEM(("Realloc:: mupdf ctx = %p lcms ctx = %p allocation = %p \n", (void*) ctx, (void*) id, (void*) ptr));
+ if (ptr == 0)
+ return fz_lcms_malloc(id, size);
+ if (size == 0)
+ {
+ fz_lcms_free(id, ptr);
+ return NULL;
+ }
+ return fz_resize_array_no_throw(ctx, ptr, size, 1);
+}
+
+static cmsPluginMemHandler fz_lcms_memhandler =
+{
+ {
+ cmsPluginMagicNumber,
+ 2000,
+ cmsPluginMemHandlerSig,
+ NULL
+ },
+ fz_lcms_malloc,
+ fz_lcms_free,
+ fz_lcms_realloc,
+ NULL,
+ NULL,
+ NULL,
+};
+
+static int
+fz_lcms_num_devcomps(cmsContext cmm_ctx, fz_iccprofile *profile)
+{
+ return cmsChannelsOf(cmm_ctx, cmsGetColorSpace(cmm_ctx, profile->cmm_handle));
+}
+
+static void
+fz_lcms_premultiply_row(fz_context *ctx, int n, int w, unsigned char *s)
+{
+ unsigned char a;
+ int k;
+ int n1 = n-1;
+
+ for (; w > 0; w--)
+ {
+ a = s[n1];
+ for (k = 0; k < n1; k++)
+ s[k] = fz_mul255(s[k], a);
+ s += n;
+ }
+}
+
+static void
+fz_lcms_unmultiply_row(fz_context *ctx, int n, int w, unsigned char *s, const unsigned char *in)
+{
+ int a, inva;
+ int k;
+ int n1 = n-1;
+
+ for (; w > 0; w--)
+ {
+ a = in[n1];
+ inva = a ? 255 * 256 / a : 0;
+ for (k = 0; k < n1; k++)
+ s[k] = (in[k] * inva) >> 8;
+ s += n;
+ in += n;
+ }
+}
+
+/* Transform pixmap */
+void
+fz_lcms_transform_pixmap(fz_cmm_instance *instance, fz_icclink *link, fz_pixmap *dst, fz_pixmap *src)
+{
+ cmsContext cmm_ctx = (cmsContext)instance;
+ fz_context *ctx = (fz_context *)cmsGetContextUserData(cmm_ctx);
+ cmsHTRANSFORM hTransform = (cmsHTRANSFORM)link->cmm_handle;
+ int cmm_num_src, cmm_num_des;
+ unsigned char *inputpos, *outputpos, *buffer;
+ int ss = src->stride;
+ int ds = dst->stride;
+ int sw = src->w;
+ int dw = dst->w;
+ int sn = src->n;
+ int dn = dst->n;
+ int sa = src->alpha;
+ int da = dst->alpha;
+ int h = src->h;
+ DEBUG_LCMS_MEM(("@@@@@@@ Transform Pixmap Start:: mupdf ctx = %p lcms ctx = %p link = %p \n", (void*)ctx, (void*)cmm_ctx, (void*)link->cmm_handle));
+
+ /* check the channels. */
+ cmm_num_src = T_CHANNELS(cmsGetTransformInputFormat(cmm_ctx, hTransform));
+ cmm_num_des = T_CHANNELS(cmsGetTransformOutputFormat(cmm_ctx, hTransform));
+ if (cmm_num_src != sn - sa || cmm_num_des != dn - da || sa != da)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "Mismatching color setup in cmm pixmap transformation: src: %d vs %d+%d, dst: %d vs %d+%d", cmm_num_src, sn-sa, sa, cmm_num_des, dn-da, da);
+
+ /* Transform */
+ inputpos = src->samples;
+ outputpos = dst->samples;
+ if (src->alpha)
+ {
+ /* Allow for premultiplied alpha */
+ buffer = fz_malloc(ctx, ss);
+ for (; h > 0; h--)
+ {
+ fz_lcms_unmultiply_row(ctx, sn, sw, buffer, inputpos);
+ cmsDoTransform(cmm_ctx, hTransform, inputpos, outputpos, sw);
+ fz_lcms_premultiply_row(ctx, dn, dw, outputpos);
+ inputpos += ss;
+ outputpos += ds;
+ }
+ fz_free(ctx, buffer);
+ }
+ else
+ {
+ for (; h > 0; h--)
+ {
+ cmsDoTransform(cmm_ctx, hTransform, inputpos, outputpos, sw);
+ inputpos += ss;
+ outputpos += ds;
+ }
+ }
+ DEBUG_LCMS_MEM(("@@@@@@@ Transform Pixmap End:: mupdf ctx = %p lcms ctx = %p link = %p \n", (void*)ctx, (void*)cmm_ctx, (void*)link->cmm_handle));
+}
+
+/* Transform a single color. */
+void
+fz_lcms_transform_color(fz_cmm_instance *instance, fz_icclink *link, unsigned short *dst, const unsigned short *src)
+{
+ cmsContext cmm_ctx = (cmsContext)instance;
+ cmsHTRANSFORM hTransform = (cmsHTRANSFORM) link->cmm_handle;
+
+ cmsDoTransform(cmm_ctx, hTransform, src, dst, 1);
+}
+
+void
+fz_lcms_init_link(fz_cmm_instance *instance, fz_icclink *link, const fz_color_params *rend, int cmm_flags, int num_bytes, int alpha, const fz_iccprofile *src, const fz_iccprofile *prf, const fz_iccprofile *dst)
+{
+ cmsContext cmm_ctx = (cmsContext)instance;
+ fz_context *ctx = (fz_context *)cmsGetContextUserData(cmm_ctx);
+
+ cmsUInt32Number src_data_type, des_data_type;
+ cmsColorSpaceSignature src_cs, des_cs;
+ int src_num_chan, des_num_chan;
+ int lcms_src_cs, lcms_des_cs;
+ unsigned int flag = cmsFLAGS_LOWRESPRECALC | cmm_flags;
+
+ DEBUG_LCMS_MEM(("@@@@@@@ Create Link Start:: mupdf ctx = %p lcms ctx = %p src = %p des = %p \n", (void*)ctx, (void*)cmm_ctx, (void*)src->cmm_handle, (void*)dst->cmm_handle));
+
+ /* src */
+ src_cs = cmsGetColorSpace(cmm_ctx, src->cmm_handle);
+ lcms_src_cs = _cmsLCMScolorSpace(cmm_ctx, src_cs);
+ if (lcms_src_cs < 0)
+ lcms_src_cs = 0;
+ src_num_chan = cmsChannelsOf(cmm_ctx, src_cs);
+ src_data_type = (COLORSPACE_SH(lcms_src_cs) | CHANNELS_SH(src_num_chan) | DOSWAP_SH(src->bgr) | BYTES_SH(num_bytes) | EXTRA_SH(alpha));
+
+ /* dst */
+ des_cs = cmsGetColorSpace(cmm_ctx, dst->cmm_handle);
+ lcms_des_cs = _cmsLCMScolorSpace(cmm_ctx, des_cs);
+ if (lcms_des_cs < 0)
+ lcms_des_cs = 0;
+ des_num_chan = cmsChannelsOf(cmm_ctx, des_cs);
+ des_data_type = (COLORSPACE_SH(lcms_des_cs) | CHANNELS_SH(des_num_chan) | DOSWAP_SH(dst->bgr) | BYTES_SH(num_bytes) | EXTRA_SH(alpha));
+
+ /* flags */
+ if (rend->bp)
+ flag |= cmsFLAGS_BLACKPOINTCOMPENSATION;
+
+ if (alpha)
+ flag |= cmsFLAGS_COPY_ALPHA;
+
+ link->depth = num_bytes;
+ link->alpha = alpha;
+
+ if (prf == NULL)
+ {
+ link->cmm_handle = cmsCreateTransformTHR(cmm_ctx, src->cmm_handle, src_data_type, dst->cmm_handle, des_data_type, rend->ri, flag);
+ if (!link->cmm_handle)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "cmsCreateTransform failed");
+ }
+ else
+ {
+ /* littleCMS proof creation links don't work properly with the Ghent
+ * test files. Handle this in a brutish manner.
+ */
+ if (src == prf)
+ {
+ link->cmm_handle = cmsCreateTransformTHR(cmm_ctx, src->cmm_handle, src_data_type, dst->cmm_handle, des_data_type, INTENT_RELATIVE_COLORIMETRIC, flag);
+ if (!link->cmm_handle)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "cmsCreateTransform failed");
+ }
+ else if (prf == dst)
+ {
+ link->cmm_handle = cmsCreateTransformTHR(cmm_ctx, src->cmm_handle, src_data_type, prf->cmm_handle, des_data_type, rend->ri, flag);
+ if (!link->cmm_handle)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "cmsCreateTransform failed");
+ }
+ else
+ {
+ cmsHPROFILE src_to_prf_profile;
+ cmsHTRANSFORM src_to_prf_link;
+ cmsColorSpaceSignature prf_cs;
+ int prf_num_chan;
+ int lcms_prf_cs;
+ cmsUInt32Number prf_data_type;
+ cmsHPROFILE hProfiles[3];
+
+ prf_cs = cmsGetColorSpace(cmm_ctx, prf->cmm_handle);
+ lcms_prf_cs = _cmsLCMScolorSpace(cmm_ctx, prf_cs);
+ if (lcms_prf_cs < 0)
+ lcms_prf_cs = 0;
+ prf_num_chan = cmsChannelsOf(cmm_ctx, prf_cs);
+ prf_data_type = (COLORSPACE_SH(lcms_prf_cs) | CHANNELS_SH(prf_num_chan) | BYTES_SH(num_bytes));
+ src_to_prf_link = cmsCreateTransformTHR(cmm_ctx, src->cmm_handle, src_data_type, prf->cmm_handle, prf_data_type, rend->ri, flag);
+ if (!src_to_prf_link)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "cmsCreateTransform failed");
+ src_to_prf_profile = cmsTransform2DeviceLink(cmm_ctx, src_to_prf_link, 3.4, flag);
+ cmsDeleteTransform(cmm_ctx, src_to_prf_link);
+ if (!src_to_prf_profile)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "cmsTransform2DeviceLink failed");
+
+ hProfiles[0] = src_to_prf_profile;
+ hProfiles[1] = prf->cmm_handle;
+ hProfiles[2] = dst->cmm_handle;
+ link->cmm_handle = cmsCreateMultiprofileTransformTHR(cmm_ctx, hProfiles, 3, src_data_type, des_data_type, INTENT_RELATIVE_COLORIMETRIC, flag);
+ cmsCloseProfile(cmm_ctx, src_to_prf_profile);
+ if (!link->cmm_handle)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "cmsCreateMultiprofileTransform failed");
+ }
+ }
+
+ DEBUG_LCMS_MEM(("@@@@@@@ Create Link End:: mupdf ctx = %p lcms ctx = %p link = %p link_cmm = %p src = %p des = %p \n", (void*)ctx, (void*)cmm_ctx, (void*)link, (void*)link->cmm_handle, (void*)src->cmm_handle, (void*)dst->cmm_handle));
+}
+
+void
+fz_lcms_fin_link(fz_cmm_instance *instance, fz_icclink *link)
+{
+ cmsContext cmm_ctx = (cmsContext)instance;
+ DEBUG_LCMS_MEM(("Free Link:: link = %p \n", (void*)link->cmm_handle));
+ if (link->cmm_handle != NULL)
+ cmsDeleteTransform(cmm_ctx, link->cmm_handle);
+ link->cmm_handle = NULL;
+}
+
+static fz_cmm_instance *
+fz_lcms_new_instance(fz_context *ctx)
+{
+ cmsContext cmm_ctx;
+
+ cmm_ctx = cmsCreateContext(&fz_lcms_memhandler, ctx);
+ DEBUG_LCMS_MEM(("Context Creation:: mupdf ctx = %p lcms ctx = %p \n", (void*) ctx, (void*) cmm_ctx));
+ if (cmm_ctx == NULL)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "cmsCreateContext failed");
+ cmsSetLogErrorHandlerTHR(cmm_ctx, fz_lcms_log_error);
+ return (fz_cmm_instance *)cmm_ctx;
+}
+
+static void
+fz_lcms_drop_instance(fz_cmm_instance *instance)
+{
+ DEBUG_LCMS_MEM(("Context Destruction:: lcms ctx = %p \n", (void*)instance));
+ if (instance == NULL)
+ return;
+ cmsDeleteContext((cmsContext)instance);
+}
+
+static void
+fz_lcms_init_profile(fz_cmm_instance *instance, fz_iccprofile *profile)
+{
+ cmsContext cmm_ctx = (cmsContext)instance;
+ fz_context *ctx = (fz_context *)cmsGetContextUserData(cmm_ctx);
+ size_t size;
+ unsigned char *data;
+
+ DEBUG_LCMS_MEM(("@@@@@@@ Create Profile Start:: mupdf ctx = %p lcms ctx = %p \n", (void*)ctx, (void*)cmm_ctx));
+
+ size = fz_buffer_storage(ctx, profile->buffer, &data);
+ profile->cmm_handle = cmsOpenProfileFromMemTHR(cmm_ctx, data, size);
+ if (profile->cmm_handle == NULL)
+ {
+ profile->num_devcomp = 0;
+ fz_throw(ctx, FZ_ERROR_GENERIC, "cmsOpenProfileFromMem failed");
+ }
+ profile->num_devcomp = fz_lcms_num_devcomps(cmm_ctx, profile);
+
+ DEBUG_LCMS_MEM(("@@@@@@@ Create Profile End:: mupdf ctx = %p lcms ctx = %p profile = %p profile_cmm = %p \n", (void*)ctx, (void*)cmm_ctx, (void*)profile, (void*)profile->cmm_handle));
+}
+
+static void
+fz_lcms_fin_profile(fz_cmm_instance *instance, fz_iccprofile *profile)
+{
+ cmsContext cmm_ctx = (cmsContext)instance;
+ DEBUG_LCMS_MEM(("Free Profile:: profile = %p \n", (void*) profile->cmm_handle));
+ if (profile->cmm_handle != NULL)
+ cmsCloseProfile(cmm_ctx, profile->cmm_handle);
+ profile->cmm_handle = NULL;
+}
+
+fz_cmm_engine fz_cmm_engine_lcms = {
+ fz_lcms_new_instance,
+ fz_lcms_drop_instance,
+ fz_lcms_transform_pixmap,
+ fz_lcms_transform_color,
+ fz_lcms_init_link,
+ fz_lcms_fin_link,
+ fz_lcms_init_profile,
+ fz_lcms_fin_profile,
+ cmsFLAGS_NOWHITEONWHITEFIXUP
+};
diff --git a/source/fitz/colorspace-imp.h b/source/fitz/colorspace-imp.h
index bf8f3fef..9c909a4d 100644
--- a/source/fitz/colorspace-imp.h
+++ b/source/fitz/colorspace-imp.h
@@ -1,6 +1,21 @@
#ifndef MUPDF_FITZ_COLORSPACE_IMP_H
#define MUPDF_FITZ_COLORSPACE_IMP_H
+#include "mupdf/fitz/context.h"
+#include "mupdf/fitz/colorspace.h"
+#include "mupdf/fitz/color-management.h"
+#include "mupdf/fitz/pixmap.h"
+
+int fz_cmm_avoid_white_fix_flag(fz_context *ctx);
+void fz_cmm_transform_pixmap(fz_context *ctx, fz_icclink *link, fz_pixmap *dst, fz_pixmap *src);
+void fz_cmm_transform_color(fz_context *ctx, fz_icclink *link, unsigned short *dst, const unsigned short *src);
+void fz_cmm_init_link(fz_context *ctx, fz_icclink *link, const fz_color_params *rend, int cmm_flags, int num_bytes, int alpha, const fz_iccprofile *src, const fz_iccprofile *prf, const fz_iccprofile *des);
+void fz_cmm_fin_link(fz_context *ctx, fz_icclink *link);
+fz_cmm_instance *fz_cmm_new_instance(fz_context *ctx);
+void fz_cmm_drop_instance(fz_context *ctx);
+void fz_cmm_init_profile(fz_context *ctx, fz_iccprofile *profile);
+void fz_cmm_fin_profile(fz_context *ctx, fz_iccprofile *profile);
+
struct fz_colorspace_s
{
fz_storable storable;
@@ -8,10 +23,48 @@ struct fz_colorspace_s
char name[16];
int n;
int is_subtractive;
- fz_colorspace_convert_fn *to_rgb;
- fz_colorspace_convert_fn *from_rgb;
+ fz_colorspace_convert_fn *to_ccs;
+ fz_colorspace_convert_fn *from_ccs;
+ fz_colorspace_clamp_fn *clamp;
+ fz_colorspace_base_fn *get_base;
fz_colorspace_destruct_fn *free_data;
void *data;
};
+struct fz_iccprofile_s
+{
+ int num_devcomp;
+ int bgr;
+ fz_buffer *buffer;
+ unsigned char md5[16];
+ void *cmm_handle;
+};
+
+struct fz_icclink_s
+{
+ fz_storable storable;
+ int num_in;
+ int num_out;
+ int depth;
+ int alpha;
+ int is_identity;
+ void *cmm_handle;
+};
+
+struct fz_default_colorspaces_s
+{
+ int refs;
+ fz_colorspace *gray;
+ fz_colorspace *rgb;
+ fz_colorspace *cmyk;
+ fz_colorspace *oi;
+};
+
+struct fz_colorspace_context_s
+{
+ int ctx_refs;
+ const fz_cmm_engine *cmm;
+ fz_colorspace *gray, *rgb, *bgr, *cmyk, *lab;
+};
+
#endif
diff --git a/source/fitz/colorspace.c b/source/fitz/colorspace.c
index 6113e496..d040b076 100644
--- a/source/fitz/colorspace.c
+++ b/source/fitz/colorspace.c
@@ -1,13 +1,139 @@
#include "mupdf/fitz.h"
#include "colorspace-imp.h"
+#include "fitz-imp.h"
#include <assert.h>
#include <math.h>
#include <string.h>
+/* CMM module */
+
+int
+fz_cmm_avoid_white_fix_flag(fz_context *ctx)
+{
+ if (ctx && ctx->colorspace && ctx->colorspace->cmm && ctx->cmm_instance)
+ return ctx->colorspace->cmm->avoid_white_fix_flag;
+ return 0;
+}
+
+void
+fz_cmm_transform_pixmap(fz_context *ctx, fz_icclink *link, fz_pixmap *dst, fz_pixmap *src)
+{
+ if (ctx && ctx->colorspace && ctx->colorspace->cmm && ctx->cmm_instance)
+ ctx->colorspace->cmm->transform_pixmap(ctx->cmm_instance, link, dst, src);
+}
+
+void
+fz_cmm_transform_color(fz_context *ctx, fz_icclink *link, unsigned short *dst, const unsigned short *src)
+{
+ if (ctx && ctx->colorspace && ctx->colorspace->cmm && ctx->cmm_instance)
+ ctx->colorspace->cmm->transform_color(ctx->cmm_instance, link, dst, src);
+}
+
+void
+fz_cmm_init_link(fz_context *ctx, fz_icclink *link, const fz_color_params *rend, int cmm_flags, int num_bytes, int alpha, const fz_iccprofile *src, const fz_iccprofile *prf, const fz_iccprofile *des)
+{
+ if (ctx && ctx->colorspace && ctx->colorspace->cmm && ctx->cmm_instance)
+ ctx->colorspace->cmm->init_link(ctx->cmm_instance, link, rend, cmm_flags, num_bytes, alpha, src, prf, des);
+}
+
+void
+fz_cmm_fin_link(fz_context *ctx, fz_icclink *link)
+{
+ if (ctx && ctx->colorspace && ctx->colorspace->cmm && ctx->cmm_instance)
+ ctx->colorspace->cmm->fin_link(ctx->cmm_instance, link);
+}
+
+fz_cmm_instance *fz_cmm_new_instance(fz_context *ctx)
+{
+ if (ctx && ctx->colorspace && ctx->colorspace->cmm)
+ return ctx->colorspace->cmm->new_instance(ctx);
+ return NULL;
+}
+
+void fz_cmm_drop_instance(fz_context *ctx)
+{
+ if (ctx && ctx->colorspace && ctx->colorspace->cmm && ctx->cmm_instance)
+ ctx->colorspace->cmm->drop_instance(ctx->cmm_instance);
+}
+
+void fz_cmm_init_profile(fz_context *ctx, fz_iccprofile *profile)
+{
+ if (ctx && ctx->colorspace && ctx->colorspace->cmm && ctx->cmm_instance)
+ ctx->colorspace->cmm->init_profile(ctx->cmm_instance, profile);
+}
+
+void fz_cmm_fin_profile(fz_context *ctx, fz_iccprofile *profile)
+{
+ if (ctx && ctx->colorspace && ctx->colorspace->cmm && ctx->cmm_instance)
+ if (profile && profile->cmm_handle != NULL)
+ ctx->colorspace->cmm->fin_profile(ctx->cmm_instance, profile);
+}
+
#define SLOWCMYK
+const unsigned char *
+fz_lookup_icc(fz_context *ctx, const char *name, size_t *size)
+{
+#ifndef NO_ICC
+ if (fz_get_cmm_engine(ctx) == NULL)
+ return *size = 0, NULL;
+ if (!strcmp(name, "gray-icc")) {
+ extern const int fz_resources_icc_gray_icc_size;
+ extern const unsigned char fz_resources_icc_gray_icc[];
+ *size = fz_resources_icc_gray_icc_size;
+ return fz_resources_icc_gray_icc;
+ }
+ if (!strcmp(name, "rgb-icc") || !strcmp(name, "bgr-icc")) {
+ extern const int fz_resources_icc_rgb_icc_size;
+ extern const unsigned char fz_resources_icc_rgb_icc[];
+ *size = fz_resources_icc_rgb_icc_size;
+ return fz_resources_icc_rgb_icc;
+ }
+ if (!strcmp(name, "cmyk-icc")) {
+ extern const int fz_resources_icc_cmyk_icc_size;
+ extern const unsigned char fz_resources_icc_cmyk_icc[];
+ *size = fz_resources_icc_cmyk_icc_size;
+ return fz_resources_icc_cmyk_icc;
+ }
+ if (!strcmp(name, "lab-icc")) {
+ extern const int fz_resources_icc_lab_icc_size;
+ extern const unsigned char fz_resources_icc_lab_icc[];
+ *size = fz_resources_icc_lab_icc_size;
+ return fz_resources_icc_lab_icc;
+ }
+#endif
+ return *size = 0, NULL;
+}
+
+/* Same order as needed by lcms */
+static const char *fz_intent_names[] =
+{
+ "Perceptual",
+ "RelativeColorimetric",
+ "Saturation",
+ "AbsoluteColorimetric",
+};
+
+int
+fz_lookup_rendering_intent(const char *name)
+{
+ int i;
+ for (i = 0; i < nelem(fz_intent_names); i++)
+ if (!strcmp(name, fz_intent_names[i]))
+ return i;
+ return FZ_RI_RELATIVE_COLORIMETRIC;
+}
+
+char *
+fz_rendering_intent_name(int ri)
+{
+ if (ri >= 0 && ri < nelem(fz_intent_names))
+ return (char*)fz_intent_names[ri];
+ return "RelativeColorimetric";
+}
+
void
fz_drop_colorspace_imp(fz_context *ctx, fz_storable *cs_)
{
@@ -18,17 +144,33 @@ fz_drop_colorspace_imp(fz_context *ctx, fz_storable *cs_)
fz_free(ctx, cs);
}
+static void
+clamp_default(const fz_colorspace *cs, const float *src, float *dst)
+{
+ int i;
+
+ for (i = 0; i < cs->n; i++)
+ dst[i] = fz_clamp(src[i], 0, 1);
+}
+
fz_colorspace *
-fz_new_colorspace(fz_context *ctx, char *name, int n, int is_subtractive, fz_colorspace_convert_fn *to_rgb, fz_colorspace_convert_fn *from_rgb, fz_colorspace_destruct_fn *destruct, void *data, size_t size)
+fz_new_colorspace(fz_context *ctx, char *name, int is_static, int n, int is_subtractive, fz_colorspace_convert_fn *to_ccs, fz_colorspace_convert_fn *from_ccs, fz_colorspace_base_fn *base, fz_colorspace_clamp_fn *clamp, fz_colorspace_destruct_fn *destruct, void *data, size_t size)
{
fz_colorspace *cs = fz_malloc_struct(ctx, fz_colorspace);
- FZ_INIT_STORABLE(cs, 1, fz_drop_colorspace_imp);
+ FZ_INIT_STORABLE(cs, is_static ? -1 : 1, fz_drop_colorspace_imp);
cs->size = sizeof(fz_colorspace) + size;
fz_strlcpy(cs->name, name, sizeof cs->name);
cs->n = n;
cs->is_subtractive = is_subtractive;
- cs->to_rgb = to_rgb;
- cs->from_rgb = from_rgb;
+ cs->to_ccs = to_ccs;
+ cs->from_ccs = from_ccs;
+ cs->get_base = base;
+
+ if (clamp != NULL)
+ cs->clamp = clamp;
+ else
+ cs->clamp = clamp_default;
+
cs->free_data = destruct;
cs->data = data;
return cs;
@@ -46,8 +188,296 @@ fz_drop_colorspace(fz_context *ctx, fz_colorspace *cs)
fz_drop_storable(ctx, &cs->storable);
}
-/* Device colorspace definitions */
+/* icc links */
+
+typedef struct fz_link_key_s fz_link_key;
+
+struct fz_link_key_s {
+ int refs;
+ unsigned char src_md5[16];
+ unsigned char dst_md5[16];
+ fz_color_params rend;
+ int alpha;
+ int depth;
+ int proof;
+};
+
+static void *
+fz_keep_link_key(fz_context *ctx, void *key_)
+{
+ fz_link_key *key = (fz_link_key *)key_;
+ return fz_keep_imp(ctx, key, &key->refs);
+}
+
+static void
+fz_drop_link_key(fz_context *ctx, void *key_)
+{
+ fz_link_key *key = (fz_link_key *)key_;
+ if (fz_drop_imp(ctx, key, &key->refs))
+ fz_free(ctx, key);
+}
+
+static int
+fz_cmp_link_key(fz_context *ctx, void *k0_, void *k1_)
+{
+ fz_link_key *k0 = (fz_link_key *)k0_;
+ fz_link_key *k1 = (fz_link_key *)k1_;
+ return k0->proof == k1->proof &&
+ k0->alpha == k1->alpha &&
+ k0->depth == k1->depth &&
+ k0->rend.bp == k1->rend.bp &&
+ k0->rend.ri == k1->rend.ri &&
+ memcmp(k0->dst_md5, k1->dst_md5, 16) == 0 &&
+ memcmp(k0->src_md5, k1->src_md5, 16);
+}
+
+static void
+fz_format_link_key(fz_context *ctx, char *s, int n, void *key_)
+{
+ static const char *hex = "0123456789abcdef";
+ fz_link_key *key = (fz_link_key *)key_;
+ char sm[33], dm[33];
+ int i;
+ for (i = 0; i < 16; ++i)
+ {
+ sm[i*2+0] = hex[key->src_md5[i]>>4];
+ sm[i*2+1] = hex[key->src_md5[i]&15];
+ dm[i*2+0] = hex[key->dst_md5[i]>>4];
+ dm[i*2+1] = hex[key->dst_md5[i]&15];
+ }
+ sm[32] = 0;
+ dm[32] = 0;
+ fz_snprintf(s, n, "(link src_md5=%s dst_md5=%s)", sm, dm);
+}
+
+static int
+fz_make_hash_link_key(fz_context *ctx, fz_store_hash *hash, void *key_)
+{
+ fz_link_key *key = (fz_link_key *)key_;
+ memcpy(hash->u.link.dst_md5, key->dst_md5, 16);
+ memcpy(hash->u.link.src_md5, key->src_md5, 16);
+ hash->u.link.ri = key->rend.ri;
+ hash->u.link.bp = key->rend.bp;
+ hash->u.link.alpha = key->alpha;
+ hash->u.link.depth = key->depth;
+ hash->u.link.proof = key->proof;
+ return 1;
+}
+
+static fz_store_type fz_link_store_type =
+{
+ fz_make_hash_link_key,
+ fz_keep_link_key,
+ fz_drop_link_key,
+ fz_cmp_link_key,
+ fz_format_link_key,
+ NULL
+};
+
+static void
+fz_drop_link_imp(fz_context *ctx, fz_storable *storable)
+{
+ fz_icclink *link = (fz_icclink *)storable;
+ fz_cmm_fin_link(ctx, link);
+ fz_free(ctx, link);
+}
+
+static void
+fz_drop_icclink(fz_context *ctx, fz_icclink *link)
+{
+ fz_drop_storable(ctx, &link->storable);
+}
+
+static fz_iccprofile *
+get_base_icc_profile(fz_context *ctx, fz_colorspace *cs)
+{
+ fz_colorspace *base;
+ fz_cal_colorspace *cal;
+ fz_iccprofile *cal_icc;
+
+ if (!cs || !cs->get_base)
+ return NULL;
+
+ base = cs->get_base(cs);
+ if (base == NULL)
+ return NULL;
+
+ if (fz_colorspace_is_icc(ctx, base))
+ return base->data;
+ if (!fz_colorspace_is_cal(ctx, base))
+ return get_base_icc_profile(ctx, base);
+
+ cal = base->data;
+ cal_icc = cal->profile;
+ if (cal_icc && cal_icc->cmm_handle == NULL)
+ fz_cmm_init_profile(ctx, cal_icc);
+
+ return cal_icc;
+}
+
+static fz_icclink *
+fz_new_icc_link(fz_context *ctx, fz_iccprofile *src, fz_iccprofile *prf, fz_iccprofile *dst, const fz_color_params *rend, int num_bytes, int alpha)
+{
+ fz_icclink *link = fz_malloc_struct(ctx, fz_icclink);
+ FZ_INIT_STORABLE(link, 1, fz_drop_link_imp);
+
+ link->num_in = src->num_devcomp;
+ link->num_out = dst->num_devcomp;
+
+ if (memcmp(src->md5, dst->md5, 16) == 0 && rend->ri == FZ_RI_RELATIVE_COLORIMETRIC && prf == NULL)
+ {
+ link->is_identity = 1;
+ return link;
+ }
+
+ fz_try(ctx)
+ fz_cmm_init_link(ctx, link, rend, 0, num_bytes, alpha, src, prf, dst);
+ fz_catch(ctx)
+ {
+ fz_free(ctx, link);
+ fz_rethrow(ctx);
+ }
+
+ return link;
+}
+
+static void
+fz_md5_icc(fz_context *ctx, fz_iccprofile *profile)
+{
+ if (profile)
+ fz_md5_buffer(ctx, profile->buffer, profile->md5);
+}
+/* Create icc profile from calrgb, calgray values */
+static fz_iccprofile *
+fz_icc_from_cal(fz_context *ctx, fz_colorspace *cs)
+{
+ fz_cal_colorspace *cal_data = cs->data;
+ fz_iccprofile *profile;
+
+ if (cal_data->profile != NULL)
+ return cal_data->profile;
+ profile = fz_malloc_struct(ctx, fz_iccprofile);
+
+ fz_try(ctx)
+ {
+ profile->buffer = fz_new_icc_data_from_cal_colorspace(ctx, cal_data);
+ fz_md5_icc(ctx, profile);
+ cal_data->profile = profile;
+ }
+ fz_catch(ctx)
+ {
+ fz_free(ctx, profile);
+ fz_rethrow(ctx);
+ }
+
+ return profile;
+}
+
+static fz_icclink *
+fz_get_icc_link(fz_context *ctx, fz_colorspace *src, fz_colorspace *prf, fz_colorspace *dst, const fz_color_params *rend, int num_bytes, int alpha, int *src_n)
+{
+ fz_icclink *link = NULL;
+ fz_iccprofile *src_icc = NULL;
+ fz_iccprofile *dst_icc = dst->data;
+ fz_iccprofile *prf_icc = NULL;
+ fz_link_key *key;
+ fz_icclink *new_link;
+
+ if (prf != NULL)
+ prf_icc = prf->data;
+
+ if (fz_colorspace_is_icc(ctx, src))
+ src_icc = src->data;
+ else if (fz_colorspace_is_cal(ctx, src))
+ {
+ fz_cal_colorspace *cal;
+
+ cal = src->data;
+ src_icc = cal->profile;
+ /* Check if we have any work to do. */
+ if (src_icc == NULL)
+ src_icc = fz_icc_from_cal(ctx, src);
+ if (src_icc->cmm_handle == NULL)
+ {
+ fz_cmm_init_profile(ctx, src_icc);
+
+ /* The CMM failed to make a profile. Use the default. */
+ if (src_icc->cmm_handle == NULL)
+ {
+ switch (src->n)
+ {
+ case 1:
+ src_icc = fz_device_gray(ctx)->data;
+ break;
+ case 3:
+ src_icc = fz_device_rgb(ctx)->data;
+ break;
+ case 4:
+ src_icc = fz_device_cmyk(ctx)->data;
+ break;
+ default:
+ fz_throw(ctx, FZ_ERROR_GENERIC, "Poorly formed Cal color space");
+ }
+ /* To avoid repeated failures building the pdf-cal color space,
+ * assign the default profile. */
+ fz_cmm_fin_profile(ctx, src_icc);
+ cal->profile = src_icc;
+ }
+ }
+ }
+ else
+ src_icc = get_base_icc_profile(ctx, src);
+
+ if (src_icc == NULL)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "Profile missing during link creation");
+
+ *src_n = src_icc->num_devcomp;
+
+ fz_var(link);
+ fz_var(key);
+
+ fz_try(ctx)
+ {
+ /* Check the storable to see if we have a copy. */
+ key = fz_malloc_struct(ctx, fz_link_key);
+ key->refs = 1;
+ memcpy(&key->dst_md5, dst_icc->md5, 16);
+ memcpy(&key->src_md5, src_icc->md5, 16);
+ key->rend.ri = rend->ri;
+ key->rend.bp = rend->bp;
+ key->alpha = alpha;
+ key->depth = num_bytes;
+ key->proof = (prf_icc != NULL);
+ link = fz_find_item(ctx, fz_drop_link_imp, key, &fz_link_store_type);
+
+ /* Not found. Make new one add to store. */
+ if (link == NULL)
+ {
+ link = fz_new_icc_link(ctx, src_icc, prf_icc, dst_icc, rend, num_bytes, alpha);
+ new_link = fz_store_item(ctx, key, link, sizeof(fz_icclink), &fz_link_store_type);
+ if (new_link != NULL)
+ {
+ /* Found one while adding! Perhaps from another thread? */
+ fz_drop_icclink(ctx, link);
+ link = new_link;
+ }
+ }
+ }
+ fz_always(ctx)
+ {
+ fz_drop_link_key(ctx, key);
+ }
+ fz_catch(ctx)
+ {
+ /* Ignore any error that came just from the enstoring. */
+ if (link == NULL)
+ fz_rethrow(ctx);
+ }
+ return link;
+}
+
+/* Device colorspace definitions */
static void gray_to_rgb(fz_context *ctx, fz_colorspace *cs, const float *gray, float *rgb)
{
rgb[0] = gray[0];
@@ -214,10 +644,19 @@ rgb_to_lab(fz_context *ctx, fz_colorspace *cs, const float *rgb, float *lab)
lab[2] = rgb[2];
}
-int
-fz_colorspace_is_lab(fz_context *ctx, fz_colorspace *cs)
+/* This could be different for a, b */
+static void
+clamp_lab(const fz_colorspace *cs, const float *src, float *dst)
{
- return (cs && cs->to_rgb == lab_to_rgb);
+ int i;
+
+ for (i = 0; i < 3; i++)
+ dst[i] = fz_clamp(src[i], i ? -128 : 0, i ? 127 : 100);
+}
+
+static int fz_colorspace_is_lab(fz_context *ctx, const fz_colorspace *cs)
+{
+ return cs && cs->to_ccs == lab_to_rgb;
}
int
@@ -226,33 +665,101 @@ fz_colorspace_is_subtractive(fz_context *ctx, fz_colorspace *cs)
return (cs && cs->is_subtractive);
}
-static fz_colorspace k_default_gray = { {-1, fz_drop_colorspace_imp}, 0, "DeviceGray", 1, 0, gray_to_rgb, rgb_to_gray };
-static fz_colorspace k_default_rgb = { {-1, fz_drop_colorspace_imp}, 0, "DeviceRGB", 3, 0, rgb_to_rgb, rgb_to_rgb };
-static fz_colorspace k_default_bgr = { {-1, fz_drop_colorspace_imp}, 0, "DeviceBGR", 3, 0, bgr_to_rgb, rgb_to_bgr };
-static fz_colorspace k_default_cmyk = { {-1, fz_drop_colorspace_imp}, 0, "DeviceCMYK", 4, 1, cmyk_to_rgb, rgb_to_cmyk };
-static fz_colorspace k_default_lab = { {-1, fz_drop_colorspace_imp}, 0, "Lab", 3, 0, lab_to_rgb, rgb_to_lab };
+static fz_colorspace k_default_gray = { {-1, fz_drop_colorspace_imp}, 0, "DeviceGray", 1, 0, gray_to_rgb, rgb_to_gray, clamp_default, NULL, NULL, NULL };
+static fz_colorspace k_default_rgb = { {-1, fz_drop_colorspace_imp}, 0, "DeviceRGB", 3, 0, rgb_to_rgb, rgb_to_rgb, clamp_default, NULL, NULL, NULL };
+static fz_colorspace k_default_bgr = { {-1, fz_drop_colorspace_imp}, 0, "DeviceBGR", 3, 0, bgr_to_rgb, rgb_to_bgr, clamp_default, NULL, NULL, NULL };
+static fz_colorspace k_default_cmyk = { {-1, fz_drop_colorspace_imp}, 0, "DeviceCMYK", 4, 1, cmyk_to_rgb, rgb_to_cmyk, clamp_default, NULL, NULL, NULL };
+static fz_colorspace k_default_lab = { {-1, fz_drop_colorspace_imp}, 0, "Lab", 3, 0, lab_to_rgb, rgb_to_lab, clamp_lab, NULL, NULL, NULL};
+static fz_color_params k_default_color_params = { FZ_RI_RELATIVE_COLORIMETRIC, 1, 0, 0 };
-static fz_colorspace *fz_default_gray = &k_default_gray;
-static fz_colorspace *fz_default_rgb = &k_default_rgb;
-static fz_colorspace *fz_default_bgr = &k_default_bgr;
-static fz_colorspace *fz_default_cmyk = &k_default_cmyk;
-static fz_colorspace *fz_default_lab = &k_default_lab;
+static fz_colorspace *default_gray = &k_default_gray;
+static fz_colorspace *default_rgb = &k_default_rgb;
+static fz_colorspace *default_bgr = &k_default_bgr;
+static fz_colorspace *default_cmyk = &k_default_cmyk;
+static fz_colorspace *default_lab = &k_default_lab;
+static fz_color_params *default_color_params = &k_default_color_params;
-struct fz_colorspace_context_s
+const fz_cmm_engine *fz_get_cmm_engine(fz_context *ctx)
{
- int ctx_refs;
- fz_colorspace *gray, *rgb, *bgr, *cmyk, *lab;
-};
+ return ctx->colorspace ? ctx->colorspace->cmm : NULL;
+}
+
+static void
+set_no_icc(fz_colorspace_context *cct)
+{
+ cct->gray = default_gray;
+ cct->rgb = default_rgb;
+ cct->bgr = default_bgr;
+ cct->cmyk = default_cmyk;
+ cct->lab = default_lab;
+}
+
+void fz_set_cmm_engine(fz_context *ctx, const fz_cmm_engine *engine)
+{
+ fz_colorspace_context *cct;
+
+ if (!ctx)
+ return;
+ cct = ctx->colorspace;
+ if (!cct)
+ return;
+
+#ifdef NO_ICC
+ if (engine)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "ICC workflow not supported in NO_ICC build");
+#else
+ if (cct->cmm == engine)
+ return;
+
+ fz_drop_cmm_context(ctx);
+ fz_drop_colorspace(ctx, cct->gray);
+ fz_drop_colorspace(ctx, cct->rgb);
+ fz_drop_colorspace(ctx, cct->bgr);
+ fz_drop_colorspace(ctx, cct->cmyk);
+ fz_drop_colorspace(ctx, cct->lab);
+ cct->gray = NULL;
+ cct->rgb = NULL;
+ cct->bgr = NULL;
+ cct->cmyk = NULL;
+ cct->lab = NULL;
+ cct->cmm = engine;
+ fz_new_cmm_context(ctx);
+ if (engine)
+ {
+ cct->gray = fz_new_icc_colorspace(ctx, 1, 1, NULL, "gray-icc");
+ cct->rgb = fz_new_icc_colorspace(ctx, 1, 3, NULL, "rgb-icc");
+ cct->bgr = fz_new_icc_colorspace(ctx, 1, 3, NULL, "bgr-icc");
+ cct->cmyk = fz_new_icc_colorspace(ctx, 1, 4, NULL, "cmyk-icc");
+ cct->lab = fz_new_icc_colorspace(ctx, 1, 3, NULL, "lab-icc");
+ }
+ else
+ set_no_icc(cct);
+#endif
+}
void fz_new_colorspace_context(fz_context *ctx)
{
ctx->colorspace = fz_malloc_struct(ctx, fz_colorspace_context);
ctx->colorspace->ctx_refs = 1;
- ctx->colorspace->gray = fz_default_gray;
- ctx->colorspace->rgb = fz_default_rgb;
- ctx->colorspace->bgr = fz_default_bgr;
- ctx->colorspace->cmyk = fz_default_cmyk;
- ctx->colorspace->lab = fz_default_lab;
+ set_no_icc(ctx->colorspace);
+#ifdef NO_ICC
+ fz_set_cmm_engine(ctx, NULL);
+#else
+ fz_set_cmm_engine(ctx, &fz_cmm_engine_lcms);
+#endif
+}
+
+void
+fz_new_cmm_context(fz_context *ctx)
+{
+ ctx->cmm_instance = fz_cmm_new_instance(ctx);
+}
+
+void
+fz_drop_cmm_context(fz_context *ctx)
+{
+ fz_cmm_drop_instance(ctx);
+ ctx->cmm_instance = NULL;
}
fz_colorspace_context *
@@ -269,6 +776,12 @@ void fz_drop_colorspace_context(fz_context *ctx)
return;
if (fz_drop_imp(ctx, ctx->colorspace, &ctx->colorspace->ctx_refs))
{
+ fz_drop_colorspace(ctx, ctx->colorspace->gray);
+ fz_drop_colorspace(ctx, ctx->colorspace->rgb);
+ /* FIXME: bgr */
+ fz_drop_colorspace(ctx, ctx->colorspace->cmyk);
+ fz_drop_colorspace(ctx, ctx->colorspace->lab);
+ fz_drop_cmm_context(ctx);
fz_free(ctx, ctx->colorspace);
ctx->colorspace = NULL;
}
@@ -304,54 +817,15 @@ fz_device_lab(fz_context *ctx)
return ctx->colorspace->lab;
}
-void
-fz_set_device_gray(fz_context *ctx, fz_colorspace *cs)
-{
- fz_lock(ctx, FZ_LOCK_ALLOC);
- fz_drop_colorspace(ctx, ctx->colorspace->gray);
- ctx->colorspace->gray = fz_keep_colorspace(ctx, cs);
- fz_unlock(ctx, FZ_LOCK_ALLOC);
-}
-
-void
-fz_set_device_rgb(fz_context *ctx, fz_colorspace *cs)
-{
- fz_lock(ctx, FZ_LOCK_ALLOC);
- fz_drop_colorspace(ctx, ctx->colorspace->rgb);
- ctx->colorspace->rgb = fz_keep_colorspace(ctx, cs);
- fz_unlock(ctx, FZ_LOCK_ALLOC);
-}
-
-void
-fz_set_device_bgr(fz_context *ctx, fz_colorspace *cs)
-{
- fz_lock(ctx, FZ_LOCK_ALLOC);
- fz_drop_colorspace(ctx, ctx->colorspace->bgr);
- ctx->colorspace->bgr = fz_keep_colorspace(ctx, cs);
- fz_unlock(ctx, FZ_LOCK_ALLOC);
-}
-
-void
-fz_set_device_cmyk(fz_context *ctx, fz_colorspace *cs)
-{
- fz_lock(ctx, FZ_LOCK_ALLOC);
- fz_drop_colorspace(ctx, ctx->colorspace->cmyk);
- ctx->colorspace->cmyk = fz_keep_colorspace(ctx, cs);
- fz_unlock(ctx, FZ_LOCK_ALLOC);
-}
-
-void
-fz_set_device_lab(fz_context *ctx, fz_colorspace *cs)
+const fz_color_params *
+fz_default_color_params(fz_context *ctx)
{
- fz_lock(ctx, FZ_LOCK_ALLOC);
- fz_drop_colorspace(ctx, ctx->colorspace->lab);
- ctx->colorspace->lab = fz_keep_colorspace(ctx, cs);
- fz_unlock(ctx, FZ_LOCK_ALLOC);
+ return default_color_params;
}
/* Fast pixmap color conversions */
-static void fast_gray_to_rgb(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
+static void fast_gray_to_rgb(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, fz_default_colorspaces *default_cs, const fz_color_params *color_params)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
@@ -429,7 +903,7 @@ static void fast_gray_to_rgb(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
}
}
-static void fast_gray_to_cmyk(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
+static void fast_gray_to_cmyk(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, fz_default_colorspaces *default_cs, const fz_color_params *color_params)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
@@ -510,7 +984,7 @@ static void fast_gray_to_cmyk(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
}
}
-static void fast_rgb_to_gray(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
+static void fast_rgb_to_gray(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, fz_default_colorspaces *default_cs, const fz_color_params *color_params)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
@@ -582,7 +1056,7 @@ static void fast_rgb_to_gray(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
}
}
-static void fast_bgr_to_gray(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
+static void fast_bgr_to_gray(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, fz_default_colorspaces *default_cs, const fz_color_params *color_params)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
@@ -654,7 +1128,7 @@ static void fast_bgr_to_gray(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
}
}
-static void fast_rgb_to_cmyk(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
+static void fast_rgb_to_cmyk(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, fz_default_colorspaces *default_cs, const fz_color_params *color_params)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
@@ -747,7 +1221,7 @@ static void fast_rgb_to_cmyk(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
}
}
-static void fast_bgr_to_cmyk(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
+static void fast_bgr_to_cmyk(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, fz_default_colorspaces *default_cs, const fz_color_params *color_params)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
@@ -840,7 +1314,7 @@ static void fast_bgr_to_cmyk(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
}
}
-static void fast_cmyk_to_gray(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
+static void fast_cmyk_to_gray(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, fz_default_colorspaces *default_cs, const fz_color_params *color_params)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
@@ -1247,7 +1721,7 @@ static inline void cached_cmyk_conv(unsigned char *restrict const pr, unsigned c
#endif
}
-static void fast_cmyk_to_rgb(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
+static void fast_cmyk_to_rgb(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, fz_default_colorspaces *default_cs, const fz_color_params *color_params)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
@@ -1346,7 +1820,7 @@ static void fast_cmyk_to_rgb(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
}
}
-static void fast_cmyk_to_bgr(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
+static void fast_cmyk_to_bgr(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, fz_default_colorspaces *default_cs, const fz_color_params *color_params)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
@@ -1438,7 +1912,7 @@ static void fast_cmyk_to_bgr(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
}
}
-static void fast_rgb_to_bgr(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
+static void fast_rgb_to_bgr(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, fz_default_colorspaces *default_cs, const fz_color_params *color_params)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
@@ -1512,7 +1986,148 @@ static void fast_rgb_to_bgr(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
}
static void
-fz_std_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
+icc_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, fz_default_colorspaces *default_cs, const fz_color_params *color_params)
+{
+ fz_colorspace *srcs = src->colorspace;
+ fz_colorspace *dsts = dst->colorspace;
+ fz_icclink *link;
+ int i;
+ unsigned char *inputpos, *outputpos;
+ int src_n;
+
+ /* Check if we have to do a color space default substitution */
+ if (default_cs)
+ {
+ switch (fz_colorspace_n(ctx, src->colorspace))
+ {
+ case 1:
+ if (src->colorspace == fz_device_gray(ctx))
+ srcs = fz_default_gray(ctx, default_cs);
+ break;
+ case 3:
+ if (src->colorspace == fz_device_rgb(ctx))
+ srcs = fz_default_rgb(ctx, default_cs);
+ break;
+ case 4:
+ if (src->colorspace == fz_device_cmyk(ctx))
+ srcs = fz_default_cmyk(ctx, default_cs);
+ break;
+ }
+ }
+
+ inputpos = src->samples;
+ outputpos = dst->samples;
+
+ link = fz_get_icc_link(ctx, srcs, prf, dsts, color_params, 1, dst->alpha, &src_n);
+
+ if (link->is_identity)
+ {
+ for (i = 0; i < src->h; i++)
+ {
+ memcpy(outputpos, inputpos, src->stride);
+ inputpos = inputpos + src->stride;
+ outputpos = outputpos + dst->stride;
+ }
+ }
+ else
+ fz_cmm_transform_pixmap(ctx, link, dst, src);
+
+ fz_drop_icclink(ctx, link);
+}
+
+/* Drill down through the base spaces until we get the either a pdf-cal or
+ * an ICC base space. This is where we want our pixmap to be decoded prior
+ * to application of the link transform */
+static fz_colorspace*
+get_base_icc_space(fz_context *ctx, fz_colorspace *srcs)
+{
+ while (1)
+ {
+ srcs = srcs->get_base(srcs);
+ if (srcs == NULL)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "Final color space should be icc or pdf-cal or lab");
+
+ if (fz_colorspace_is_icc(ctx, srcs) || fz_colorspace_is_cal(ctx, srcs) || fz_colorspace_is_lab(ctx, srcs))
+ return srcs;
+ }
+}
+
+/* Cope with cases where we have to convert through multiple base spaces before
+ * getting to the final cm color space */
+static void
+convert_to_icc_base(fz_context *ctx, fz_colorspace *srcs, float *src_f, float *des_f)
+{
+ float temp_f[FZ_MAX_COLORS];
+ fz_colorspace *base_cs = srcs->get_base(srcs);
+
+ if (fz_colorspace_is_icc(ctx, base_cs) || fz_colorspace_is_cal(ctx, base_cs) || fz_colorspace_is_lab(ctx, base_cs))
+ srcs->to_ccs(ctx, srcs, src_f, des_f);
+ else
+ {
+ srcs->to_ccs(ctx, srcs, src_f, temp_f);
+ convert_to_icc_base(ctx, base_cs, temp_f, des_f);
+ }
+}
+
+/* For DeviceN and Separation CS, where we require an alternate tint tranform
+ * prior to the application of an icc profile. Also, indexed images have to
+ * be handled. Realize those can map from index->devn->pdf-cal->icc for
+ * example. */
+static void
+icc_base_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, fz_default_colorspaces *default_cs, const fz_color_params *color_params)
+{
+ fz_colorspace *srcs = src->colorspace;
+ fz_colorspace *base_cs = get_base_icc_space(ctx, srcs);
+ int i;
+ unsigned char *inputpos, *outputpos;
+ fz_pixmap *base;
+ fz_irect bbox;
+ int h, len;
+ float src_f[FZ_MAX_COLORS], des_f[FZ_MAX_COLORS];
+ int sn = src->n;
+ int stride_src = src->stride - src->w * sn;
+ int stride_base;
+ int bn;
+
+ base = fz_new_pixmap_with_bbox(ctx, base_cs, fz_pixmap_bbox(ctx, src, &bbox), src->alpha);
+ bn = base->n;
+ stride_base = base->stride - base->w * bn;
+
+ inputpos = src->samples;
+ outputpos = base->samples;
+
+ h = src->h;
+ while (h--)
+ {
+ len = src->w;
+ while (len--)
+ {
+ for (i = 0; i < sn; i++)
+ src_f[i] = (float) inputpos[i] / 255.0;
+
+ convert_to_icc_base(ctx, srcs, src_f, des_f);
+ base_cs->clamp(base_cs, des_f, des_f);
+
+ for (i = 0; i < bn; i++)
+ outputpos[i] = des_f[i] * 255.0;
+
+ outputpos += bn;
+ inputpos += sn;
+ }
+ outputpos += stride_base;
+ inputpos += stride_src;
+ }
+
+ fz_try(ctx)
+ icc_conv_pixmap(ctx, dst, base, prf, default_cs, color_params);
+ fz_always(ctx)
+ fz_drop_pixmap(ctx, base);
+ fz_catch(ctx)
+ fz_rethrow(ctx);
+}
+
+static void
+std_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, fz_default_colorspaces *default_cs, const fz_color_params *color_params)
{
float srcv[FZ_MAX_COLORS];
float dstv[FZ_MAX_COLORS];
@@ -1534,6 +2149,9 @@ fz_std_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
if ((int)w < 0 || h < 0)
return;
+ if (color_params == NULL)
+ color_params = fz_default_color_params(ctx);
+
srcn = ss->n;
dstn = ds->n;
@@ -1548,11 +2166,11 @@ fz_std_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
}
/* Special case for Lab colorspace (scaling of components to float) */
- if (!strcmp(ss->name, "Lab") && srcn == 3)
+ if ((fz_colorspace_is_lab(ctx, ss) || fz_colorspace_is_lab_icc(ctx, ss)) && srcn == 3)
{
fz_color_converter cc;
- fz_lookup_color_converter(ctx, &cc, ds, ss);
+ fz_find_color_converter(ctx, &cc, NULL, ds, ss, color_params);
while (h--)
{
size_t ww = w;
@@ -1573,6 +2191,7 @@ fz_std_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
d += d_line_inc;
s += s_line_inc;
}
+ fz_drop_color_converter(ctx, &cc);
}
/* Brute-force for small images */
@@ -1580,7 +2199,7 @@ fz_std_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
{
fz_color_converter cc;
- fz_lookup_color_converter(ctx, &cc, ds, ss);
+ fz_find_color_converter(ctx, &cc, NULL, ds, ss, color_params);
while (h--)
{
size_t ww = w;
@@ -1600,6 +2219,7 @@ fz_std_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
d += d_line_inc;
s += s_line_inc;
}
+ fz_drop_color_converter(ctx, &cc);
}
/* 1-d lookup table for separation and similar colorspaces */
@@ -1608,7 +2228,7 @@ fz_std_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
unsigned char lookup[FZ_MAX_COLORS * 256];
fz_color_converter cc;
- fz_lookup_color_converter(ctx, &cc, ds, ss);
+ fz_find_color_converter(ctx, &cc, NULL, ds, ss, color_params);
for (i = 0; i < 256; i++)
{
srcv[0] = i / 255.0f;
@@ -1616,6 +2236,7 @@ fz_std_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
for (k = 0; k < dstn; k++)
lookup[i * dstn + k] = dstv[k] * 255;
}
+ fz_drop_color_converter(ctx, &cc);
while (h--)
{
@@ -1644,63 +2265,70 @@ fz_std_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
unsigned char *dold;
fz_color_converter cc;
- fz_lookup_color_converter(ctx, &cc, ds, ss);
lookup = fz_new_hash_table(ctx, 509, srcn, -1, NULL);
+ fz_find_color_converter(ctx, &cc, NULL, ds, ss, color_params);
- while (h--)
+ fz_try(ctx)
{
- size_t ww = w;
- while (ww--)
+ while (h--)
{
- if (*s == *sold && memcmp(sold,s,srcn) == 0)
- {
- sold = s;
- memcpy(d, dold, dstn);
- d += dstn;
- s += srcn;
- if (da)
- *d++ = (sa ? *s : 255);
- s += sa;
- }
- else
+ size_t ww = w;
+ while (ww--)
{
- sold = s;
- dold = d;
- color = fz_hash_find(ctx, lookup, s);
- if (color)
+ if (*s == *sold && memcmp(sold,s,srcn) == 0)
{
- memcpy(d, color, dstn);
- s += srcn;
+ sold = s;
+ memcpy(d, dold, dstn);
d += dstn;
- if (dst->alpha)
+ s += srcn;
+ if (da)
*d++ = (sa ? *s : 255);
s += sa;
}
else
{
- for (k = 0; k < srcn; k++)
- srcv[k] = *s++ / 255.0f;
- cc.convert(ctx, &cc, dstv, srcv);
- for (k = 0; k < dstn; k++)
- *d++ = dstv[k] * 255;
-
- fz_hash_insert(ctx, lookup, s - srcn, d - dstn);
-
- if (dst->alpha)
- *d++ = (sa ? *s : 255);
- s += sa;
+ sold = s;
+ dold = d;
+ color = fz_hash_find(ctx, lookup, s);
+ if (color)
+ {
+ memcpy(d, color, dstn);
+ s += srcn;
+ d += dstn;
+ if (dst->alpha)
+ *d++ = (sa ? *s : 255);
+ s += sa;
+ }
+ else
+ {
+ for (k = 0; k < srcn; k++)
+ srcv[k] = *s++ / 255.0f;
+ cc.convert(ctx, &cc, dstv, srcv);
+ for (k = 0; k < dstn; k++)
+ *d++ = dstv[k] * 255;
+
+ fz_hash_insert(ctx, lookup, s - srcn, d - dstn);
+
+ if (dst->alpha)
+ *d++ = (sa ? *s : 255);
+ s += sa;
+ }
}
}
+ d += d_line_inc;
+ s += s_line_inc;
}
- d += d_line_inc;
- s += s_line_inc;
}
+ fz_always(ctx)
+ fz_drop_color_converter(ctx, &cc);
+ fz_catch(ctx)
+ fz_rethrow(ctx);
fz_drop_hash_table(ctx, lookup);
}
}
-static void fast_any_to_alpha(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
+static void fast_any_to_alpha(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src, fz_colorspace *prf, fz_default_colorspaces *default_cs, const fz_color_params *color_params)
{
if (!src->alpha)
fz_clear_pixmap_with_value(ctx, dst, 255);
@@ -1740,48 +2368,128 @@ static void fast_any_to_alpha(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
}
}
+/* Used for testing all color managed source color spaces. If it is icc, cal or
+ * has a base space that is managed */
+static fz_colorspace *
+fz_source_colorspace_cm(fz_context *ctx, fz_colorspace *cs)
+{
+ while (cs)
+ {
+ if (fz_colorspace_is_icc(ctx, cs))
+ return cs;
+ if (fz_colorspace_is_cal(ctx, cs))
+ return cs;
+ cs = fz_colorspace_base(ctx, cs);
+ }
+ return NULL;
+}
+
fz_pixmap_converter *fz_lookup_pixmap_converter(fz_context *ctx, fz_colorspace *ds, fz_colorspace *ss)
{
if (ds == NULL)
return fast_any_to_alpha;
- if (ss == fz_default_gray)
+ if (ss == default_gray)
{
- if (ds == fz_default_rgb) return fast_gray_to_rgb;
- else if (ds == fz_default_bgr) return fast_gray_to_rgb; /* bgr == rgb here */
- else if (ds == fz_default_cmyk) return fast_gray_to_cmyk;
- else return fz_std_conv_pixmap;
+ if (ds == default_rgb) return fast_gray_to_rgb;
+ else if (ds == default_bgr) return fast_gray_to_rgb; /* bgr == rgb here */
+ else if (ds == default_cmyk) return fast_gray_to_cmyk;
+ else return std_conv_pixmap;
}
- else if (ss == fz_default_rgb)
+ else if (ss == default_rgb)
{
- if (ds == fz_default_gray) return fast_rgb_to_gray;
- else if (ds == fz_default_bgr) return fast_rgb_to_bgr;
- else if (ds == fz_default_cmyk) return fast_rgb_to_cmyk;
- else return fz_std_conv_pixmap;
+ if (ds == default_gray) return fast_rgb_to_gray;
+ else if (ds == default_bgr) return fast_rgb_to_bgr;
+ else if (ds == default_cmyk) return fast_rgb_to_cmyk;
+ else return std_conv_pixmap;
}
- else if (ss == fz_default_bgr)
+ else if (ss == default_bgr)
{
- if (ds == fz_default_gray) return fast_bgr_to_gray;
- else if (ds == fz_default_rgb) return fast_rgb_to_bgr; /* bgr = rgb here */
- else if (ds == fz_default_cmyk) return fast_bgr_to_cmyk;
- else return fz_std_conv_pixmap;
+ if (ds == default_gray) return fast_bgr_to_gray;
+ else if (ds == default_rgb) return fast_rgb_to_bgr; /* bgr = rgb here */
+ else if (ds == default_cmyk) return fast_bgr_to_cmyk;
+ else return std_conv_pixmap;
}
- else if (ss == fz_default_cmyk)
+ else if (ss == default_cmyk)
{
- if (ds == fz_default_gray) return fast_cmyk_to_gray;
- else if (ds == fz_default_bgr) return fast_cmyk_to_bgr;
- else if (ds == fz_default_rgb) return fast_cmyk_to_rgb;
- else return fz_std_conv_pixmap;
+ if (ds == default_gray) return fast_cmyk_to_gray;
+ else if (ds == default_bgr) return fast_cmyk_to_bgr;
+ else if (ds == default_rgb) return fast_cmyk_to_rgb;
+ else return std_conv_pixmap;
}
- else return fz_std_conv_pixmap;
+ else
+ {
+ fz_colorspace *ss_base = fz_source_colorspace_cm(ctx, ss);
+ if (ss_base != NULL && fz_colorspace_is_icc(ctx, ds))
+ {
+ if (ss_base == ss)
+ return icc_conv_pixmap;
+ else
+ return icc_base_conv_pixmap;
+ }
+ else return std_conv_pixmap;
+ }
}
-/* Convert a single color */
+/* Single color conversion with ICC profiles. ToDo: Check if it makes sense
+ * to use lcms float link here or to do the conversion to short and back.
+ */
+static void
+icc_conv_color(fz_context *ctx, fz_color_converter *cc, float *dstv, const float *srcv)
+{
+ fz_colorspace *dsts = cc->ds;
+ int src_n = cc->n;
+ int dst_n = dsts->n;
+
+ fz_icclink *link = (fz_icclink *)cc->link;
+ int i;
+ unsigned short dstv_s[FZ_MAX_COLORS];
+ unsigned short srcv_s[FZ_MAX_COLORS];
+
+ if (link->is_identity)
+ {
+ for (i = 0; i < src_n; i++)
+ dstv[i] = srcv[i];
+ }
+ else
+ {
+ for (i = 0; i < src_n; i++)
+ srcv_s[i] = srcv[i] * 65535;
+ fz_cmm_transform_color(ctx, link, dstv_s, srcv_s);
+ for (i = 0; i < dst_n; i++)
+ dstv[i] = fz_clamp((float) dstv_s[i] / 65535.0, 0, 1);
+ }
+}
+/* Single ICC color conversion but for DeviceN, Sep and Indexed spaces.
+ * Does premapping to get to ICC */
+static void
+icc_base_conv_color(fz_context *ctx, fz_color_converter *cc, float *dstv, const float *srcv)
+{
+ fz_colorspace *srcs = cc->ss;
+
+ float local_src_map[FZ_MAX_COLORS];
+ float local_src_map2[FZ_MAX_COLORS];
+ float *src_map = local_src_map;
+
+ do
+ {
+ srcs->to_ccs(ctx, srcs, srcv, src_map);
+ srcs = srcs->get_base(srcs);
+ srcs->clamp(srcs, src_map, src_map);
+ srcv = src_map;
+ src_map = (src_map == local_src_map ? local_src_map2 : local_src_map);
+ }
+ while (!fz_colorspace_is_icc(ctx, srcs) && !fz_colorspace_is_cal(ctx, srcs));
+
+ icc_conv_color(ctx, cc, dstv, srcv);
+}
+
+/* Convert a single color */
static void
std_conv_color(fz_context *ctx, fz_color_converter *cc, float *dstv, const float *srcv)
{
@@ -1797,9 +2505,9 @@ std_conv_color(fz_context *ctx, fz_color_converter *cc, float *dstv, const float
if (srcs != dsts)
{
- assert(srcs->to_rgb && dsts->from_rgb);
- srcs->to_rgb(ctx, srcs, srcv, rgb);
- dsts->from_rgb(ctx, dsts, rgb, dstv);
+ assert(srcs->to_ccs && dsts->from_ccs);
+ srcs->to_ccs(ctx, srcs, srcv, rgb);
+ dsts->from_ccs(ctx, dsts, rgb, dstv);
for (i = 0; i < dsts->n; i++)
dstv[i] = fz_clamp(dstv[i], 0, 1);
}
@@ -1910,66 +2618,90 @@ cmyk2bgr(fz_context *ctx, fz_color_converter *cc, float *dv, const float *sv)
#endif
}
-void fz_lookup_color_converter(fz_context *ctx, fz_color_converter *cc, fz_colorspace *ds, fz_colorspace *ss)
+void fz_find_color_converter(fz_context *ctx, fz_color_converter *cc, fz_colorspace *is, fz_colorspace *ds, fz_colorspace *ss, const fz_color_params *params)
{
cc->ds = ds;
cc->ss = ss;
- if (ss == fz_default_gray)
+ cc->is = is;
+ cc->link = NULL;
+ if (ss == default_gray)
{
- if ((ds == fz_default_rgb) || (ds == fz_default_bgr))
+ if ((ds == default_rgb) || (ds == default_bgr))
cc->convert = g2rgb;
- else if (ds == fz_default_cmyk)
+ else if (ds == default_cmyk)
cc->convert = g2cmyk;
else
cc->convert = std_conv_color;
}
- else if (ss == fz_default_rgb)
+ else if (ss == default_rgb)
{
- if (ds == fz_default_gray)
+ if (ds == default_gray)
cc->convert = rgb2g;
- else if (ds == fz_default_bgr)
+ else if (ds == default_bgr)
cc->convert = rgb2bgr;
- else if (ds == fz_default_cmyk)
+ else if (ds == default_cmyk)
cc->convert = rgb2cmyk;
else
cc->convert = std_conv_color;
}
- else if (ss == fz_default_bgr)
+ else if (ss == default_bgr)
{
- if (ds == fz_default_gray)
+ if (ds == default_gray)
cc->convert = bgr2g;
- else if (ds == fz_default_rgb)
+ else if (ds == default_rgb)
cc->convert = rgb2bgr;
- else if (ds == fz_default_cmyk)
+ else if (ds == default_cmyk)
cc->convert = bgr2cmyk;
else
cc->convert = std_conv_color;
}
- else if (ss == fz_default_cmyk)
+ else if (ss == default_cmyk)
{
- if (ds == fz_default_gray)
+ if (ds == default_gray)
cc->convert = cmyk2g;
- else if (ds == fz_default_rgb)
+ else if (ds == default_rgb)
cc->convert = cmyk2rgb;
- else if (ds == fz_default_bgr)
+ else if (ds == default_bgr)
cc->convert = cmyk2bgr;
else
cc->convert = std_conv_color;
}
-
else
- cc->convert = std_conv_color;
+ {
+ fz_colorspace *ss_base = fz_source_colorspace_cm(ctx, ss);
+ if (ss_base != NULL && fz_colorspace_is_icc(ctx, ds))
+ {
+ if (ss_base == ss)
+ cc->convert = icc_conv_color;
+ else
+ cc->convert = icc_base_conv_color;
+ cc->link = fz_get_icc_link(ctx, ss_base, is, ds, params, 2, 0, &cc->n);
+ }
+ else
+ cc->convert = std_conv_color;
+ }
}
void
-fz_convert_color(fz_context *ctx, fz_colorspace *ds, float *dv, fz_colorspace *ss, const float *sv)
+fz_drop_color_converter(fz_context *ctx, fz_color_converter *cc)
+{
+ fz_icclink *link = (fz_icclink *)cc->link;
+ if (link)
+ fz_drop_icclink(ctx, link);
+ cc->link = NULL;
+
+}
+
+void
+fz_convert_color(fz_context *ctx, const fz_color_params *params, fz_colorspace *is, fz_colorspace *ds, float *dv, fz_colorspace *ss, const float *sv)
{
fz_color_converter cc;
- fz_lookup_color_converter(ctx, &cc, ds, ss);
+ fz_find_color_converter(ctx, &cc, is, ds, ss, params);
cc.convert(ctx, &cc, dv, sv);
+ fz_drop_color_converter(ctx, &cc);
}
/* Indexed */
@@ -1982,16 +2714,26 @@ struct indexed
};
static void
-indexed_to_rgb(fz_context *ctx, fz_colorspace *cs, const float *color, float *rgb)
+indexed_to_alt(fz_context *ctx, fz_colorspace *cs, const float *color, float *alt)
{
struct indexed *idx = cs->data;
- float alt[FZ_MAX_COLORS];
int i, k;
+ int n = idx->base->n;
+
i = color[0] * 255;
i = fz_clampi(i, 0, idx->high);
- for (k = 0; k < idx->base->n; k++)
- alt[k] = idx->lookup[i * idx->base->n + k] / 255.0f;
- idx->base->to_rgb(ctx, idx->base, alt, rgb);
+ for (k = 0; k < n; k++)
+ alt[k] = idx->lookup[i * n + k] / 255.0f;
+}
+
+static void
+indexed_to_rgb(fz_context *ctx, fz_colorspace *cs, const float *color, float *rgb)
+{
+ float alt[FZ_MAX_COLORS];
+ struct indexed *idx = cs->data;
+
+ indexed_to_alt(ctx, cs, color, alt);
+ idx->base->to_ccs(ctx, idx->base, alt, rgb);
}
static void
@@ -2003,10 +2745,25 @@ free_indexed(fz_context *ctx, fz_colorspace *cs)
fz_free(ctx, idx);
}
-int
-fz_colorspace_is_indexed(fz_context *ctx, fz_colorspace *cs)
+static fz_colorspace *
+base_indexed(const fz_colorspace *cs)
{
- return (cs && cs->to_rgb == indexed_to_rgb);
+ struct indexed *idx = cs->data;
+
+ return idx->base;
+}
+
+static void
+clamp_indexed(const fz_colorspace *cs, const float *in, float *out)
+{
+ struct indexed *idx = cs->data;
+
+ *out = fz_clamp(*in, 0, idx->high) / 255.0; /* To do, avoid 255 divide */
+}
+
+int fz_colorspace_is_indexed(fz_context *ctx, const fz_colorspace *cs)
+{
+ return cs && cs->clamp == clamp_indexed;
}
fz_colorspace *
@@ -2021,9 +2778,7 @@ fz_new_indexed_colorspace(fz_context *ctx, fz_colorspace *base, int high, unsign
idx->high = high;
fz_try(ctx)
- {
- cs = fz_new_colorspace(ctx, "Indexed", 1, 0, indexed_to_rgb, NULL, free_indexed, idx, sizeof(*idx) + (base->n * (idx->high + 1)) + base->size);
- }
+ cs = fz_new_colorspace(ctx, "Indexed", 0, 1, 0, fz_colorspace_is_icc(ctx, fz_device_rgb(ctx)) ? indexed_to_alt : indexed_to_rgb, NULL, base_indexed, clamp_indexed, free_indexed, idx, sizeof(*idx) + (base->n * (idx->high + 1)) + base->size);
fz_catch(ctx)
{
fz_free(ctx, idx);
@@ -2044,7 +2799,7 @@ fz_expand_indexed_pixmap(fz_context *ctx, const fz_pixmap *src, int alpha)
fz_irect bbox;
int s_line_inc, d_line_inc;
- assert(src->colorspace->to_rgb == indexed_to_rgb);
+ assert(src->colorspace->to_ccs == indexed_to_rgb || src->colorspace->to_ccs == indexed_to_alt);
assert(src->n == 1 + alpha);
idx = src->colorspace->data;
@@ -2129,23 +2884,26 @@ static void fz_cached_color_convert(fz_context *ctx, fz_color_converter *cc_, fl
}
}
-void fz_init_cached_color_converter(fz_context *ctx, fz_color_converter *cc, fz_colorspace *ds, fz_colorspace *ss)
+void fz_init_cached_color_converter(fz_context *ctx, fz_color_converter *cc, fz_colorspace *is, fz_colorspace *ds, fz_colorspace *ss, const fz_color_params *params)
{
int n = ss->n;
fz_cached_color_converter *cached = fz_malloc_struct(ctx, fz_cached_color_converter);
fz_try(ctx)
{
- fz_lookup_color_converter(ctx, &cached->base, ds, ss);
+ fz_find_color_converter(ctx, &cached->base, is, ds, ss, params);
cached->hash = fz_new_hash_table(ctx, 256, n * sizeof(float), -1, fz_free);
cc->convert = fz_cached_color_convert;
cc->ds = ds;
cc->ss = ss;
+ cc->is = is;
cc->opaque = cached;
}
fz_catch(ctx)
{
+ fz_drop_color_converter(ctx, &cached->base);
fz_drop_hash_table(ctx, cached->hash);
+ fz_free(ctx, cached);
fz_rethrow(ctx);
}
}
@@ -2160,12 +2918,13 @@ void fz_fin_cached_color_converter(fz_context *ctx, fz_color_converter *cc_)
return;
cc_->opaque = NULL;
fz_drop_hash_table(ctx, cc->hash);
+ fz_drop_color_converter(ctx, &cc->base);
fz_free(ctx, cc);
}
-int fz_colorspace_is(fz_context *ctx, const fz_colorspace *cs, fz_colorspace_convert_fn *to_rgb)
+fz_colorspace *fz_colorspace_base(fz_context *ctx, const fz_colorspace *cs)
{
- return cs && cs->to_rgb == to_rgb;
+ return cs && cs->get_base ? cs->get_base(cs) : NULL;
}
int fz_colorspace_n(fz_context *ctx, const fz_colorspace *cs)
@@ -2177,3 +2936,278 @@ const char *fz_colorspace_name(fz_context *ctx, const fz_colorspace *cs)
{
return cs ? cs->name : "";
}
+
+static void
+free_icc(fz_context *ctx, fz_colorspace *cs)
+{
+ fz_iccprofile *profile = cs->data;
+ fz_drop_buffer(ctx, profile->buffer);
+ fz_cmm_fin_profile(ctx, profile);
+ fz_free(ctx, profile);
+}
+
+/* This could be different for a* b* */
+static void
+clamp_lab_icc(const fz_colorspace *cs, const float *src, float *dst)
+{
+ dst[0] = (fz_clamp(src[0], 0, 100)) / 100.0;
+ dst[1] = (fz_clamp(src[1], -128, 127) + 128.0) / 256;
+ dst[2] = (fz_clamp(src[2], -128, 127) + 128.0) / 256;
+}
+
+/* Embedded icc profiles could have different range */
+static void
+clamp_default_icc(const fz_colorspace *cs, const float *src, float *dst)
+{
+ int i;
+ fz_iccprofile *profile = cs->data;
+
+ for (i = 0; i < profile->num_devcomp; i++)
+ dst[i] = fz_clamp(src[i], 0, 1);
+}
+
+int fz_colorspace_is_icc(fz_context *ctx, const fz_colorspace *cs)
+{
+ return cs && cs->free_data == free_icc;
+}
+
+int fz_colorspace_is_lab_icc(fz_context *ctx, const fz_colorspace *cs)
+{
+ return cs && cs->clamp == clamp_lab_icc;
+}
+
+fz_colorspace *
+fz_new_icc_colorspace(fz_context *ctx, int is_static, int num, fz_buffer *buf, const char *name)
+{
+ fz_colorspace *cs = NULL;
+ fz_iccprofile *profile;
+ int is_lab = 0;
+
+ profile = fz_malloc_struct(ctx, fz_iccprofile);
+ fz_try(ctx)
+ {
+ profile->buffer = buf;
+ if (name != NULL)
+ {
+ size_t size;
+ const unsigned char *data;
+ data = fz_lookup_icc(ctx, name, &size);
+ profile->buffer = fz_new_buffer_from_shared_data(ctx, (const char *)data, size);
+ is_lab = (strcmp(name, "lab-icc") == 0);
+ profile->bgr = (strcmp(name, "bgr-icc") == 0);
+ }
+
+ fz_cmm_init_profile(ctx, profile);
+
+ /* Check if correct type */
+ if (num != profile->num_devcomp)
+ {
+ if (name != NULL)
+ fz_drop_buffer(ctx, profile->buffer);
+ fz_cmm_fin_profile(ctx, profile);
+ fz_free(ctx, profile);
+ }
+ else
+ {
+ fz_keep_buffer(ctx, buf);
+ fz_md5_icc(ctx, profile);
+ cs = fz_new_colorspace(ctx, "icc", is_static, num, 0, NULL, NULL, NULL, is_lab ? clamp_lab_icc : clamp_default_icc, free_icc, profile, sizeof(profile));
+ }
+ }
+ fz_catch(ctx)
+ {
+ fz_drop_buffer(ctx, profile->buffer);
+ fz_cmm_fin_profile(ctx, profile);
+ fz_free(ctx, profile);
+ }
+ return cs;
+}
+
+/* Gets the icc data from a color space. Used in the writing out of the icc
+ * data for output formats.
+ */
+fz_buffer *
+fz_icc_data_from_icc_colorspace(fz_context *ctx, const fz_colorspace *cs)
+{
+ fz_iccprofile *profile;
+
+ if (cs == NULL || !fz_colorspace_is_icc(ctx, cs))
+ return NULL;
+ profile = cs->data;
+ if (!profile)
+ return NULL;
+ return profile->buffer;
+}
+
+static void
+free_cal(fz_context *ctx, fz_colorspace *cs)
+{
+ fz_cal_colorspace *cal_data = cs->data;
+ if (cal_data->profile != NULL)
+ {
+ fz_drop_buffer(ctx, cal_data->profile->buffer);
+ fz_cmm_fin_profile(ctx, cal_data->profile);
+ fz_free(ctx, cal_data->profile);
+ }
+ fz_free(ctx, cal_data);
+}
+
+int fz_colorspace_is_cal(fz_context *ctx, const fz_colorspace *cs)
+{
+ return cs && cs->free_data == free_cal;
+}
+
+/* Profile created if needed during draw command. */
+fz_colorspace *
+fz_new_cal_colorspace(fz_context *ctx, float *wp, float *bp, float *gamma, float *matrix)
+{
+ fz_colorspace *cs = NULL;
+ int num = (matrix == NULL ? 1 : 3);
+ fz_cal_colorspace *cal_data = fz_malloc_struct(ctx, fz_cal_colorspace);
+
+ memcpy(&cal_data->bp, bp, sizeof(float) * 3);
+ memcpy(&cal_data->wp, wp, sizeof(float) * 3);
+ memcpy(&cal_data->gamma, gamma, sizeof(float) * num);
+ if (matrix != NULL)
+ memcpy(&cal_data->matrix, matrix, sizeof(float) * 9);
+ cal_data->n = num;
+
+ fz_try(ctx)
+ cs = fz_new_colorspace(ctx, "pdf-cal", 0, num, 0, NULL, NULL, NULL, NULL, free_cal, cal_data, sizeof(cal_data));
+ fz_catch(ctx)
+ {
+ fz_free(ctx, cal_data);
+ fz_rethrow(ctx);
+ }
+ return cs;
+}
+
+void
+fz_clamp_color(fz_context *ctx, const fz_colorspace *cs, const float *in, float *out)
+{
+ cs->clamp(cs, in, out);
+}
+
+/* Default CS. To handle the page specific default settings that PDF can do in
+ * its page resource dictionary as well as the output intent. Both need to
+ * to be accessible by the device on the other side of the display list.
+ * Same with the output intent. */
+void
+fz_set_default_gray(fz_context *ctx, fz_default_colorspaces *default_cs, fz_colorspace *cs)
+{
+ if (cs->n == 1)
+ {
+ fz_drop_colorspace(ctx, default_cs->gray);
+ default_cs->gray = fz_keep_colorspace(ctx, cs);
+ }
+}
+
+void
+fz_set_default_rgb(fz_context *ctx, fz_default_colorspaces *default_cs, fz_colorspace *cs)
+{
+ if (cs->n == 3)
+ {
+ fz_drop_colorspace(ctx, default_cs->rgb);
+ default_cs->rgb = fz_keep_colorspace(ctx, cs);
+ }
+}
+
+void
+fz_set_default_cmyk(fz_context *ctx, fz_default_colorspaces *default_cs, fz_colorspace *cs)
+{
+ if (cs->n == 4)
+ {
+ fz_drop_colorspace(ctx, default_cs->cmyk);
+ default_cs->cmyk = fz_keep_colorspace(ctx, cs);
+ }
+}
+
+void
+fz_set_default_output_intent(fz_context *ctx, fz_default_colorspaces *default_cs, fz_colorspace *cs)
+{
+ fz_drop_colorspace(ctx, default_cs->oi);
+ default_cs->oi = fz_keep_colorspace(ctx, cs);
+
+ switch (cs->n)
+ {
+ case 1:
+ fz_drop_colorspace(ctx, default_cs->gray);
+ default_cs->gray = fz_keep_colorspace(ctx, cs);
+ break;
+ case 3:
+ fz_drop_colorspace(ctx, default_cs->rgb);
+ default_cs->rgb = fz_keep_colorspace(ctx, cs);
+ break;
+ case 4:
+ fz_drop_colorspace(ctx, default_cs->cmyk);
+ default_cs->cmyk = fz_keep_colorspace(ctx, cs);
+ break;
+ }
+}
+
+fz_colorspace *
+fz_default_gray(fz_context *ctx, fz_default_colorspaces *default_cs)
+{
+ if (default_cs)
+ return default_cs->gray;
+ else
+ return fz_device_gray(ctx);
+}
+
+fz_colorspace *
+fz_default_rgb(fz_context *ctx, fz_default_colorspaces *default_cs)
+{
+ if (default_cs)
+ return default_cs->rgb;
+ else
+ return fz_device_rgb(ctx);
+}
+
+fz_colorspace *
+fz_default_cmyk(fz_context *ctx, fz_default_colorspaces *default_cs)
+{
+ if (default_cs)
+ return default_cs->cmyk;
+ else
+ return fz_device_cmyk(ctx);
+}
+
+fz_colorspace *
+fz_default_output_intent(fz_context *ctx, fz_default_colorspaces *default_cs)
+{
+ if (default_cs)
+ return default_cs->oi;
+ else
+ return NULL;
+}
+
+fz_default_colorspaces *
+fz_new_default_colorspaces(fz_context *ctx)
+{
+ fz_default_colorspaces *default_cs = fz_malloc_struct(ctx, fz_default_colorspaces);
+ default_cs->refs = 1;
+ default_cs->gray = fz_keep_colorspace(ctx, fz_device_gray(ctx));
+ default_cs->rgb = fz_keep_colorspace(ctx, fz_device_rgb(ctx));
+ default_cs->cmyk = fz_keep_colorspace(ctx, fz_device_cmyk(ctx));
+ default_cs->oi = NULL;
+ return default_cs;
+}
+
+fz_default_colorspaces *
+fz_keep_default_colorspaces(fz_context *ctx, fz_default_colorspaces *default_cs)
+{
+ return fz_keep_imp(ctx, default_cs, &default_cs->refs);
+}
+
+void
+fz_drop_default_colorspaces(fz_context *ctx, fz_default_colorspaces *default_cs)
+{
+ if (fz_drop_imp(ctx, default_cs, &default_cs->refs))
+ {
+ fz_drop_colorspace(ctx, default_cs->gray);
+ fz_drop_colorspace(ctx, default_cs->rgb);
+ fz_drop_colorspace(ctx, default_cs->cmyk);
+ fz_drop_colorspace(ctx, default_cs->oi);
+ fz_free(ctx, default_cs);
+ }
+}
diff --git a/source/fitz/context.c b/source/fitz/context.c
index 42806bc0..380af9a3 100644
--- a/source/fitz/context.c
+++ b/source/fitz/context.c
@@ -146,6 +146,7 @@ fz_drop_context(fz_context *ctx)
fz_drop_style_context(ctx);
fz_drop_tuning_context(ctx);
fz_drop_colorspace_context(ctx);
+ fz_drop_cmm_context(ctx);
fz_drop_font_context(ctx);
fz_drop_id_context(ctx);
fz_drop_output_context(ctx);
@@ -242,6 +243,7 @@ fz_new_context_imp(const fz_alloc_context *alloc, const fz_locks_context *locks,
fz_new_output_context(ctx);
fz_new_store_context(ctx, max_store);
fz_new_glyph_cache_context(ctx);
+ fz_new_cmm_context(ctx);
fz_new_colorspace_context(ctx);
fz_new_font_context(ctx);
fz_new_id_context(ctx);
@@ -291,6 +293,7 @@ fz_clone_context_internal(fz_context *ctx)
new_ctx->store = fz_keep_store_context(new_ctx);
new_ctx->glyph_cache = ctx->glyph_cache;
new_ctx->glyph_cache = fz_keep_glyph_cache(new_ctx);
+ fz_new_cmm_context(new_ctx);
new_ctx->colorspace = ctx->colorspace;
new_ctx->colorspace = fz_keep_colorspace_context(new_ctx);
new_ctx->font = ctx->font;
diff --git a/source/fitz/device.c b/source/fitz/device.c
index 21f74f65..fcf135d0 100644
--- a/source/fitz/device.c
+++ b/source/fitz/device.c
@@ -109,22 +109,22 @@ pop_clip_stack(fz_context *ctx, fz_device *dev)
void
fz_fill_path(fz_context *ctx, fz_device *dev, const fz_path *path, int even_odd, const fz_matrix *ctm,
- fz_colorspace *colorspace, const float *color, float alpha)
+ fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params)
{
if (dev->error_depth)
return;
if (dev->fill_path)
- dev->fill_path(ctx, dev, path, even_odd, ctm, colorspace, color, alpha);
+ dev->fill_path(ctx, dev, path, even_odd, ctm, colorspace, color, alpha, color_params);
}
void
fz_stroke_path(fz_context *ctx, fz_device *dev, const fz_path *path, const fz_stroke_state *stroke, const fz_matrix *ctm,
- fz_colorspace *colorspace, const float *color, float alpha)
+ fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params)
{
if (dev->error_depth)
return;
if (dev->stroke_path)
- dev->stroke_path(ctx, dev, path, stroke, ctm, colorspace, color, alpha);
+ dev->stroke_path(ctx, dev, path, stroke, ctm, colorspace, color, alpha, color_params);
}
void
@@ -195,22 +195,22 @@ fz_clip_stroke_path(fz_context *ctx, fz_device *dev, const fz_path *path, const
void
fz_fill_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_matrix *ctm,
- fz_colorspace *colorspace, const float *color, float alpha)
+ fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params)
{
if (dev->error_depth)
return;
if (dev->fill_text)
- dev->fill_text(ctx, dev, text, ctm, colorspace, color, alpha);
+ dev->fill_text(ctx, dev, text, ctm, colorspace, color, alpha, color_params);
}
void
fz_stroke_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_stroke_state *stroke, const fz_matrix *ctm,
- fz_colorspace *colorspace, const float *color, float alpha)
+ fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params)
{
if (dev->error_depth)
return;
if (dev->stroke_text)
- dev->stroke_text(ctx, dev, text, stroke, ctm, colorspace, color, alpha);
+ dev->stroke_text(ctx, dev, text, stroke, ctm, colorspace, color, alpha, color_params);
}
void
@@ -305,31 +305,31 @@ fz_pop_clip(fz_context *ctx, fz_device *dev)
}
void
-fz_fill_shade(fz_context *ctx, fz_device *dev, fz_shade *shade, const fz_matrix *ctm, float alpha)
+fz_fill_shade(fz_context *ctx, fz_device *dev, fz_shade *shade, const fz_matrix *ctm, float alpha, const fz_color_params *color_params)
{
if (dev->error_depth)
return;
if (dev->fill_shade)
- dev->fill_shade(ctx, dev, shade, ctm, alpha);
+ dev->fill_shade(ctx, dev, shade, ctm, alpha, color_params);
}
void
-fz_fill_image(fz_context *ctx, fz_device *dev, fz_image *image, const fz_matrix *ctm, float alpha)
+fz_fill_image(fz_context *ctx, fz_device *dev, fz_image *image, const fz_matrix *ctm, float alpha, const fz_color_params *color_params)
{
if (dev->error_depth)
return;
if (dev->fill_image)
- dev->fill_image(ctx, dev, image, ctm, alpha);
+ dev->fill_image(ctx, dev, image, ctm, alpha, color_params);
}
void
fz_fill_image_mask(fz_context *ctx, fz_device *dev, fz_image *image, const fz_matrix *ctm,
- fz_colorspace *colorspace, const float *color, float alpha)
+ fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params)
{
if (dev->error_depth)
return;
if (dev->fill_image_mask)
- dev->fill_image_mask(ctx, dev, image, ctm, colorspace, color, alpha);
+ dev->fill_image_mask(ctx, dev, image, ctm, colorspace, color, alpha, color_params);
}
void
@@ -366,7 +366,7 @@ fz_clip_image_mask(fz_context *ctx, fz_device *dev, fz_image *image, const fz_ma
}
void
-fz_begin_mask(fz_context *ctx, fz_device *dev, const fz_rect *area, int luminosity, fz_colorspace *colorspace, const float *bc)
+fz_begin_mask(fz_context *ctx, fz_device *dev, const fz_rect *area, int luminosity, fz_colorspace *colorspace, const float *bc, const fz_color_params *color_params)
{
if (dev->error_depth)
{
@@ -379,7 +379,7 @@ fz_begin_mask(fz_context *ctx, fz_device *dev, const fz_rect *area, int luminosi
if (dev->hints & FZ_MAINTAIN_CONTAINER_STACK)
push_clip_stack(ctx, dev, area, fz_device_container_stack_in_mask);
if (dev->begin_mask)
- dev->begin_mask(ctx, dev, area, luminosity, colorspace, bc);
+ dev->begin_mask(ctx, dev, area, luminosity, colorspace, bc, color_params);
}
fz_catch(ctx)
{
@@ -513,3 +513,10 @@ fz_render_flags(fz_context *ctx, fz_device *dev, int set, int clear)
if (dev->render_flags)
dev->render_flags(ctx, dev, set, clear);
}
+
+void
+fz_set_default_colorspaces(fz_context *ctx, fz_device *dev, fz_default_colorspaces *default_cs)
+{
+ if (dev->set_default_colorspaces)
+ dev->set_default_colorspaces(ctx, dev, default_cs);
+}
diff --git a/source/fitz/document.c b/source/fitz/document.c
index 8f34026a..ceccd26d 100644
--- a/source/fitz/document.c
+++ b/source/fitz/document.c
@@ -296,6 +296,14 @@ fz_lookup_metadata(fz_context *ctx, fz_document *doc, const char *key, char *buf
return -1;
}
+fz_colorspace *
+fz_document_output_intent(fz_context *ctx, fz_document *doc)
+{
+ if (doc && doc->get_output_intent)
+ return doc->get_output_intent(ctx, doc);
+ return NULL;
+}
+
fz_page *
fz_load_page(fz_context *ctx, fz_document *doc, int number)
{
diff --git a/source/fitz/draw-device.c b/source/fitz/draw-device.c
index af8e8384..b4cb88c2 100644
--- a/source/fitz/draw-device.c
+++ b/source/fitz/draw-device.c
@@ -44,6 +44,7 @@ struct fz_draw_device_s
fz_device super;
fz_matrix transform;
fz_rasterizer *rast;
+ fz_default_colorspaces *default_cs;
int flags;
int top;
fz_scale_cache *cache_x;
@@ -107,6 +108,50 @@ static void stack_change(fz_context *ctx, fz_draw_device *dev, char *s)
#define STACK_CONVERT(A) do {} while (0)
#endif
+/* Based upon the existence of a proof color space, and if we happen to be
+ * in a color space that is our target color space or a transparency group
+ * color space decide if we should be using the proof color space at this time */
+static fz_colorspace *
+fz_proof_cs(fz_context *ctx, fz_device *devp)
+{
+ fz_draw_device *dev = (fz_draw_device*)devp;
+ fz_colorspace *prf = fz_default_output_intent(ctx, dev->default_cs);
+ fz_draw_state *state = &dev->stack[dev->top];
+ fz_colorspace *model = state->dest->colorspace;
+
+ if (prf == NULL || model == prf)
+ return NULL;
+ return prf;
+}
+
+/* Logic below assumes that default cs is set to color context cs if there
+ * was not a default in the document for that particular cs
+ */
+static fz_colorspace *fz_default_colorspace(fz_context *ctx, fz_default_colorspaces *default_cs, fz_colorspace *cs)
+{
+ if (cs == NULL)
+ return NULL;
+ if (default_cs == NULL)
+ return cs;
+
+ switch (fz_colorspace_n(ctx, cs))
+ {
+ case 1:
+ if (cs == fz_device_gray(ctx))
+ return fz_default_gray(ctx, default_cs);
+ break;
+ case 3:
+ if (cs == fz_device_rgb(ctx))
+ return fz_default_rgb(ctx, default_cs);
+ break;
+ case 4:
+ if (cs == fz_device_cmyk(ctx))
+ return fz_default_cmyk(ctx, default_cs);
+ break;
+ }
+ return cs;
+}
+
static void fz_grow_stack(fz_context *ctx, fz_draw_device *dev)
{
int max = dev->stack_cap * 2;
@@ -281,12 +326,13 @@ static inline fz_matrix concat(const fz_matrix *one, const fz_matrix *two)
static void
fz_draw_fill_path(fz_context *ctx, fz_device *devp, const fz_path *path, int even_odd, const fz_matrix *in_ctm,
- fz_colorspace *colorspace, const float *color, float alpha)
+ fz_colorspace *colorspace_in, const float *color, float alpha, const fz_color_params *color_params)
{
fz_draw_device *dev = (fz_draw_device*)devp;
fz_matrix ctm = concat(in_ctm, &dev->transform);
fz_rasterizer *rast = dev->rast;
-
+ fz_colorspace *colorspace = fz_default_colorspace(ctx, dev->default_cs, colorspace_in);
+ fz_colorspace *prf = fz_proof_cs(ctx, devp);
float expansion = fz_matrix_expansion(&ctm);
float flatness = 0.3f / expansion;
unsigned char colorbv[FZ_MAX_COLORS + 1];
@@ -299,6 +345,9 @@ fz_draw_fill_path(fz_context *ctx, fz_device *devp, const fz_path *path, int eve
if (colorspace == NULL && model != NULL)
fz_throw(ctx, FZ_ERROR_GENERIC, "color destination requires source color");
+ if (color_params == NULL)
+ color_params = fz_default_color_params(ctx);
+
if (flatness < 0.001f)
flatness = 0.001f;
@@ -312,7 +361,7 @@ fz_draw_fill_path(fz_context *ctx, fz_device *devp, const fz_path *path, int eve
n = fz_colorspace_n(ctx, model);
if (n > 0)
{
- fz_convert_color(ctx, model, colorfv, colorspace, color);
+ fz_convert_color(ctx, color_params, prf, model, colorfv, colorspace, color);
for (i = 0; i < n; i++)
colorbv[i] = colorfv[i] * 255;
}
@@ -336,12 +385,13 @@ fz_draw_fill_path(fz_context *ctx, fz_device *devp, const fz_path *path, int eve
static void
fz_draw_stroke_path(fz_context *ctx, fz_device *devp, const fz_path *path, const fz_stroke_state *stroke, const fz_matrix *in_ctm,
- fz_colorspace *colorspace, const float *color, float alpha)
+ fz_colorspace *colorspace_in, const float *color, float alpha, const fz_color_params *color_params)
{
fz_draw_device *dev = (fz_draw_device*)devp;
fz_matrix ctm = concat(in_ctm, &dev->transform);
fz_rasterizer *rast = dev->rast;
-
+ fz_colorspace *colorspace = fz_default_colorspace(ctx, dev->default_cs, colorspace_in);
+ fz_colorspace *prf = fz_proof_cs(ctx, devp);
float expansion = fz_matrix_expansion(&ctm);
float flatness = 0.3f / expansion;
float linewidth = stroke->linewidth;
@@ -354,9 +404,13 @@ fz_draw_stroke_path(fz_context *ctx, fz_device *devp, const fz_path *path, const
fz_colorspace *model = state->dest->colorspace;
float mlw = fz_graphics_min_line_width(ctx);
+
if (colorspace == NULL && model != NULL)
fz_throw(ctx, FZ_ERROR_GENERIC, "color destination requires source color");
+ if (color_params == NULL)
+ color_params = fz_default_color_params(ctx);
+
if (mlw > aa_level)
aa_level = mlw;
if (linewidth * expansion < aa_level)
@@ -374,7 +428,7 @@ fz_draw_stroke_path(fz_context *ctx, fz_device *devp, const fz_path *path, const
n = fz_colorspace_n(ctx, model);
if (n > 0)
{
- fz_convert_color(ctx, model, colorfv, colorspace, color);
+ fz_convert_color(ctx, color_params, prf, model, colorfv, colorspace, color);
for (i = 0; i < n; i++)
colorbv[i] = colorfv[i] * 255;
}
@@ -626,7 +680,7 @@ draw_glyph(unsigned char *colorbv, fz_pixmap *dst, fz_glyph *glyph,
static void
fz_draw_fill_text(fz_context *ctx, fz_device *devp, const fz_text *text, const fz_matrix *in_ctm,
- fz_colorspace *colorspace, const float *color, float alpha)
+ fz_colorspace *colorspace_in, const float *color, float alpha, const fz_color_params *color_params)
{
fz_draw_device *dev = (fz_draw_device*)devp;
fz_matrix ctm = concat(in_ctm, &dev->transform);
@@ -637,17 +691,25 @@ fz_draw_fill_text(fz_context *ctx, fz_device *devp, const fz_text *text, const f
float colorfv[FZ_MAX_COLORS];
fz_text_span *span;
int i, n;
+ fz_colorspace *colorspace = NULL;
+ fz_colorspace *prf = fz_proof_cs(ctx, devp);
+
+ if (colorspace_in)
+ colorspace = fz_default_colorspace(ctx, dev->default_cs, colorspace_in);
if (colorspace == NULL && model != NULL)
fz_throw(ctx, FZ_ERROR_GENERIC, "color destination requires source color");
+ if (color_params == NULL)
+ color_params = fz_default_color_params(ctx);
+
if (state->blendmode & FZ_BLEND_KNOCKOUT)
state = fz_knockout_begin(ctx, dev);
n = fz_colorspace_n(ctx, model);
if (n > 0)
{
- fz_convert_color(ctx, model, colorfv, colorspace, color);
+ fz_convert_color(ctx, color_params, prf, model, colorfv, colorspace, color);
for (i = 0; i < n; i++)
colorbv[i] = colorfv[i] * 255;
}
@@ -700,7 +762,7 @@ fz_draw_fill_text(fz_context *ctx, fz_device *devp, const fz_text *text, const f
fz_path *path = fz_outline_glyph(ctx, span->font, gid, &tm);
if (path)
{
- fz_draw_fill_path(ctx, devp, path, 0, in_ctm, colorspace, color, alpha);
+ fz_draw_fill_path(ctx, devp, path, 0, in_ctm, colorspace, color, alpha, color_params);
fz_drop_path(ctx, path);
}
else
@@ -717,8 +779,7 @@ fz_draw_fill_text(fz_context *ctx, fz_device *devp, const fz_text *text, const f
static void
fz_draw_stroke_text(fz_context *ctx, fz_device *devp, const fz_text *text, const fz_stroke_state *stroke,
- const fz_matrix *in_ctm, fz_colorspace *colorspace,
- const float *color, float alpha)
+ const fz_matrix *in_ctm, fz_colorspace *colorspace_in, const float *color, float alpha, const fz_color_params *color_params)
{
fz_draw_device *dev = (fz_draw_device*)devp;
fz_matrix ctm = concat(in_ctm, &dev->transform);
@@ -728,17 +789,25 @@ fz_draw_stroke_text(fz_context *ctx, fz_device *devp, const fz_text *text, const
float colorfv[FZ_MAX_COLORS];
fz_text_span *span;
int i, n;
+ fz_colorspace *colorspace = NULL;
+ fz_colorspace *prf = fz_proof_cs(ctx, devp);
+
+ if (colorspace_in)
+ colorspace = fz_default_colorspace(ctx, dev->default_cs, colorspace_in);
if (colorspace == NULL && model != NULL)
fz_throw(ctx, FZ_ERROR_GENERIC, "color destination requires source color");
+ if (color_params == NULL)
+ color_params = fz_default_color_params(ctx);
+
if (state->blendmode & FZ_BLEND_KNOCKOUT)
state = fz_knockout_begin(ctx, dev);
n = fz_colorspace_n(ctx, model);
if (n > 0)
{
- fz_convert_color(ctx, model, colorfv, colorspace, color);
+ fz_convert_color(ctx, color_params, prf, model, colorfv, colorspace, color);
for (i = 0; i < n; i++)
colorbv[i] = colorfv[i] * 255;
}
@@ -779,7 +848,7 @@ fz_draw_stroke_text(fz_context *ctx, fz_device *devp, const fz_text *text, const
fz_path *path = fz_outline_glyph(ctx, span->font, gid, &tm);
if (path)
{
- fz_draw_stroke_path(ctx, devp, path, stroke, in_ctm, colorspace, color, alpha);
+ fz_draw_stroke_path(ctx, devp, path, stroke, in_ctm, colorspace, color, alpha, color_params);
fz_drop_path(ctx, path);
}
else
@@ -893,7 +962,7 @@ fz_draw_clip_text(fz_context *ctx, fz_device *devp, const fz_text *text, const f
state[1].mask = NULL;
fz_try(ctx)
{
- fz_draw_fill_path(ctx, devp, path, 0, in_ctm, fz_device_gray(ctx), &white, 1);
+ fz_draw_fill_path(ctx, devp, path, 0, in_ctm, fz_device_gray(ctx), &white, 1, NULL);
}
fz_always(ctx)
{
@@ -1016,7 +1085,7 @@ fz_draw_clip_stroke_text(fz_context *ctx, fz_device *devp, const fz_text *text,
state[0].mask = NULL;
fz_try(ctx)
{
- fz_draw_stroke_path(ctx, devp, path, stroke, in_ctm, fz_device_gray(ctx), &white, 1);
+ fz_draw_stroke_path(ctx, devp, path, stroke, in_ctm, fz_device_gray(ctx), &white, 1, NULL);
}
fz_always(ctx)
{
@@ -1050,7 +1119,7 @@ fz_draw_ignore_text(fz_context *ctx, fz_device *dev, const fz_text *text, const
}
static void
-fz_draw_fill_shade(fz_context *ctx, fz_device *devp, fz_shade *shade, const fz_matrix *in_ctm, float alpha)
+fz_draw_fill_shade(fz_context *ctx, fz_device *devp, fz_shade *shade, const fz_matrix *in_ctm, float alpha, const fz_color_params *color_params)
{
fz_draw_device *dev = (fz_draw_device*)devp;
fz_matrix ctm = concat(in_ctm, &dev->transform);
@@ -1061,6 +1130,7 @@ fz_draw_fill_shade(fz_context *ctx, fz_device *devp, fz_shade *shade, const fz_m
unsigned char colorbv[FZ_MAX_COLORS + 1];
fz_draw_state *state = &dev->stack[dev->top];
fz_colorspace *model = state->dest->colorspace;
+ fz_colorspace *prf = fz_proof_cs(ctx, devp);
fz_bound_shade(ctx, shade, &ctm, &bounds);
scissor = state->scissor;
@@ -1069,6 +1139,9 @@ fz_draw_fill_shade(fz_context *ctx, fz_device *devp, fz_shade *shade, const fz_m
if (fz_is_empty_irect(&bbox))
return;
+ if (color_params == NULL)
+ color_params = fz_default_color_params(ctx);
+
if (state->blendmode & FZ_BLEND_KNOCKOUT)
state = fz_knockout_begin(ctx, dev);
@@ -1096,7 +1169,7 @@ fz_draw_fill_shade(fz_context *ctx, fz_device *devp, fz_shade *shade, const fz_m
n = fz_colorspace_n(ctx, model);
if (n > 0)
{
- fz_convert_color(ctx, model, colorfv, shade->colorspace, shade->background);
+ fz_convert_color(ctx, color_params, prf, model, colorfv, fz_default_colorspace(ctx, dev->default_cs, shade->colorspace), shade->background);
for (i = 0; i < n; i++)
colorbv[i] = colorfv[i] * 255;
}
@@ -1127,7 +1200,7 @@ fz_draw_fill_shade(fz_context *ctx, fz_device *devp, fz_shade *shade, const fz_m
}
}
- fz_paint_shade(ctx, shade, &ctm, dest, &bbox);
+ fz_paint_shade(ctx, shade, &ctm, dest, prf, color_params, &bbox);
if (shape)
fz_clear_pixmap_rect_with_value(ctx, shape, 255, &bbox);
@@ -1219,7 +1292,7 @@ fz_default_image_scale(void *arg, int dst_w, int dst_h, int src_w, int src_h)
}
static void
-fz_draw_fill_image(fz_context *ctx, fz_device *devp, fz_image *image, const fz_matrix *in_ctm, float alpha)
+fz_draw_fill_image(fz_context *ctx, fz_device *devp, fz_image *image, const fz_matrix *in_ctm, float alpha, const fz_color_params *color_params)
{
fz_draw_device *dev = (fz_draw_device*)devp;
fz_matrix local_ctm = concat(in_ctm, &dev->transform);
@@ -1231,6 +1304,8 @@ fz_draw_fill_image(fz_context *ctx, fz_device *devp, fz_image *image, const fz_m
fz_irect clip;
fz_matrix inverse;
fz_irect src_area;
+ fz_colorspace *src_cs;
+ fz_colorspace *prf = fz_proof_cs(ctx, devp);
fz_intersect_irect(fz_pixmap_bbox(ctx, state->dest, &clip), &state->scissor);
@@ -1273,6 +1348,7 @@ fz_draw_fill_image(fz_context *ctx, fz_device *devp, fz_image *image, const fz_m
}
pixmap = fz_get_pixmap_from_image(ctx, image, &src_area, &local_ctm, &dx, &dy);
+ src_cs = fz_default_colorspace(ctx, dev->default_cs, pixmap->colorspace);
/* convert images with more components (cmyk->rgb) before scaling */
/* convert images with fewer components (gray->rgb) after scaling */
@@ -1286,12 +1362,12 @@ fz_draw_fill_image(fz_context *ctx, fz_device *devp, fz_image *image, const fz_m
state = fz_knockout_begin(ctx, dev);
after = 0;
- if (pixmap->colorspace == fz_device_gray(ctx))
+ if (src_cs == fz_device_gray(ctx))
after = 1;
- if (pixmap->colorspace != model && !after)
+ if (src_cs != model && !after)
{
- fz_pixmap *converted = fz_convert_pixmap(ctx, pixmap, model, 1);
+ fz_pixmap *converted = fz_convert_pixmap(ctx, pixmap, model, prf, dev->default_cs, color_params, 1);
fz_drop_pixmap(ctx, pixmap);
pixmap = converted;
}
@@ -1315,18 +1391,18 @@ fz_draw_fill_image(fz_context *ctx, fz_device *devp, fz_image *image, const fz_m
}
}
- if (pixmap->colorspace != model)
+ if (src_cs != model && after)
{
#if FZ_PLOTTERS_RGB
- if ((pixmap->colorspace == fz_device_gray(ctx) && model == fz_device_rgb(ctx)) ||
- (pixmap->colorspace == fz_device_gray(ctx) && model == fz_device_bgr(ctx)))
+ if ((src_cs == fz_device_gray(ctx) && model == fz_device_rgb(ctx)) ||
+ (src_cs == fz_device_gray(ctx) && model == fz_device_bgr(ctx)))
{
/* We have special case rendering code for gray -> rgb/bgr */
}
else
#endif
{
- fz_pixmap *converted = fz_convert_pixmap(ctx, pixmap, model, 1);
+ fz_pixmap *converted = fz_convert_pixmap(ctx, pixmap, model, prf, dev->default_cs, color_params, 1);
fz_drop_pixmap(ctx, pixmap);
pixmap = converted;
}
@@ -1345,7 +1421,7 @@ fz_draw_fill_image(fz_context *ctx, fz_device *devp, fz_image *image, const fz_m
static void
fz_draw_fill_image_mask(fz_context *ctx, fz_device *devp, fz_image *image, const fz_matrix *in_ctm,
- fz_colorspace *colorspace, const float *color, float alpha)
+ fz_colorspace *colorspace_in, const float *color, float alpha, const fz_color_params *color_params)
{
fz_draw_device *dev = (fz_draw_device*)devp;
fz_matrix local_ctm = concat(in_ctm, &dev->transform);
@@ -1360,6 +1436,14 @@ fz_draw_fill_image_mask(fz_context *ctx, fz_device *devp, fz_image *image, const
fz_irect clip;
fz_matrix inverse;
fz_irect src_area;
+ fz_colorspace *colorspace = NULL;
+ fz_colorspace *prf = fz_proof_cs(ctx, devp);
+
+ if (colorspace_in)
+ colorspace = fz_default_colorspace(ctx, dev->default_cs, colorspace_in);
+
+ if (color_params == NULL)
+ color_params = fz_default_color_params(ctx);
if (colorspace == NULL && model != NULL)
fz_throw(ctx, FZ_ERROR_GENERIC, "color destination requires source color");
@@ -1436,7 +1520,7 @@ fz_draw_fill_image_mask(fz_context *ctx, fz_device *devp, fz_image *image, const
n = fz_colorspace_n(ctx, model);
if (n > 0)
{
- fz_convert_color(ctx, model, colorfv, colorspace, color);
+ fz_convert_color(ctx, color_params, prf, model, colorfv, colorspace, color);
for (i = 0; i < n; i++)
colorbv[i] = colorfv[i] * 255;
}
@@ -1629,7 +1713,7 @@ fz_draw_pop_clip(fz_context *ctx, fz_device *devp)
}
static void
-fz_draw_begin_mask(fz_context *ctx, fz_device *devp, const fz_rect *rect, int luminosity, fz_colorspace *colorspace, const float *colorfv)
+fz_draw_begin_mask(fz_context *ctx, fz_device *devp, const fz_rect *rect, int luminosity, fz_colorspace *colorspace_in, const float *colorfv, const fz_color_params *color_params)
{
fz_draw_device *dev = (fz_draw_device*)devp;
fz_pixmap *dest;
@@ -1637,6 +1721,13 @@ fz_draw_begin_mask(fz_context *ctx, fz_device *devp, const fz_rect *rect, int lu
fz_draw_state *state = push_stack(ctx, dev);
fz_pixmap *shape = state->shape;
fz_rect trect = *rect;
+ fz_colorspace *colorspace = NULL;
+
+ if (colorspace_in)
+ colorspace = fz_default_colorspace(ctx, dev->default_cs, colorspace_in);
+
+ if (color_params == NULL)
+ color_params = fz_default_color_params(ctx);
STACK_PUSHED("mask");
fz_transform_rect(&trect, &dev->transform);
@@ -1671,7 +1762,7 @@ fz_draw_begin_mask(fz_context *ctx, fz_device *devp, const fz_rect *rect, int lu
float bc;
if (!colorspace)
colorspace = fz_device_gray(ctx);
- fz_convert_color(ctx, fz_device_gray(ctx), &bc, colorspace, colorfv);
+ fz_convert_color(ctx, color_params, NULL, fz_device_gray(ctx), &bc, colorspace, colorfv);
fz_clear_pixmap_with_value(ctx, dest, bc * 255);
if (shape)
fz_clear_pixmap_with_value(ctx, shape, 255);
@@ -2247,11 +2338,28 @@ fz_draw_end_tile(fz_context *ctx, fz_device *devp)
}
static void
+fz_draw_render_flags(fz_context *ctx, fz_device *devp, int set, int clear)
+{
+ fz_draw_device *dev = (fz_draw_device*)devp;
+ dev->flags = (dev->flags | set ) & ~clear;
+}
+
+static void
+fz_draw_set_default_colorspaces(fz_context *ctx, fz_device *devp, fz_default_colorspaces *default_cs)
+{
+ fz_draw_device *dev = (fz_draw_device*)devp;
+ fz_drop_default_colorspaces(ctx, dev->default_cs);
+ dev->default_cs = fz_keep_default_colorspaces(ctx, default_cs);
+}
+
+static void
fz_draw_drop_device(fz_context *ctx, fz_device *devp)
{
fz_draw_device *dev = (fz_draw_device*)devp;
fz_rasterizer *rast = dev->rast;
+ fz_drop_default_colorspaces(ctx, dev->default_cs);
+
/* pop and free the stacks */
if (dev->top > 0)
fz_warn(ctx, "items left on stack in draw device: %d", dev->top+1);
@@ -2277,14 +2385,6 @@ fz_draw_drop_device(fz_context *ctx, fz_device *devp)
fz_drop_rasterizer(ctx, rast);
}
-static void
-fz_draw_render_flags(fz_context *ctx, fz_device *devp, int set, int clear)
-{
- fz_draw_device *dev = (fz_draw_device*)devp;
-
- dev->flags = (dev->flags | set ) & ~clear;
-}
-
fz_device *
fz_new_draw_device(fz_context *ctx, const fz_matrix *transform, fz_pixmap *dest)
{
@@ -2319,6 +2419,7 @@ fz_new_draw_device(fz_context *ctx, const fz_matrix *transform, fz_pixmap *dest)
dev->super.end_tile = fz_draw_end_tile;
dev->super.render_flags = fz_draw_render_flags;
+ dev->super.set_default_colorspaces = fz_draw_set_default_colorspaces;
dev->transform = transform ? *transform : fz_identity;
dev->flags = 0;
diff --git a/source/fitz/draw-mesh.c b/source/fitz/draw-mesh.c
index a40cdd12..10091521 100644
--- a/source/fitz/draw-mesh.c
+++ b/source/fitz/draw-mesh.c
@@ -205,7 +205,7 @@ do_paint_tri(fz_context *ctx, void *arg, fz_vertex *av, fz_vertex *bv, fz_vertex
}
void
-fz_paint_shade(fz_context *ctx, fz_shade *shade, const fz_matrix *ctm, fz_pixmap *dest, const fz_irect *bbox)
+fz_paint_shade(fz_context *ctx, fz_shade *shade, const fz_matrix *ctm, fz_pixmap *dest, fz_colorspace *prf, const fz_color_params *color_params, const fz_irect *bbox)
{
unsigned char clut[256][FZ_MAX_COLORS];
fz_pixmap *temp = NULL;
@@ -227,7 +227,7 @@ fz_paint_shade(fz_context *ctx, fz_shade *shade, const fz_matrix *ctm, fz_pixmap
fz_color_converter cc;
int cn = fz_colorspace_n(ctx, shade->colorspace);
n = fz_colorspace_n(ctx, dest->colorspace);
- fz_lookup_color_converter(ctx, &cc, dest->colorspace, shade->colorspace);
+ fz_find_color_converter(ctx, &cc, prf, dest->colorspace, shade->colorspace, color_params);
for (i = 0; i < 256; i++)
{
cc.convert(ctx, &cc, color, shade->function[i]);
@@ -235,6 +235,7 @@ fz_paint_shade(fz_context *ctx, fz_shade *shade, const fz_matrix *ctm, fz_pixmap
clut[i][k] = color[k] * 255;
clut[i][k] = shade->function[i][cn] * 255;
}
+ fz_drop_color_converter(ctx, &cc);
/* We need to use alpha = 1 here, because the shade might not fill
* the bbox. */
conv = fz_new_pixmap_with_bbox(ctx, dest->colorspace, bbox, 1);
@@ -250,7 +251,7 @@ fz_paint_shade(fz_context *ctx, fz_shade *shade, const fz_matrix *ctm, fz_pixmap
ptd.shade = shade;
ptd.bbox = bbox;
- fz_init_cached_color_converter(ctx, &ptd.cc, temp->colorspace, shade->colorspace);
+ fz_init_cached_color_converter(ctx, &ptd.cc, NULL, temp->colorspace, shade->colorspace, color_params);
fz_process_shade(ctx, shade, &local_ctm, prepare_mesh_vertex, &do_paint_tri, &ptd);
if (shade->use_function)
diff --git a/source/fitz/fitz-imp.h b/source/fitz/fitz-imp.h
index d75e2242..23908a8d 100644
--- a/source/fitz/fitz-imp.h
+++ b/source/fitz/fitz-imp.h
@@ -13,6 +13,8 @@ struct fz_buffer_s
};
void fz_new_colorspace_context(fz_context *ctx);
+void fz_new_cmm_context(fz_context *ctx);
+void fz_drop_cmm_context(fz_context *ctx);
fz_colorspace_context *fz_keep_colorspace_context(fz_context *ctx);
void fz_drop_colorspace_context(fz_context *ctx);
diff --git a/source/fitz/icc34.h b/source/fitz/icc34.h
new file mode 100644
index 00000000..3b63abcf
--- /dev/null
+++ b/source/fitz/icc34.h
@@ -0,0 +1,1022 @@
+/* Header file guard bands */
+#ifndef ICC_H
+#define ICC_H
+
+/*****************************************************************
+ Copyright (c) 1994-1996 SunSoft, Inc.
+
+ Rights Reserved
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without restrict-
+ion, including without limitation the rights to use, copy, modify,
+merge, publish distribute, sublicense, and/or sell copies of the
+Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-
+INFRINGEMENT. IN NO EVENT SHALL SUNSOFT, INC. OR ITS PARENT
+COMPANY BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of SunSoft, Inc.
+shall not be used in advertising or otherwise to promote the
+sale, use or other dealings in this Software without written
+authorization from SunSoft Inc.
+******************************************************************/
+
+/*
+ * This version of the header file corresponds to the profile
+ * specification version 3.4.
+ *
+ * All header file entries are pre-fixed with "ic" to help
+ * avoid name space collisions. Signatures are pre-fixed with
+ * icSig.
+ *
+ * The structures defined in this header file were created to
+ * represent a description of an ICC profile on disk. Rather
+ * than use pointers a technique is used where a single byte array
+ * was placed at the end of each structure. This allows us in "C"
+ * to extend the structure by allocating more data than is needed
+ * to account for variable length structures.
+ *
+ * This also ensures that data following is allocated
+ * contiguously and makes it easier to write and read data from
+ * the file.
+ *
+ * For example to allocate space for a 256 count length UCR
+ * and BG array, and fill the allocated data. Note strlen + 1
+ * to remember NULL terminator.
+ *
+ icUcrBgCurve *ucrCurve, *bgCurve;
+ int ucr_nbytes, bg_nbytes, string_bytes;
+ icUcrBg *ucrBgWrite;
+ char ucr_string[100], *ucr_char;
+
+ strcpy(ucr_string, "Example ucrBG curves");
+ ucr_nbytes = sizeof(icUInt32Number) +
+ (UCR_CURVE_SIZE * sizeof(icUInt16Number));
+ bg_nbytes = sizeof(icUInt32Number) +
+ (BG_CURVE_SIZE * sizeof(icUInt16Number));
+ string_bytes = strlen(ucr_string) + 1;
+
+ ucrBgWrite = (icUcrBg *)malloc(
+ (ucr_nbytes + bg_nbytes + string_bytes));
+
+ ucrCurve = (icUcrBgCurve *)ucrBgWrite->data;
+ ucrCurve->count = UCR_CURVE_SIZE;
+ for (i=0; i<ucrCurve->count; i++)
+ ucrCurve->curve[i] = (icUInt16Number)i;
+
+ bgCurve = (icUcrBgCurve *)((char *)ucrCurve + ucr_nbytes);
+ bgCurve->count = BG_CURVE_SIZE;
+ for (i=0; i<bgCurve->count; i++)
+ bgCurve->curve[i] = 255 - (icUInt16Number)i;
+
+ ucr_char = (char *)((char *)bgCurve + bg_nbytes);
+ memcpy(ucr_char, ucr_string, string_bytes);
+ *
+ */
+
+/*
+ * Many of the structures contain variable length arrays. This
+ * is represented by the use of the convention.
+ *
+ * type data[icAny];
+ */
+
+/*------------------------------------------------------------------------*/
+/*
+ * Defines used in the specification
+ */
+#define icMagicNumber 0x61637370L /* 'acsp' */
+#define icVersionNumber 0x02100000L /* 2.1.0, BCD */
+
+/* Screening Encodings */
+#define icPrtrDefaultScreensFalse 0x00000000L /* Bit pos 0 */
+#define icPrtrDefaultScreensTrue 0x00000001L /* Bit pos 0 */
+#define icLinesPerInch 0x00000002L /* Bit pos 1 */
+#define icLinesPerCm 0x00000000L /* Bit pos 1 */
+
+/*
+ * Device attributes, currently defined values correspond
+ * to the low 4 bytes of the 8 byte attribute quantity, see
+ * the header for their location.
+ */
+#define icReflective 0x00000000L /* Bit pos 0 */
+#define icTransparency 0x00000001L /* Bit pos 0 */
+#define icGlossy 0x00000000L /* Bit pos 1 */
+#define icMatte 0x00000002L /* Bit pos 1 */
+
+/*
+ * Profile header flags, the low 16 bits are reserved for consortium
+ * use.
+ */
+#define icEmbeddedProfileFalse 0x00000000L /* Bit pos 0 */
+#define icEmbeddedProfileTrue 0x00000001L /* Bit pos 0 */
+#define icUseAnywhere 0x00000000L /* Bit pos 1 */
+#define icUseWithEmbeddedDataOnly 0x00000002L /* Bit pos 1 */
+
+/* Ascii or Binary data */
+#define icAsciiData 0x00000000L
+#define icBinaryData 0x00000001L
+
+/*
+ * Define used to indicate that this is a variable length array
+ */
+#define icAny 1
+
+
+/*------------------------------------------------------------------------*/
+/*
+ * Use this area to translate platform definitions of long
+ * etc into icXXX form. The rest of the header uses the icXXX
+ * typedefs. Signatures are 4 byte quantities.
+ *
+ */
+
+
+#ifdef PACKAGE_NAME
+/*
+ June 9, 2003, Adapted for use with configure by Bob Friesenhahn
+ Added the stupid check for autoconf by Marti Maria.
+ PACKAGE_NAME is defined if autoconf is being used
+*/
+
+typedef @UINT8_T@ icUInt8Number;
+typedef @UINT16_T@ icUInt16Number;
+typedef @UINT32_T@ icUInt32Number;
+typedef @UINT32_T@ icUInt64Number[2];
+
+typedef @INT8_T@ icInt8Number;
+typedef @INT16_T@ icInt16Number;
+typedef @INT32_T@ icInt32Number;
+typedef @INT32_T@ icInt64Number[2];
+
+#elif defined (__digital__) && defined (__unix__)
+
+/*
+ *Apr-17-2002: Modified by Marti Maria in order to provide wider portability.
+ */
+
+/* Tru64 */
+
+#include <inttypes.h>
+
+typedef uint8_t icUInt8Number;
+typedef uint16_t icUInt16Number;
+typedef uint32_t icUInt32Number;
+typedef uint32_t icUInt64Number[2];
+
+typedef int8_t icInt8Number;
+typedef int16_t icInt16Number;
+typedef int32_t icInt32Number;
+typedef int32_t icInt64Number[2];
+
+#elif defined(__sgi)
+#include "sgidefs.h"
+
+
+/*
+ * Number definitions
+ */
+
+/* Unsigned integer numbers */
+typedef unsigned char icUInt8Number;
+typedef unsigned short icUInt16Number;
+typedef __uint32_t icUInt32Number;
+typedef __uint32_t icUInt64Number[2];
+
+/* Signed numbers */
+typedef char icInt8Number;
+typedef short icInt16Number;
+typedef __int32_t icInt32Number;
+typedef __int32_t icInt64Number[2];
+
+
+#elif defined(__GNUC__) || defined(__unix__) || defined(__unix)
+
+#include <sys/types.h>
+
+#if defined(__sun) || defined(__hpux) || defined (__MINGW) || defined(__MINGW32__) || defined(HAVE_STDINT_H)
+
+#if defined (__MINGW) || defined(__MINGW32__) || defined(HAVE_STDINT_H)
+#include <stdint.h>
+#endif
+
+
+typedef uint8_t icUInt8Number;
+typedef uint16_t icUInt16Number;
+typedef uint32_t icUInt32Number;
+typedef uint32_t icUInt64Number[2];
+
+#else
+
+/* Unsigned integer numbers */
+typedef u_int8_t icUInt8Number;
+typedef u_int16_t icUInt16Number;
+typedef u_int32_t icUInt32Number;
+typedef u_int32_t icUInt64Number[2];
+
+#endif /* defined(__sun) || defined(__hpux) || defined (__MINGW) || defined(__MINGW32__) || defined(HAVE_STDINT_H) */
+
+
+/* Signed numbers */
+typedef int8_t icInt8Number;
+typedef int16_t icInt16Number;
+typedef int32_t icInt32Number;
+typedef int32_t icInt64Number[2];
+
+
+#else /* default definitions */
+
+/*
+ * Number definitions
+ */
+
+/* Unsigned integer numbers */
+typedef unsigned char icUInt8Number;
+typedef unsigned short icUInt16Number;
+typedef unsigned long icUInt32Number;
+typedef unsigned long icUInt64Number[2];
+
+/* Signed numbers */
+typedef char icInt8Number;
+typedef short icInt16Number;
+typedef long icInt32Number;
+typedef long icInt64Number[2];
+
+
+#endif /* default defs */
+
+/* Base types */
+
+typedef icInt32Number icSignature;
+typedef icInt32Number icS15Fixed16Number;
+typedef icUInt32Number icU16Fixed16Number;
+
+
+/*------------------------------------------------------------------------*/
+/* public tags and sizes */
+typedef enum {
+ icSigAToB0Tag = 0x41324230L, /* 'A2B0' */
+ icSigAToB1Tag = 0x41324231L, /* 'A2B1' */
+ icSigAToB2Tag = 0x41324232L, /* 'A2B2' */
+ icSigBlueColorantTag = 0x6258595AL, /* 'bXYZ' */
+ icSigBlueTRCTag = 0x62545243L, /* 'bTRC' */
+ icSigBToA0Tag = 0x42324130L, /* 'B2A0' */
+ icSigBToA1Tag = 0x42324131L, /* 'B2A1' */
+ icSigBToA2Tag = 0x42324132L, /* 'B2A2' */
+ icSigCalibrationDateTimeTag = 0x63616C74L, /* 'calt' */
+ icSigCharTargetTag = 0x74617267L, /* 'targ' */
+ icSigCopyrightTag = 0x63707274L, /* 'cprt' */
+ icSigCrdInfoTag = 0x63726469L, /* 'crdi' */
+ icSigDeviceMfgDescTag = 0x646D6E64L, /* 'dmnd' */
+ icSigDeviceModelDescTag = 0x646D6464L, /* 'dmdd' */
+ icSigGamutTag = 0x67616D74L, /* 'gamt ' */
+ icSigGrayTRCTag = 0x6b545243L, /* 'kTRC' */
+ icSigGreenColorantTag = 0x6758595AL, /* 'gXYZ' */
+ icSigGreenTRCTag = 0x67545243L, /* 'gTRC' */
+ icSigLuminanceTag = 0x6C756d69L, /* 'lumi' */
+ icSigMeasurementTag = 0x6D656173L, /* 'meas' */
+ icSigMediaBlackPointTag = 0x626B7074L, /* 'bkpt' */
+ icSigMediaWhitePointTag = 0x77747074L, /* 'wtpt' */
+ icSigNamedColorTag = 0x6E636f6CL, /* 'ncol'
+ * OBSOLETE, use ncl2 */
+ icSigNamedColor2Tag = 0x6E636C32L, /* 'ncl2' */
+ icSigPreview0Tag = 0x70726530L, /* 'pre0' */
+ icSigPreview1Tag = 0x70726531L, /* 'pre1' */
+ icSigPreview2Tag = 0x70726532L, /* 'pre2' */
+ icSigProfileDescriptionTag = 0x64657363L, /* 'desc' */
+ icSigProfileSequenceDescTag = 0x70736571L, /* 'pseq' */
+ icSigPs2CRD0Tag = 0x70736430L, /* 'psd0' */
+ icSigPs2CRD1Tag = 0x70736431L, /* 'psd1' */
+ icSigPs2CRD2Tag = 0x70736432L, /* 'psd2' */
+ icSigPs2CRD3Tag = 0x70736433L, /* 'psd3' */
+ icSigPs2CSATag = 0x70733273L, /* 'ps2s' */
+ icSigPs2RenderingIntentTag = 0x70733269L, /* 'ps2i' */
+ icSigRedColorantTag = 0x7258595AL, /* 'rXYZ' */
+ icSigRedTRCTag = 0x72545243L, /* 'rTRC' */
+ icSigScreeningDescTag = 0x73637264L, /* 'scrd' */
+ icSigScreeningTag = 0x7363726EL, /* 'scrn' */
+ icSigTechnologyTag = 0x74656368L, /* 'tech' */
+ icSigUcrBgTag = 0x62666420L, /* 'bfd ' */
+ icSigViewingCondDescTag = 0x76756564L, /* 'vued' */
+ icSigViewingConditionsTag = 0x76696577L, /* 'view' */
+ icMaxEnumTag = 0xFFFFFFFFL
+} icTagSignature;
+
+/* technology signature descriptions */
+typedef enum {
+ icSigDigitalCamera = 0x6463616DL, /* 'dcam' */
+ icSigFilmScanner = 0x6673636EL, /* 'fscn' */
+ icSigReflectiveScanner = 0x7273636EL, /* 'rscn' */
+ icSigInkJetPrinter = 0x696A6574L, /* 'ijet' */
+ icSigThermalWaxPrinter = 0x74776178L, /* 'twax' */
+ icSigElectrophotographicPrinter = 0x6570686FL, /* 'epho' */
+ icSigElectrostaticPrinter = 0x65737461L, /* 'esta' */
+ icSigDyeSublimationPrinter = 0x64737562L, /* 'dsub' */
+ icSigPhotographicPaperPrinter = 0x7270686FL, /* 'rpho' */
+ icSigFilmWriter = 0x6670726EL, /* 'fprn' */
+ icSigVideoMonitor = 0x7669646DL, /* 'vidm' */
+ icSigVideoCamera = 0x76696463L, /* 'vidc' */
+ icSigProjectionTelevision = 0x706A7476L, /* 'pjtv' */
+ icSigCRTDisplay = 0x43525420L, /* 'CRT ' */
+ icSigPMDisplay = 0x504D4420L, /* 'PMD ' */
+ icSigAMDisplay = 0x414D4420L, /* 'AMD ' */
+ icSigPhotoCD = 0x4B504344L, /* 'KPCD' */
+ icSigPhotoImageSetter = 0x696D6773L, /* 'imgs' */
+ icSigGravure = 0x67726176L, /* 'grav' */
+ icSigOffsetLithography = 0x6F666673L, /* 'offs' */
+ icSigSilkscreen = 0x73696C6BL, /* 'silk' */
+ icSigFlexography = 0x666C6578L, /* 'flex' */
+ icMaxEnumTechnology = 0xFFFFFFFFL
+} icTechnologySignature;
+
+/* type signatures */
+typedef enum {
+ icSigCurveType = 0x63757276L, /* 'curv' */
+ icSigDataType = 0x64617461L, /* 'data' */
+ icSigDateTimeType = 0x6474696DL, /* 'dtim' */
+ icSigLut16Type = 0x6d667432L, /* 'mft2' */
+ icSigLut8Type = 0x6d667431L, /* 'mft1' */
+ icSigMeasurementType = 0x6D656173L, /* 'meas' */
+ icSigNamedColorType = 0x6E636f6CL, /* 'ncol'
+ * OBSOLETE, use ncl2 */
+ icSigProfileSequenceDescType = 0x70736571L, /* 'pseq' */
+ icSigS15Fixed16ArrayType = 0x73663332L, /* 'sf32' */
+ icSigScreeningType = 0x7363726EL, /* 'scrn' */
+ icSigSignatureType = 0x73696720L, /* 'sig ' */
+ icSigTextType = 0x74657874L, /* 'text' */
+ icSigTextDescriptionType = 0x64657363L, /* 'desc' */
+ icSigU16Fixed16ArrayType = 0x75663332L, /* 'uf32' */
+ icSigUcrBgType = 0x62666420L, /* 'bfd ' */
+ icSigUInt16ArrayType = 0x75693136L, /* 'ui16' */
+ icSigUInt32ArrayType = 0x75693332L, /* 'ui32' */
+ icSigUInt64ArrayType = 0x75693634L, /* 'ui64' */
+ icSigUInt8ArrayType = 0x75693038L, /* 'ui08' */
+ icSigViewingConditionsType = 0x76696577L, /* 'view' */
+ icSigXYZType = 0x58595A20L, /* 'XYZ ' */
+ icSigXYZArrayType = 0x58595A20L, /* 'XYZ ' */
+ icSigNamedColor2Type = 0x6E636C32L, /* 'ncl2' */
+ icSigCrdInfoType = 0x63726469L, /* 'crdi' */
+ icMaxEnumType = 0xFFFFFFFFL
+} icTagTypeSignature;
+
+/*
+ * Color Space Signatures
+ * Note that only icSigXYZData and icSigLabData are valid
+ * Profile Connection Spaces (PCSs)
+ */
+typedef enum {
+ icSigXYZData = 0x58595A20L, /* 'XYZ ' */
+ icSigLabData = 0x4C616220L, /* 'Lab ' */
+ icSigLuvData = 0x4C757620L, /* 'Luv ' */
+ icSigYCbCrData = 0x59436272L, /* 'YCbr' */
+ icSigYxyData = 0x59787920L, /* 'Yxy ' */
+ icSigRgbData = 0x52474220L, /* 'RGB ' */
+ icSigGrayData = 0x47524159L, /* 'GRAY' */
+ icSigHsvData = 0x48535620L, /* 'HSV ' */
+ icSigHlsData = 0x484C5320L, /* 'HLS ' */
+ icSigCmykData = 0x434D594BL, /* 'CMYK' */
+ icSigCmyData = 0x434D5920L, /* 'CMY ' */
+ icSig2colorData = 0x32434C52L, /* '2CLR' */
+ icSig3colorData = 0x33434C52L, /* '3CLR' */
+ icSig4colorData = 0x34434C52L, /* '4CLR' */
+ icSig5colorData = 0x35434C52L, /* '5CLR' */
+ icSig6colorData = 0x36434C52L, /* '6CLR' */
+ icSig7colorData = 0x37434C52L, /* '7CLR' */
+ icSig8colorData = 0x38434C52L, /* '8CLR' */
+ icSig9colorData = 0x39434C52L, /* '9CLR' */
+ icSig10colorData = 0x41434C52L, /* 'ACLR' */
+ icSig11colorData = 0x42434C52L, /* 'BCLR' */
+ icSig12colorData = 0x43434C52L, /* 'CCLR' */
+ icSig13colorData = 0x44434C52L, /* 'DCLR' */
+ icSig14colorData = 0x45434C52L, /* 'ECLR' */
+ icSig15colorData = 0x46434C52L, /* 'FCLR' */
+ icMaxEnumData = 0xFFFFFFFFL
+} icColorSpaceSignature;
+
+/* profileClass enumerations */
+typedef enum {
+ icSigInputClass = 0x73636E72L, /* 'scnr' */
+ icSigDisplayClass = 0x6D6E7472L, /* 'mntr' */
+ icSigOutputClass = 0x70727472L, /* 'prtr' */
+ icSigLinkClass = 0x6C696E6BL, /* 'link' */
+ icSigAbstractClass = 0x61627374L, /* 'abst' */
+ icSigColorSpaceClass = 0x73706163L, /* 'spac' */
+ icSigNamedColorClass = 0x6e6d636cL, /* 'nmcl' */
+ icMaxEnumClass = 0xFFFFFFFFL
+} icProfileClassSignature;
+
+/* Platform Signatures */
+typedef enum {
+ icSigMacintosh = 0x4150504CL, /* 'APPL' */
+ icSigMicrosoft = 0x4D534654L, /* 'MSFT' */
+ icSigSolaris = 0x53554E57L, /* 'SUNW' */
+ icSigSGI = 0x53474920L, /* 'SGI ' */
+ icSigTaligent = 0x54474E54L, /* 'TGNT' */
+ icMaxEnumPlatform = 0xFFFFFFFFL
+} icPlatformSignature;
+
+/*------------------------------------------------------------------------*/
+/*
+ * Other enums
+ */
+
+/* Measurement Flare, used in the measurmentType tag */
+typedef enum {
+ icFlare0 = 0x00000000L, /* 0% flare */
+ icFlare100 = 0x00000001L, /* 100% flare */
+ icMaxFlare = 0xFFFFFFFFL
+} icMeasurementFlare;
+
+/* Measurement Geometry, used in the measurmentType tag */
+typedef enum {
+ icGeometryUnknown = 0x00000000L, /* Unknown */
+ icGeometry045or450 = 0x00000001L, /* 0/45, 45/0 */
+ icGeometry0dord0 = 0x00000002L, /* 0/d or d/0 */
+ icMaxGeometry = 0xFFFFFFFFL
+} icMeasurementGeometry;
+
+/* Rendering Intents, used in the profile header */
+typedef enum {
+ icPerceptual = 0,
+ icRelativeColorimetric = 1,
+ icSaturation = 2,
+ icAbsoluteColorimetric = 3,
+ icMaxEnumIntent = 0xFFFFFFFFL
+} icRenderingIntent;
+
+/* Different Spot Shapes currently defined, used for screeningType */
+typedef enum {
+ icSpotShapeUnknown = 0,
+ icSpotShapePrinterDefault = 1,
+ icSpotShapeRound = 2,
+ icSpotShapeDiamond = 3,
+ icSpotShapeEllipse = 4,
+ icSpotShapeLine = 5,
+ icSpotShapeSquare = 6,
+ icSpotShapeCross = 7,
+ icMaxEnumSpot = 0xFFFFFFFFL
+} icSpotShape;
+
+/* Standard Observer, used in the measurmentType tag */
+typedef enum {
+ icStdObsUnknown = 0x00000000L, /* Unknown */
+ icStdObs1931TwoDegrees = 0x00000001L, /* 2 deg */
+ icStdObs1964TenDegrees = 0x00000002L, /* 10 deg */
+ icMaxStdObs = 0xFFFFFFFFL
+} icStandardObserver;
+
+/* Pre-defined illuminants, used in measurement and viewing conditions type */
+typedef enum {
+ icIlluminantUnknown = 0x00000000L,
+ icIlluminantD50 = 0x00000001L,
+ icIlluminantD65 = 0x00000002L,
+ icIlluminantD93 = 0x00000003L,
+ icIlluminantF2 = 0x00000004L,
+ icIlluminantD55 = 0x00000005L,
+ icIlluminantA = 0x00000006L,
+ icIlluminantEquiPowerE = 0x00000007L,
+ icIlluminantF8 = 0x00000008L,
+ icMaxEnumIluminant = 0xFFFFFFFFL
+} icIlluminant;
+
+
+/*------------------------------------------------------------------------*/
+/*
+ * Arrays of numbers
+ */
+
+/* Int8 Array */
+typedef struct {
+ icInt8Number data[icAny]; /* Variable array of values */
+} icInt8Array;
+
+/* UInt8 Array */
+typedef struct {
+ icUInt8Number data[icAny]; /* Variable array of values */
+} icUInt8Array;
+
+/* uInt16 Array */
+typedef struct {
+ icUInt16Number data[icAny]; /* Variable array of values */
+} icUInt16Array;
+
+/* Int16 Array */
+typedef struct {
+ icInt16Number data[icAny]; /* Variable array of values */
+} icInt16Array;
+
+/* uInt32 Array */
+typedef struct {
+ icUInt32Number data[icAny]; /* Variable array of values */
+} icUInt32Array;
+
+/* Int32 Array */
+typedef struct {
+ icInt32Number data[icAny]; /* Variable array of values */
+} icInt32Array;
+
+/* UInt64 Array */
+typedef struct {
+ icUInt64Number data[icAny]; /* Variable array of values */
+} icUInt64Array;
+
+/* Int64 Array */
+typedef struct {
+ icInt64Number data[icAny]; /* Variable array of values */
+} icInt64Array;
+
+/* u16Fixed16 Array */
+typedef struct {
+ icU16Fixed16Number data[icAny]; /* Variable array of values */
+} icU16Fixed16Array;
+
+/* s15Fixed16 Array */
+typedef struct {
+ icS15Fixed16Number data[icAny]; /* Variable array of values */
+} icS15Fixed16Array;
+
+/* The base date time number */
+typedef struct {
+ icUInt16Number year;
+ icUInt16Number month;
+ icUInt16Number day;
+ icUInt16Number hours;
+ icUInt16Number minutes;
+ icUInt16Number seconds;
+} icDateTimeNumber;
+
+/* XYZ Number */
+typedef struct {
+ icS15Fixed16Number X;
+ icS15Fixed16Number Y;
+ icS15Fixed16Number Z;
+} icXYZNumber;
+
+/* XYZ Array */
+typedef struct {
+ icXYZNumber data[icAny]; /* Variable array of XYZ numbers */
+} icXYZArray;
+
+/* Curve */
+typedef struct {
+ icUInt32Number count; /* Number of entries */
+ icUInt16Number data[icAny]; /* The actual table data, real
+ * number is determined by count
+ * Interpretation depends on how
+ * data is used with a given tag
+ */
+} icCurve;
+
+/* Data */
+typedef struct {
+ icUInt32Number dataFlag; /* 0 = ascii, 1 = binary */
+ icInt8Number data[icAny]; /* Data, size from tag */
+} icData;
+
+/* lut16 */
+typedef struct {
+ icUInt8Number inputChan; /* Number of input channels */
+ icUInt8Number outputChan; /* Number of output channels */
+ icUInt8Number clutPoints; /* Number of grid points */
+ icInt8Number pad; /* Padding for byte alignment */
+ icS15Fixed16Number e00; /* e00 in the 3 * 3 */
+ icS15Fixed16Number e01; /* e01 in the 3 * 3 */
+ icS15Fixed16Number e02; /* e02 in the 3 * 3 */
+ icS15Fixed16Number e10; /* e10 in the 3 * 3 */
+ icS15Fixed16Number e11; /* e11 in the 3 * 3 */
+ icS15Fixed16Number e12; /* e12 in the 3 * 3 */
+ icS15Fixed16Number e20; /* e20 in the 3 * 3 */
+ icS15Fixed16Number e21; /* e21 in the 3 * 3 */
+ icS15Fixed16Number e22; /* e22 in the 3 * 3 */
+ icUInt16Number inputEnt; /* Num of in-table entries */
+ icUInt16Number outputEnt; /* Num of out-table entries */
+ icUInt16Number data[icAny]; /* Data follows see spec */
+/*
+ * Data that follows is of this form
+ *
+ * icUInt16Number inputTable[inputChan][icAny]; * The in-table
+ * icUInt16Number clutTable[icAny]; * The clut
+ * icUInt16Number outputTable[outputChan][icAny]; * The out-table
+ */
+} icLut16;
+
+/* lut8, input & output tables are always 256 bytes in length */
+typedef struct {
+ icUInt8Number inputChan; /* Num of input channels */
+ icUInt8Number outputChan; /* Num of output channels */
+ icUInt8Number clutPoints; /* Num of grid points */
+ icInt8Number pad;
+ icS15Fixed16Number e00; /* e00 in the 3 * 3 */
+ icS15Fixed16Number e01; /* e01 in the 3 * 3 */
+ icS15Fixed16Number e02; /* e02 in the 3 * 3 */
+ icS15Fixed16Number e10; /* e10 in the 3 * 3 */
+ icS15Fixed16Number e11; /* e11 in the 3 * 3 */
+ icS15Fixed16Number e12; /* e12 in the 3 * 3 */
+ icS15Fixed16Number e20; /* e20 in the 3 * 3 */
+ icS15Fixed16Number e21; /* e21 in the 3 * 3 */
+ icS15Fixed16Number e22; /* e22 in the 3 * 3 */
+ icUInt8Number data[icAny]; /* Data follows see spec */
+/*
+ * Data that follows is of this form
+ *
+ * icUInt8Number inputTable[inputChan][256]; * The in-table
+ * icUInt8Number clutTable[icAny]; * The clut
+ * icUInt8Number outputTable[outputChan][256]; * The out-table
+ */
+} icLut8;
+
+/* Measurement Data */
+typedef struct {
+ icStandardObserver stdObserver; /* Standard observer */
+ icXYZNumber backing; /* XYZ for backing */
+ icMeasurementGeometry geometry; /* Meas. geometry */
+ icMeasurementFlare flare; /* Measurement flare */
+ icIlluminant illuminant; /* Illuminant */
+} icMeasurement;
+
+/* Named color */
+
+/*
+ * icNamedColor2 takes the place of icNamedColor
+ */
+typedef struct {
+ icUInt32Number vendorFlag; /* Bottom 16 bits for IC use */
+ icUInt32Number count; /* Count of named colors */
+ icUInt32Number nDeviceCoords; /* Num of device coordinates */
+ icInt8Number prefix[32]; /* Prefix for each color name */
+ icInt8Number suffix[32]; /* Suffix for each color name */
+ icInt8Number data[icAny]; /* Named color data follows */
+/*
+ * Data that follows is of this form
+ *
+ * icInt8Number root1[32]; * Root name for 1st color
+ * icUInt16Number pcsCoords1[icAny]; * PCS coords of 1st color
+ * icUInt16Number deviceCoords1[icAny]; * Dev coords of 1st color
+ * icInt8Number root2[32]; * Root name for 2nd color
+ * icUInt16Number pcsCoords2[icAny]; * PCS coords of 2nd color
+ * icUInt16Number deviceCoords2[icAny]; * Dev coords of 2nd color
+ * :
+ * :
+ * Repeat for name and PCS and device color coordinates up to (count-1)
+ *
+ * NOTES:
+ * PCS and device space can be determined from the header.
+ *
+ * PCS coordinates are icUInt16 numbers and are described in Annex A of
+ * the ICC spec. Only 16 bit L*a*b* and XYZ are allowed. The number of
+ * coordinates is consistent with the headers PCS.
+ *
+ * Device coordinates are icUInt16 numbers where 0x0000 represents
+ * the minimum value and 0xFFFF represents the maximum value.
+ * If the nDeviceCoords value is 0 this field is not given.
+ */
+} icNamedColor2;
+
+/* Profile sequence structure */
+typedef struct {
+ icSignature deviceMfg; /* Dev Manufacturer */
+ icSignature deviceModel; /* Dev Model */
+ icUInt64Number attributes; /* Dev attributes */
+ icTechnologySignature technology; /* Technology sig */
+ icInt8Number data[icAny]; /* Desc text follows */
+/*
+ * Data that follows is of this form, this is an icInt8Number
+ * to avoid problems with a compiler generating bad code as
+ * these arrays are variable in length.
+ *
+ * icTextDescription deviceMfgDesc; * Manufacturer text
+ * icTextDescription modelDesc; * Model text
+ */
+} icDescStruct;
+
+/* Profile sequence description */
+typedef struct {
+ icUInt32Number count; /* Number of descriptions */
+ icUInt8Number data[icAny]; /* Array of desc structs */
+} icProfileSequenceDesc;
+
+/* textDescription */
+typedef struct {
+ icUInt32Number count; /* Description length */
+ icInt8Number data[icAny]; /* Descriptions follow */
+/*
+ * Data that follows is of this form
+ *
+ * icInt8Number desc[count] * NULL terminated ascii string
+ * icUInt32Number ucLangCode; * UniCode language code
+ * icUInt32Number ucCount; * UniCode description length
+ * icInt16Number ucDesc[ucCount];* The UniCode description
+ * icUInt16Number scCode; * ScriptCode code
+ * icUInt8Number scCount; * ScriptCode count
+ * icInt8Number scDesc[67]; * ScriptCode Description
+ */
+} icTextDescription;
+
+/* Screening Data */
+typedef struct {
+ icS15Fixed16Number frequency; /* Frequency */
+ icS15Fixed16Number angle; /* Screen angle */
+ icSpotShape spotShape; /* Spot Shape encodings below */
+} icScreeningData;
+
+typedef struct {
+ icUInt32Number screeningFlag; /* Screening flag */
+ icUInt32Number channels; /* Number of channels */
+ icScreeningData data[icAny]; /* Array of screening data */
+} icScreening;
+
+/* Text Data */
+typedef struct {
+ icInt8Number data[icAny]; /* Variable array of chars */
+} icText;
+
+/* Structure describing either a UCR or BG curve */
+typedef struct {
+ icUInt32Number count; /* Curve length */
+ icUInt16Number curve[icAny]; /* The array of curve values */
+} icUcrBgCurve;
+
+/* Under color removal, black generation */
+typedef struct {
+ icInt8Number data[icAny]; /* The Ucr BG data */
+/*
+ * Data that follows is of this form, this is a icInt8Number
+ * to avoid problems with a compiler generating bad code as
+ * these arrays are variable in length.
+ *
+ * icUcrBgCurve ucr; * Ucr curve
+ * icUcrBgCurve bg; * Bg curve
+ * icInt8Number string; * UcrBg description
+ */
+} icUcrBg;
+
+/* viewingConditionsType */
+typedef struct {
+ icXYZNumber illuminant; /* In candelas per sq. meter */
+ icXYZNumber surround; /* In candelas per sq. meter */
+ icIlluminant stdIluminant; /* See icIlluminant defines */
+} icViewingCondition;
+
+/* CrdInfo type */
+typedef struct {
+ icUInt32Number count; /* Char count includes NULL */
+ icInt8Number desc[icAny]; /* Null terminated string */
+} icCrdInfo;
+
+/*------------------------------------------------------------------------*/
+/*
+ * Tag Type definitions
+ */
+
+/*
+ * Many of the structures contain variable length arrays. This
+ * is represented by the use of the convention.
+ *
+ * type data[icAny];
+ */
+
+/* The base part of each tag */
+typedef struct {
+ icTagTypeSignature sig; /* Signature */
+ icInt8Number reserved[4]; /* Reserved, set to 0 */
+} icTagBase;
+
+/* curveType */
+typedef struct {
+ icTagBase base; /* Signature, "curv" */
+ icCurve curve; /* The curve data */
+} icCurveType;
+
+/* dataType */
+typedef struct {
+ icTagBase base; /* Signature, "data" */
+ icData data; /* The data structure */
+} icDataType;
+
+/* dateTimeType */
+typedef struct {
+ icTagBase base; /* Signature, "dtim" */
+ icDateTimeNumber date; /* The date */
+} icDateTimeType;
+
+/* lut16Type */
+typedef struct {
+ icTagBase base; /* Signature, "mft2" */
+ icLut16 lut; /* Lut16 data */
+} icLut16Type;
+
+/* lut8Type, input & output tables are always 256 bytes in length */
+typedef struct {
+ icTagBase base; /* Signature, "mft1" */
+ icLut8 lut; /* Lut8 data */
+} icLut8Type;
+
+/* Measurement Type */
+typedef struct {
+ icTagBase base; /* Signature, "meas" */
+ icMeasurement measurement; /* Measurement data */
+} icMeasurementType;
+
+/* Named color type */
+/* icNamedColor2Type, replaces icNamedColorType */
+typedef struct {
+ icTagBase base; /* Signature, "ncl2" */
+ icNamedColor2 ncolor; /* Named color data */
+} icNamedColor2Type;
+
+/* Profile sequence description type */
+typedef struct {
+ icTagBase base; /* Signature, "pseq" */
+ icProfileSequenceDesc desc; /* The seq description */
+} icProfileSequenceDescType;
+
+/* textDescriptionType */
+typedef struct {
+ icTagBase base; /* Signature, "desc" */
+ icTextDescription desc; /* The description */
+} icTextDescriptionType;
+
+/* s15Fixed16Type */
+typedef struct {
+ icTagBase base; /* Signature, "sf32" */
+ icS15Fixed16Array data; /* Array of values */
+} icS15Fixed16ArrayType;
+
+typedef struct {
+ icTagBase base; /* Signature, "scrn" */
+ icScreening screen; /* Screening structure */
+} icScreeningType;
+
+/* sigType */
+typedef struct {
+ icTagBase base; /* Signature, "sig" */
+ icSignature signature; /* The signature data */
+} icSignatureType;
+
+/* textType */
+typedef struct {
+ icTagBase base; /* Signature, "text" */
+ icText data; /* Variable array of chars */
+} icTextType;
+
+/* u16Fixed16Type */
+typedef struct {
+ icTagBase base; /* Signature, "uf32" */
+ icU16Fixed16Array data; /* Variable array of values */
+} icU16Fixed16ArrayType;
+
+/* Under color removal, black generation type */
+typedef struct {
+ icTagBase base; /* Signature, "bfd " */
+ icUcrBg data; /* ucrBg structure */
+} icUcrBgType;
+
+/* uInt16Type */
+typedef struct {
+ icTagBase base; /* Signature, "ui16" */
+ icUInt16Array data; /* Variable array of values */
+} icUInt16ArrayType;
+
+/* uInt32Type */
+typedef struct {
+ icTagBase base; /* Signature, "ui32" */
+ icUInt32Array data; /* Variable array of values */
+} icUInt32ArrayType;
+
+/* uInt64Type */
+typedef struct {
+ icTagBase base; /* Signature, "ui64" */
+ icUInt64Array data; /* Variable array of values */
+} icUInt64ArrayType;
+
+/* uInt8Type */
+typedef struct {
+ icTagBase base; /* Signature, "ui08" */
+ icUInt8Array data; /* Variable array of values */
+} icUInt8ArrayType;
+
+/* viewingConditionsType */
+typedef struct {
+ icTagBase base; /* Signature, "view" */
+ icViewingCondition view; /* Viewing conditions */
+} icViewingConditionType;
+
+/* XYZ Type */
+typedef struct {
+ icTagBase base; /* Signature, "XYZ" */
+ icXYZArray data; /* Variable array of XYZ nums */
+} icXYZType;
+
+/* CRDInfoType where [0] is the CRD product name count and string and
+ * [1] -[5] are the rendering intents 0-4 counts and strings
+ */
+typedef struct {
+ icTagBase base; /* Signature, "crdi" */
+ icCrdInfo info; /* 5 sets of counts & strings */
+}icCrdInfoType;
+ /* icCrdInfo productName; PS product count/string */
+ /* icCrdInfo CRDName0; CRD name for intent 0 */
+ /* icCrdInfo CRDName1; CRD name for intent 1 */
+ /* icCrdInfo CRDName2; CRD name for intent 2 */
+ /* icCrdInfo CRDName3; CRD name for intent 3 */
+
+/*------------------------------------------------------------------------*/
+
+/*
+ * Lists of tags, tags, profile header and profile structure
+ */
+
+/* A tag */
+typedef struct {
+ icTagSignature sig; /* The tag signature */
+ icUInt32Number offset; /* Start of tag relative to
+ * start of header, Spec
+ * Clause 5 */
+ icUInt32Number size; /* Size in bytes */
+} icTag;
+
+/* A Structure that may be used independently for a list of tags */
+typedef struct {
+ icUInt32Number count; /* Num tags in the profile */
+ icTag tags[icAny]; /* Variable array of tags */
+} icTagList;
+
+/* The Profile header */
+typedef struct {
+ icUInt32Number size; /* Prof size in bytes */
+ icSignature cmmId; /* CMM for profile */
+ icUInt32Number version; /* Format version */
+ icProfileClassSignature deviceClass; /* Type of profile */
+ icColorSpaceSignature colorSpace; /* Clr space of data */
+ icColorSpaceSignature pcs; /* PCS, XYZ or Lab */
+ icDateTimeNumber date; /* Creation Date */
+ icSignature magic; /* icMagicNumber */
+ icPlatformSignature platform; /* Primary Platform */
+ icUInt32Number flags; /* Various bits */
+ icSignature manufacturer; /* Dev manufacturer */
+ icUInt32Number model; /* Dev model number */
+ icUInt64Number attributes; /* Device attributes */
+ icUInt32Number renderingIntent;/* Rendering intent */
+ icXYZNumber illuminant; /* Profile illuminant */
+ icSignature creator; /* Profile creator */
+ icInt8Number reserved[44]; /* Reserved */
+} icHeader;
+
+/*
+ * A profile,
+ * we can't use icTagList here because its not at the end of the structure
+ */
+typedef struct {
+ icHeader header; /* The header */
+ icUInt32Number count; /* Num tags in the profile */
+ icInt8Number data[icAny]; /* The tagTable and tagData */
+/*
+ * Data that follows is of the form
+ *
+ * icTag tagTable[icAny]; * The tag table
+ * icInt8Number tagData[icAny]; * The tag data
+ */
+} icProfile;
+
+/*------------------------------------------------------------------------*/
+/* Obsolete entries */
+
+/* icNamedColor was replaced with icNamedColor2 */
+typedef struct {
+ icUInt32Number vendorFlag; /* Bottom 16 bits for IC use */
+ icUInt32Number count; /* Count of named colors */
+ icInt8Number data[icAny]; /* Named color data follows */
+/*
+ * Data that follows is of this form
+ *
+ * icInt8Number prefix[icAny]; * Prefix
+ * icInt8Number suffix[icAny]; * Suffix
+ * icInt8Number root1[icAny]; * Root name
+ * icInt8Number coords1[icAny]; * Color coordinates
+ * icInt8Number root2[icAny]; * Root name
+ * icInt8Number coords2[icAny]; * Color coordinates
+ * :
+ * :
+ * Repeat for root name and color coordinates up to (count-1)
+ */
+} icNamedColor;
+
+/* icNamedColorType was replaced by icNamedColor2Type */
+typedef struct {
+ icTagBase base; /* Signature, "ncol" */
+ icNamedColor ncolor; /* Named color data */
+} icNamedColorType;
+
+#endif /* ICC_H */
diff --git a/source/fitz/list-device.c b/source/fitz/list-device.c
index fdd5ea18..a8f0bb09 100644
--- a/source/fitz/list-device.c
+++ b/source/fitz/list-device.c
@@ -30,7 +30,8 @@ typedef enum fz_display_command_e
FZ_CMD_END_GROUP,
FZ_CMD_BEGIN_TILE,
FZ_CMD_END_TILE,
- FZ_CMD_RENDER_FLAGS
+ FZ_CMD_RENDER_FLAGS,
+ FZ_CMD_DEFAULT_COLORSPACES
} fz_display_command;
/* The display list is a list of nodes.
@@ -132,6 +133,7 @@ struct fz_list_device_s
fz_matrix ctm;
fz_stroke_state *stroke;
fz_colorspace *colorspace;
+ fz_color_params *color_params;
float color[FZ_MAX_COLORS];
fz_rect rect;
@@ -144,6 +146,8 @@ struct fz_list_device_s
};
enum { ISOLATED = 1, KNOCKOUT = 2 };
+enum { OPM = 1, OP = 2, BP = 3, RI = 4};
+
#define SIZE_IN_NODES(t) \
((t + sizeof(fz_display_node) - 1) / sizeof(fz_display_node))
@@ -530,38 +534,38 @@ fz_append_display_node(
switch(node.cs)
{
case CS_GRAY_0:
- writer->colorspace = fz_device_gray(ctx);
+ writer->colorspace = fz_keep_colorspace(ctx, fz_device_gray(ctx));
writer->color[0] = 0;
break;
case CS_GRAY_1:
- writer->colorspace = fz_device_gray(ctx);
+ writer->colorspace = fz_keep_colorspace(ctx, fz_device_gray(ctx));
writer->color[0] = 1;
break;
case CS_RGB_0:
writer->color[0] = 0;
writer->color[1] = 0;
writer->color[2] = 0;
- writer->colorspace = fz_device_rgb(ctx);
+ writer->colorspace = fz_keep_colorspace(ctx, fz_device_rgb(ctx));
break;
case CS_RGB_1:
writer->color[0] = 1;
writer->color[1] = 1;
writer->color[2] = 1;
- writer->colorspace = fz_device_rgb(ctx);
+ writer->colorspace = fz_keep_colorspace(ctx, fz_device_rgb(ctx));
break;
case CS_CMYK_0:
writer->color[0] = 0;
writer->color[1] = 0;
writer->color[2] = 0;
writer->color[3] = 0;
- writer->colorspace = fz_device_cmyk(ctx);
+ writer->colorspace = fz_keep_colorspace(ctx, fz_device_cmyk(ctx));
break;
case CS_CMYK_1:
writer->color[0] = 0;
writer->color[1] = 0;
writer->color[2] = 0;
writer->color[3] = 1;
- writer->colorspace = fz_device_cmyk(ctx);
+ writer->colorspace = fz_keep_colorspace(ctx, fz_device_cmyk(ctx));
break;
default:
{
@@ -628,9 +632,35 @@ fz_append_display_node(
list->len += size;
}
+/* Pack ri, op, opm, bp into flags upper bits, even/odd in lower bit */
+static int
+fz_pack_color_params(const fz_color_params *color_params)
+{
+ int flags = 0;
+
+ if (color_params == NULL)
+ return 0;
+
+ flags = color_params->ri << RI; /* 2 bits */
+ flags = flags | (color_params->bp << BP);
+ flags = flags | (color_params->op << OP);
+ flags = flags | (color_params->opm << OPM);
+ return flags;
+}
+
+/* unpack ri, op, opm, bp from flags, even/odd in lower bit */
+static void
+fz_unpack_color_params(fz_color_params *color_params, int flags)
+{
+ color_params->ri = (flags >> RI) & 3;
+ color_params->bp = (flags >> BP) & 1;
+ color_params->op = (flags >> OP) & 1;
+ color_params->opm = (flags >> OPM) & 1;
+}
+
static void
fz_list_fill_path(fz_context *ctx, fz_device *dev, const fz_path *path, int even_odd, const fz_matrix *ctm,
- fz_colorspace *colorspace, const float *color, float alpha)
+ fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params)
{
fz_rect rect;
@@ -639,7 +669,7 @@ fz_list_fill_path(fz_context *ctx, fz_device *dev, const fz_path *path, int even
ctx,
dev,
FZ_CMD_FILL_PATH,
- even_odd, /* flags */
+ even_odd | fz_pack_color_params(color_params), /* flags */
&rect,
path, /* path */
color,
@@ -653,7 +683,7 @@ fz_list_fill_path(fz_context *ctx, fz_device *dev, const fz_path *path, int even
static void
fz_list_stroke_path(fz_context *ctx, fz_device *dev, const fz_path *path, const fz_stroke_state *stroke,
- const fz_matrix *ctm, fz_colorspace *colorspace, const float *color, float alpha)
+ const fz_matrix *ctm, fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params)
{
fz_rect rect;
@@ -662,7 +692,7 @@ fz_list_stroke_path(fz_context *ctx, fz_device *dev, const fz_path *path, const
ctx,
dev,
FZ_CMD_STROKE_PATH,
- 0, /* flags */
+ fz_pack_color_params(color_params), /* flags */
&rect,
path, /* path */
color,
@@ -724,7 +754,7 @@ fz_list_clip_stroke_path(fz_context *ctx, fz_device *dev, const fz_path *path, c
static void
fz_list_fill_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_matrix *ctm,
- fz_colorspace *colorspace, const float *color, float alpha)
+ fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params)
{
fz_rect rect;
fz_text *cloned_text = fz_keep_text(ctx, text);
@@ -736,7 +766,7 @@ fz_list_fill_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz
ctx,
dev,
FZ_CMD_FILL_TEXT,
- 0, /* flags */
+ fz_pack_color_params(color_params), /* flags */
&rect,
NULL, /* path */
color, /* color */
@@ -756,7 +786,7 @@ fz_list_fill_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz
static void
fz_list_stroke_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_stroke_state *stroke, const fz_matrix *ctm,
- fz_colorspace *colorspace, const float *color, float alpha)
+ fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params)
{
fz_rect rect;
fz_text *cloned_text = fz_keep_text(ctx, text);
@@ -768,7 +798,7 @@ fz_list_stroke_text(fz_context *ctx, fz_device *dev, const fz_text *text, const
ctx,
dev,
FZ_CMD_STROKE_TEXT,
- 0, /* flags */
+ fz_pack_color_params(color_params), /* flags */
&rect,
NULL, /* path */
color, /* color */
@@ -903,7 +933,7 @@ fz_list_pop_clip(fz_context *ctx, fz_device *dev)
}
static void
-fz_list_fill_shade(fz_context *ctx, fz_device *dev, fz_shade *shade, const fz_matrix *ctm, float alpha)
+fz_list_fill_shade(fz_context *ctx, fz_device *dev, fz_shade *shade, const fz_matrix *ctm, float alpha, const fz_color_params *color_params)
{
fz_shade *shade2 = fz_keep_shade(ctx, shade);
fz_rect rect;
@@ -915,7 +945,7 @@ fz_list_fill_shade(fz_context *ctx, fz_device *dev, fz_shade *shade, const fz_ma
ctx,
dev,
FZ_CMD_FILL_SHADE,
- 0, /* flags */
+ fz_pack_color_params(color_params), /* flags */
&rect,
NULL, /* path */
NULL, /* color */
@@ -934,7 +964,7 @@ fz_list_fill_shade(fz_context *ctx, fz_device *dev, fz_shade *shade, const fz_ma
}
static void
-fz_list_fill_image(fz_context *ctx, fz_device *dev, fz_image *image, const fz_matrix *ctm, float alpha)
+fz_list_fill_image(fz_context *ctx, fz_device *dev, fz_image *image, const fz_matrix *ctm, float alpha, const fz_color_params *color_params)
{
fz_image *image2 = fz_keep_image(ctx, image);
fz_rect rect = fz_unit_rect;
@@ -946,7 +976,7 @@ fz_list_fill_image(fz_context *ctx, fz_device *dev, fz_image *image, const fz_ma
ctx,
dev,
FZ_CMD_FILL_IMAGE,
- 0, /* flags */
+ fz_pack_color_params(color_params), /* flags */
&rect,
NULL, /* path */
NULL, /* color */
@@ -966,7 +996,7 @@ fz_list_fill_image(fz_context *ctx, fz_device *dev, fz_image *image, const fz_ma
static void
fz_list_fill_image_mask(fz_context *ctx, fz_device *dev, fz_image *image, const fz_matrix *ctm,
- fz_colorspace *colorspace, const float *color, float alpha)
+ fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params)
{
fz_image *image2 = fz_keep_image(ctx, image);
fz_rect rect = fz_unit_rect;
@@ -978,7 +1008,7 @@ fz_list_fill_image_mask(fz_context *ctx, fz_device *dev, fz_image *image, const
ctx,
dev,
FZ_CMD_FILL_IMAGE_MASK,
- 0, /* flags */
+ fz_pack_color_params(color_params), /* flags */
&rect,
NULL, /* path */
color,
@@ -1030,13 +1060,13 @@ fz_list_clip_image_mask(fz_context *ctx, fz_device *dev, fz_image *image, const
}
static void
-fz_list_begin_mask(fz_context *ctx, fz_device *dev, const fz_rect *rect, int luminosity, fz_colorspace *colorspace, const float *color)
+fz_list_begin_mask(fz_context *ctx, fz_device *dev, const fz_rect *rect, int luminosity, fz_colorspace *colorspace, const float *color, const fz_color_params *color_params)
{
fz_append_display_node(
ctx,
dev,
FZ_CMD_BEGIN_MASK,
- luminosity, /* flags */
+ (!!luminosity) | fz_pack_color_params(color_params), /* flags */
rect,
NULL, /* path */
color,
@@ -1198,6 +1228,27 @@ fz_list_render_flags(fz_context *ctx, fz_device *dev, int set, int clear)
}
static void
+fz_list_set_default_colorspaces(fz_context *ctx, fz_device *dev, fz_default_colorspaces *default_cs)
+{
+ fz_default_colorspaces *default_cs2 = fz_keep_default_colorspaces(ctx, default_cs);
+
+ fz_append_display_node(
+ ctx,
+ dev,
+ FZ_CMD_DEFAULT_COLORSPACES,
+ 0, /* flags */
+ NULL,
+ NULL, /* path */
+ NULL, /* color */
+ NULL, /* colorspace */
+ NULL, /* alpha */
+ NULL, /* ctm */
+ NULL, /* stroke */
+ &default_cs2, /* private_data */
+ sizeof(default_cs2)); /* private_data_len */
+}
+
+static void
fz_list_drop_device(fz_context *ctx, fz_device *dev)
{
fz_list_device *writer = (fz_list_device *)dev;
@@ -1241,6 +1292,7 @@ fz_new_list_device(fz_context *ctx, fz_display_list *list)
dev->super.end_tile = fz_list_end_tile;
dev->super.render_flags = fz_list_render_flags;
+ dev->super.set_default_colorspaces = fz_list_set_default_colorspaces;
dev->super.drop_device = fz_list_drop_device;
@@ -1342,8 +1394,10 @@ fz_drop_display_list_imp(fz_context *ctx, fz_storable *list_)
case FZ_CMD_CLIP_IMAGE_MASK:
fz_drop_image(ctx, *(fz_image **)node);
break;
+ case FZ_CMD_DEFAULT_COLORSPACES:
+ fz_drop_default_colorspaces(ctx, *(fz_default_colorspaces **)node);
+ break;
}
-
node = next;
}
fz_free(ctx, list->list);
@@ -1405,6 +1459,7 @@ fz_run_display_list(fz_context *ctx, fz_display_list *list, fz_device *dev, cons
fz_stroke_state *stroke = NULL;
float color[FZ_MAX_COLORS] = { 0 };
fz_colorspace *colorspace = fz_device_gray(ctx);
+ fz_color_params color_params;
fz_rect rect = { 0 };
/* Transformed versions of graphic state entries */
@@ -1423,6 +1478,8 @@ fz_run_display_list(fz_context *ctx, fz_display_list *list, fz_device *dev, cons
cookie->progress = 0;
}
+ color_params = *fz_default_color_params(ctx);
+
node = list->list;
node_end = &list->list[list->len];
for (; node != node_end ; node = next_node)
@@ -1455,34 +1512,34 @@ fz_run_display_list(fz_context *ctx, fz_display_list *list, fz_device *dev, cons
{
default:
case CS_GRAY_0:
- colorspace = fz_device_gray(ctx);
+ colorspace = fz_keep_colorspace(ctx, fz_device_gray(ctx));
color[0] = 0.0f;
break;
case CS_GRAY_1:
- colorspace = fz_device_gray(ctx);
+ colorspace = fz_keep_colorspace(ctx, fz_device_gray(ctx));
color[0] = 1.0f;
break;
case CS_RGB_0:
- colorspace = fz_device_rgb(ctx);
+ colorspace = fz_keep_colorspace(ctx, fz_device_rgb(ctx));
color[0] = 0.0f;
color[1] = 0.0f;
color[2] = 0.0f;
break;
case CS_RGB_1:
- colorspace = fz_device_rgb(ctx);
+ colorspace = fz_keep_colorspace(ctx, fz_device_rgb(ctx));
color[0] = 1.0f;
color[1] = 1.0f;
color[2] = 1.0f;
break;
case CS_CMYK_0:
- colorspace = fz_device_cmyk(ctx);
+ colorspace = fz_keep_colorspace(ctx, fz_device_cmyk(ctx));
color[0] = 0.0f;
color[1] = 0.0f;
color[2] = 0.0f;
color[3] = 0.0f;
break;
case CS_CMYK_1:
- colorspace = fz_device_cmyk(ctx);
+ colorspace = fz_keep_colorspace(ctx, fz_device_cmyk(ctx));
color[0] = 0.0f;
color[1] = 0.0f;
color[2] = 0.0f;
@@ -1572,7 +1629,7 @@ fz_run_display_list(fz_context *ctx, fz_display_list *list, fz_device *dev, cons
if (tiled ||
n.cmd == FZ_CMD_BEGIN_TILE || n.cmd == FZ_CMD_END_TILE ||
- n.cmd == FZ_CMD_RENDER_FLAGS)
+ n.cmd == FZ_CMD_RENDER_FLAGS || n.cmd == FZ_CMD_DEFAULT_COLORSPACES)
{
empty = 0;
}
@@ -1619,10 +1676,12 @@ visible:
switch (n.cmd)
{
case FZ_CMD_FILL_PATH:
- fz_fill_path(ctx, dev, path, n.flags, &trans_ctm, colorspace, color, alpha);
+ fz_unpack_color_params(&color_params, n.flags);
+ fz_fill_path(ctx, dev, path, n.flags & 1, &trans_ctm, colorspace, color, alpha, &color_params);
break;
case FZ_CMD_STROKE_PATH:
- fz_stroke_path(ctx, dev, path, stroke, &trans_ctm, colorspace, color, alpha);
+ fz_unpack_color_params(&color_params, n.flags);
+ fz_stroke_path(ctx, dev, path, stroke, &trans_ctm, colorspace, color, alpha, &color_params);
break;
case FZ_CMD_CLIP_PATH:
fz_clip_path(ctx, dev, path, n.flags, &trans_ctm, &trans_rect);
@@ -1631,10 +1690,12 @@ visible:
fz_clip_stroke_path(ctx, dev, path, stroke, &trans_ctm, &trans_rect);
break;
case FZ_CMD_FILL_TEXT:
- fz_fill_text(ctx, dev, *(fz_text **)node, &trans_ctm, colorspace, color, alpha);
+ fz_unpack_color_params(&color_params, n.flags);
+ fz_fill_text(ctx, dev, *(fz_text **)node, &trans_ctm, colorspace, color, alpha, &color_params);
break;
case FZ_CMD_STROKE_TEXT:
- fz_stroke_text(ctx, dev, *(fz_text **)node, stroke, &trans_ctm, colorspace, color, alpha);
+ fz_unpack_color_params(&color_params, n.flags);
+ fz_stroke_text(ctx, dev, *(fz_text **)node, stroke, &trans_ctm, colorspace, color, alpha, &color_params);
break;
case FZ_CMD_CLIP_TEXT:
fz_clip_text(ctx, dev, *(fz_text **)node, &trans_ctm, &trans_rect);
@@ -1646,13 +1707,16 @@ visible:
fz_ignore_text(ctx, dev, *(fz_text **)node, &trans_ctm);
break;
case FZ_CMD_FILL_SHADE:
- fz_fill_shade(ctx, dev, *(fz_shade **)node, &trans_ctm, alpha);
+ fz_unpack_color_params(&color_params, n.flags);
+ fz_fill_shade(ctx, dev, *(fz_shade **)node, &trans_ctm, alpha, &color_params);
break;
case FZ_CMD_FILL_IMAGE:
- fz_fill_image(ctx, dev, *(fz_image **)node, &trans_ctm, alpha);
+ fz_unpack_color_params(&color_params, n.flags);
+ fz_fill_image(ctx, dev, *(fz_image **)node, &trans_ctm, alpha, &color_params);
break;
case FZ_CMD_FILL_IMAGE_MASK:
- fz_fill_image_mask(ctx, dev, *(fz_image **)node, &trans_ctm, colorspace, color, alpha);
+ fz_unpack_color_params(&color_params, n.flags);
+ fz_fill_image_mask(ctx, dev, *(fz_image **)node, &trans_ctm, colorspace, color, alpha, &color_params);
break;
case FZ_CMD_CLIP_IMAGE_MASK:
fz_clip_image_mask(ctx, dev, *(fz_image **)node, &trans_ctm, &trans_rect);
@@ -1661,7 +1725,8 @@ visible:
fz_pop_clip(ctx, dev);
break;
case FZ_CMD_BEGIN_MASK:
- fz_begin_mask(ctx, dev, &trans_rect, n.flags, colorspace, color);
+ fz_unpack_color_params(&color_params, n.flags);
+ fz_begin_mask(ctx, dev, &trans_rect, n.flags, colorspace, color, &color_params);
break;
case FZ_CMD_END_MASK:
fz_end_mask(ctx, dev);
@@ -1694,6 +1759,9 @@ visible:
else if (n.flags == 1)
fz_render_flags(ctx, dev, FZ_DEVFLAG_GRIDFIT_AS_TILED, 0);
break;
+ case FZ_CMD_DEFAULT_COLORSPACES:
+ fz_set_default_colorspaces(ctx, dev, *(fz_default_colorspaces **)node);
+ break;
}
}
fz_catch(ctx)
diff --git a/source/fitz/output-cbz.c b/source/fitz/output-cbz.c
index c7ab5805..55c28e77 100644
--- a/source/fitz/output-cbz.c
+++ b/source/fitz/output-cbz.c
@@ -40,7 +40,7 @@ cbz_end_page(fz_context *ctx, fz_document_writer *wri_, fz_device *dev)
fz_snprintf(name, sizeof name, "p%04d.png", wri->count);
- buffer = fz_new_buffer_from_pixmap_as_png(ctx, wri->pixmap);
+ buffer = fz_new_buffer_from_pixmap_as_png(ctx, wri->pixmap, NULL);
fz_try(ctx)
fz_write_zip_entry(ctx, wri->zip, name, buffer, 0);
fz_always(ctx)
diff --git a/source/fitz/output-pcl.c b/source/fitz/output-pcl.c
index 2c680f8f..7f676cf5 100644
--- a/source/fitz/output-pcl.c
+++ b/source/fitz/output-pcl.c
@@ -691,7 +691,7 @@ fz_write_pixmap_as_pcl(fz_context *ctx, fz_output *out, const fz_pixmap *pixmap,
writer = fz_new_color_pcl_band_writer(ctx, out, pcl);
fz_try(ctx)
{
- fz_write_header(ctx, writer, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha, pixmap->xres, pixmap->yres, 0);
+ fz_write_header(ctx, writer, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha, pixmap->xres, pixmap->yres, 0, pixmap->colorspace);
fz_write_band(ctx, writer, pixmap->stride, pixmap->h, pixmap->samples);
}
fz_always(ctx)
@@ -713,7 +713,7 @@ typedef struct color_pcl_band_writer_s
} color_pcl_band_writer;
static void
-color_pcl_write_header(fz_context *ctx, fz_band_writer *writer_)
+color_pcl_write_header(fz_context *ctx, fz_band_writer *writer_, const fz_colorspace *cs)
{
color_pcl_band_writer *writer = (color_pcl_band_writer *)writer_;
fz_output *out = writer->super.out;
@@ -1078,7 +1078,7 @@ fz_write_bitmap_as_pcl(fz_context *ctx, fz_output *out, const fz_bitmap *bitmap,
writer = fz_new_mono_pcl_band_writer(ctx, out, pcl);
fz_try(ctx)
{
- fz_write_header(ctx, writer, bitmap->w, bitmap->h, 1, 0, bitmap->xres, bitmap->yres, 0);
+ fz_write_header(ctx, writer, bitmap->w, bitmap->h, 1, 0, bitmap->xres, bitmap->yres, 0, NULL);
fz_write_band(ctx, writer, bitmap->stride, bitmap->h, bitmap->samples);
}
fz_always(ctx)
@@ -1099,7 +1099,7 @@ typedef struct mono_pcl_band_writer_s
} mono_pcl_band_writer;
static void
-mono_pcl_write_header(fz_context *ctx, fz_band_writer *writer_)
+mono_pcl_write_header(fz_context *ctx, fz_band_writer *writer_, const fz_colorspace *cs)
{
mono_pcl_band_writer *writer = (mono_pcl_band_writer *)writer_;
fz_output *out = writer->super.out;
diff --git a/source/fitz/output-png.c b/source/fitz/output-png.c
index c8972b25..4a325959 100644
--- a/source/fitz/output-png.c
+++ b/source/fitz/output-png.c
@@ -33,7 +33,7 @@ fz_save_pixmap_as_png(fz_context *ctx, fz_pixmap *pixmap, const char *filename)
fz_try(ctx)
{
writer = fz_new_png_band_writer(ctx, out);
- fz_write_header(ctx, writer, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha, pixmap->xres, pixmap->yres, 0);
+ fz_write_header(ctx, writer, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha, pixmap->xres, pixmap->yres, 0, pixmap->colorspace);
fz_write_band(ctx, writer, pixmap->stride, pixmap->h, pixmap->samples);
}
fz_always(ctx)
@@ -59,7 +59,7 @@ fz_write_pixmap_as_png(fz_context *ctx, fz_output *out, const fz_pixmap *pixmap)
fz_try(ctx)
{
- fz_write_header(ctx, writer, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha, pixmap->xres, pixmap->yres, 0);
+ fz_write_header(ctx, writer, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha, pixmap->xres, pixmap->yres, 0, pixmap->colorspace);
fz_write_band(ctx, writer, pixmap->stride, pixmap->h, pixmap->samples);
}
fz_always(ctx)
@@ -82,7 +82,59 @@ typedef struct png_band_writer_s
} png_band_writer;
static void
-png_write_header(fz_context *ctx, fz_band_writer *writer_)
+png_write_icc(fz_context *ctx, png_band_writer *writer, const fz_colorspace *cs)
+{
+ fz_output *out = writer->super.out;
+ int size;
+ fz_buffer *buffer = fz_icc_data_from_icc_colorspace(ctx, cs);
+ unsigned char *data;
+ unsigned char *chunk, *pos, *cdata;
+ uLong bound;
+ uLongf csize;
+ uLong long_size;
+ int t;
+
+ long_size = (uLong)fz_buffer_storage(ctx, buffer, &data);
+
+ if (!data)
+ return;
+
+ /* Deflate the profile */
+ bound = compressBound(long_size);
+ cdata = fz_malloc(ctx, bound);
+ csize = (uLongf)bound;
+ t = compress(cdata, &csize, data, long_size);
+ if (t != Z_OK)
+ {
+ fz_free(ctx, cdata);
+ fz_throw(ctx, FZ_ERROR_GENERIC, "cannot deflate icc buffer");
+ }
+ size = csize + strlen("MuPDF Profile") + 2;
+
+ fz_var(cdata);
+
+ fz_try(ctx)
+ {
+ chunk = fz_calloc(ctx, size, 1);
+ pos = chunk;
+ memcpy(chunk, "MuPDF Profile", strlen("MuPDF Profile"));
+ pos += strlen("MuPDF Profile") + 2;
+ memcpy(pos, cdata, csize);
+ putchunk(ctx, out, "iCCP", chunk, size);
+ }
+ fz_always(ctx)
+ {
+ fz_free(ctx, cdata);
+ fz_free(ctx, chunk);
+ }
+ fz_catch(ctx)
+ {
+ /* Nothing */
+ }
+}
+
+static void
+png_write_header(fz_context *ctx, fz_band_writer *writer_, const fz_colorspace *cs)
{
png_band_writer *writer = (png_band_writer *)(void *)writer_;
fz_output *out = writer->super.out;
@@ -116,6 +168,8 @@ png_write_header(fz_context *ctx, fz_band_writer *writer_)
fz_write_data(ctx, out, pngsig, 8);
putchunk(ctx, out, "IHDR", head, 13);
+
+ png_write_icc(ctx, writer, cs);
}
static void
@@ -240,7 +294,7 @@ fz_band_writer *fz_new_png_band_writer(fz_context *ctx, fz_output *out)
* drop pix early in the case where we have to convert, potentially saving
* us having to have 2 copies of the pixmap and a buffer open at once. */
static fz_buffer *
-png_from_pixmap(fz_context *ctx, fz_pixmap *pix, int drop)
+png_from_pixmap(fz_context *ctx, fz_pixmap *pix, const fz_color_params *color_params, int drop)
{
fz_buffer *buf = NULL;
fz_output *out;
@@ -253,11 +307,14 @@ png_from_pixmap(fz_context *ctx, fz_pixmap *pix, int drop)
if (pix->w == 0 || pix->h == 0)
return NULL;
+ if (color_params == NULL)
+ color_params = fz_default_color_params(ctx);
+
fz_try(ctx)
{
if (pix->colorspace && pix->colorspace != fz_device_gray(ctx) && pix->colorspace != fz_device_rgb(ctx))
{
- pix2 = fz_convert_pixmap(ctx, pix, fz_device_rgb(ctx), 1);
+ pix2 = fz_convert_pixmap(ctx, pix, fz_device_rgb(ctx), NULL, NULL, color_params, 1);
if (drop)
fz_drop_pixmap(ctx, pix);
pix = pix2;
@@ -280,22 +337,20 @@ png_from_pixmap(fz_context *ctx, fz_pixmap *pix, int drop)
}
fz_buffer *
-fz_new_buffer_from_image_as_png(fz_context *ctx, fz_image *image)
+fz_new_buffer_from_image_as_png(fz_context *ctx, fz_image *image, const fz_color_params *color_params)
{
fz_pixmap *pix = fz_get_pixmap_from_image(ctx, image, NULL, NULL, NULL, NULL);
- fz_buffer *buf = NULL;
-
- fz_var(buf);
+ fz_buffer *buf;
fz_try(ctx)
- buf = png_from_pixmap(ctx, pix, 1);
+ buf = png_from_pixmap(ctx, pix, color_params, 1);
fz_catch(ctx)
fz_rethrow(ctx);
return buf;
}
fz_buffer *
-fz_new_buffer_from_pixmap_as_png(fz_context *ctx, fz_pixmap *pix)
+fz_new_buffer_from_pixmap_as_png(fz_context *ctx, fz_pixmap *pix, const fz_color_params *color_params)
{
- return png_from_pixmap(ctx, pix, 0);
+ return png_from_pixmap(ctx, pix, color_params, 0);
}
diff --git a/source/fitz/output-pnm.c b/source/fitz/output-pnm.c
index 455a5358..496d8ea0 100644
--- a/source/fitz/output-pnm.c
+++ b/source/fitz/output-pnm.c
@@ -4,7 +4,7 @@
* Write pixmap to PNM file (without alpha channel)
*/
static void
-pnm_write_header(fz_context *ctx, fz_band_writer *writer)
+pnm_write_header(fz_context *ctx, fz_band_writer *writer, const fz_colorspace *cs)
{
fz_output *out = writer->out;
int w = writer->w;
@@ -123,7 +123,7 @@ void
fz_write_pixmap_as_pnm(fz_context *ctx, fz_output *out, fz_pixmap *pixmap)
{
fz_band_writer *writer = fz_new_pnm_band_writer(ctx, out);
- fz_write_header(ctx, writer, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha, 0, 0, 0);
+ fz_write_header(ctx, writer, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha, 0, 0, 0, pixmap->colorspace);
fz_write_band(ctx, writer, pixmap->stride, pixmap->h, pixmap->samples);
fz_drop_band_writer(ctx, writer);
}
@@ -139,7 +139,7 @@ fz_save_pixmap_as_pnm(fz_context *ctx, fz_pixmap *pixmap, const char *filename)
fz_try(ctx)
{
writer = fz_new_pnm_band_writer(ctx, out);
- fz_write_header(ctx, writer, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha, 0, 0, 0);
+ fz_write_header(ctx, writer, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha, 0, 0, 0, pixmap->colorspace);
fz_write_band(ctx, writer, pixmap->stride, pixmap->h, pixmap->samples);
}
fz_always(ctx)
@@ -156,7 +156,7 @@ fz_save_pixmap_as_pnm(fz_context *ctx, fz_pixmap *pixmap, const char *filename)
*/
static void
-pam_write_header(fz_context *ctx, fz_band_writer *writer)
+pam_write_header(fz_context *ctx, fz_band_writer *writer, const fz_colorspace *cs)
{
fz_output *out = writer->out;
int w = writer->w;
@@ -220,7 +220,7 @@ void
fz_write_pixmap_as_pam(fz_context *ctx, fz_output *out, fz_pixmap *pixmap)
{
fz_band_writer *writer = fz_new_pam_band_writer(ctx, out);
- fz_write_header(ctx, writer, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha, 0, 0, 0);
+ fz_write_header(ctx, writer, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha, 0, 0, 0, pixmap->colorspace);
fz_write_band(ctx, writer, pixmap->stride, pixmap->h, pixmap->samples);
fz_drop_band_writer(ctx, writer);
}
@@ -236,7 +236,7 @@ fz_save_pixmap_as_pam(fz_context *ctx, fz_pixmap *pixmap, const char *filename)
fz_try(ctx)
{
writer = fz_new_pam_band_writer(ctx, out);
- fz_write_header(ctx, writer, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha, 0, 0, 0);
+ fz_write_header(ctx, writer, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha, 0, 0, 0, pixmap->colorspace);
fz_write_band(ctx, writer, pixmap->stride, pixmap->h, pixmap->samples);
}
fz_always(ctx)
diff --git a/source/fitz/output-ps.c b/source/fitz/output-ps.c
index 90be4367..a3d354ad 100644
--- a/source/fitz/output-ps.c
+++ b/source/fitz/output-ps.c
@@ -41,7 +41,7 @@ void fz_write_ps_file_trailer(fz_context *ctx, fz_output *out, int pages)
}
static void
-ps_write_header(fz_context *ctx, fz_band_writer *writer_)
+ps_write_header(fz_context *ctx, fz_band_writer *writer_, const fz_colorspace *cs)
{
ps_band_writer *writer = (ps_band_writer *)writer_;
fz_output *out = writer->super.out;
@@ -147,7 +147,7 @@ void fz_write_pixmap_as_ps(fz_context *ctx, fz_output *out, const fz_pixmap *pix
fz_try(ctx)
{
- fz_write_header(ctx, writer, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha, pixmap->xres, pixmap->yres, 0);
+ fz_write_header(ctx, writer, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha, pixmap->xres, pixmap->yres, 0, pixmap->colorspace);
fz_write_band(ctx, writer, pixmap->stride, pixmap->h, pixmap->samples);
}
fz_always(ctx)
diff --git a/source/fitz/output-pwg.c b/source/fitz/output-pwg.c
index 1b5f3812..f36c3a2b 100644
--- a/source/fitz/output-pwg.c
+++ b/source/fitz/output-pwg.c
@@ -102,7 +102,7 @@ fz_write_pixmap_as_pwg_page(fz_context *ctx, fz_output *out, const fz_pixmap *pi
fz_try(ctx)
{
- fz_write_header(ctx, writer, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha, pixmap->xres, pixmap->yres, 0);
+ fz_write_header(ctx, writer, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha, pixmap->xres, pixmap->yres, 0, pixmap->colorspace);
fz_write_band(ctx, writer, pixmap->stride, pixmap->h, pixmap->samples);
}
fz_always(ctx)
@@ -118,7 +118,7 @@ fz_write_bitmap_as_pwg_page(fz_context *ctx, fz_output *out, const fz_bitmap *bi
fz_try(ctx)
{
- fz_write_header(ctx, writer, bitmap->w, bitmap->h, bitmap->n, 0, bitmap->xres, bitmap->yres, 0);
+ fz_write_header(ctx, writer, bitmap->w, bitmap->h, bitmap->n, 0, bitmap->xres, bitmap->yres, 0, NULL);
fz_write_band(ctx, writer, bitmap->stride, bitmap->h, bitmap->samples);
}
fz_always(ctx)
@@ -174,7 +174,7 @@ fz_save_bitmap_as_pwg(fz_context *ctx, fz_bitmap *bitmap, char *filename, int ap
}
static void
-pwg_write_mono_header(fz_context *ctx, fz_band_writer *writer_)
+pwg_write_mono_header(fz_context *ctx, fz_band_writer *writer_, const fz_colorspace *cs)
{
pwg_band_writer *writer = (pwg_band_writer *)writer_;
@@ -272,7 +272,7 @@ fz_band_writer *fz_new_mono_pwg_band_writer(fz_context *ctx, fz_output *out, con
}
static void
-pwg_write_header(fz_context *ctx, fz_band_writer *writer_)
+pwg_write_header(fz_context *ctx, fz_band_writer *writer_, const fz_colorspace *cs)
{
pwg_band_writer *writer = (pwg_band_writer *)writer_;
int n = writer->super.n;
diff --git a/source/fitz/output-tga.c b/source/fitz/output-tga.c
index 712f82fe..f576dd74 100644
--- a/source/fitz/output-tga.c
+++ b/source/fitz/output-tga.c
@@ -69,7 +69,7 @@ fz_write_pixmap_as_tga(fz_context *ctx, fz_output *out, fz_pixmap *pixmap)
fz_try(ctx)
{
- fz_write_header(ctx, writer, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha, pixmap->xres, pixmap->yres, 0);
+ fz_write_header(ctx, writer, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha, pixmap->xres, pixmap->yres, 0, pixmap->colorspace);
fz_write_band(ctx, writer, -pixmap->stride, pixmap->h, pixmap->samples + pixmap->stride * (pixmap->h-1));
}
fz_always(ctx)
@@ -79,7 +79,7 @@ fz_write_pixmap_as_tga(fz_context *ctx, fz_output *out, fz_pixmap *pixmap)
}
static void
-tga_write_header(fz_context *ctx, fz_band_writer *writer_)
+tga_write_header(fz_context *ctx, fz_band_writer *writer_, const fz_colorspace *cs)
{
tga_band_writer *writer = (tga_band_writer *)writer_;
fz_output *out = writer->super.out;
diff --git a/source/fitz/output.c b/source/fitz/output.c
index cbcc4209..3240be12 100644
--- a/source/fitz/output.c
+++ b/source/fitz/output.c
@@ -392,7 +392,7 @@ fz_band_writer *fz_new_band_writer_of_size(fz_context *ctx, size_t size, fz_outp
return writer;
}
-void fz_write_header(fz_context *ctx, fz_band_writer *writer, int w, int h, int n, int alpha, int xres, int yres, int pagenum)
+void fz_write_header(fz_context *ctx, fz_band_writer *writer, int w, int h, int n, int alpha, int xres, int yres, int pagenum, const fz_colorspace *cs)
{
if (writer == NULL || writer->band == NULL)
return;
@@ -404,7 +404,7 @@ void fz_write_header(fz_context *ctx, fz_band_writer *writer, int w, int h, int
writer->yres = yres;
writer->pagenum = pagenum;
writer->line = 0;
- writer->header(ctx, writer);
+ writer->header(ctx, writer, cs);
}
void fz_write_band(fz_context *ctx, fz_band_writer *writer, int stride, int band_height, const unsigned char *samples)
diff --git a/source/fitz/pixmap.c b/source/fitz/pixmap.c
index ab7d068f..d89889fd 100644
--- a/source/fitz/pixmap.c
+++ b/source/fitz/pixmap.c
@@ -722,7 +722,7 @@ fz_ensure_pixmap_is_additive(fz_context *ctx, fz_pixmap *pix)
{
if (fz_colorspace_is_subtractive(ctx, pix->colorspace))
{
- fz_pixmap *rgb = fz_convert_pixmap(ctx, pix, fz_device_rgb(ctx), 1);
+ fz_pixmap *rgb = fz_convert_pixmap(ctx, pix, fz_device_rgb(ctx), NULL, NULL, NULL/* FIXME */, 1);
fz_drop_pixmap(ctx, pix);
return rgb;
}
@@ -881,13 +881,16 @@ fz_pixmap_size(fz_context *ctx, fz_pixmap * pix)
}
fz_pixmap *
-fz_convert_pixmap(fz_context *ctx, fz_pixmap *pix, fz_colorspace *ds, int keep_alpha)
+fz_convert_pixmap(fz_context *ctx, fz_pixmap *pix, fz_colorspace *ds, fz_colorspace *prf, fz_default_colorspaces *default_cs, const fz_color_params *color_params, int keep_alpha)
{
fz_pixmap *cvt;
if (!ds && !keep_alpha)
fz_throw(ctx, FZ_ERROR_GENERIC, "cannot both throw away and keep alpha");
+ if (color_params == NULL)
+ color_params = fz_default_color_params(ctx);
+
cvt = fz_new_pixmap(ctx, ds, pix->w, pix->h, keep_alpha && pix->alpha);
cvt->xres = pix->xres;
@@ -899,7 +902,7 @@ fz_convert_pixmap(fz_context *ctx, fz_pixmap *pix, fz_colorspace *ds, int keep_a
fz_try(ctx)
{
fz_pixmap_converter *pc = fz_lookup_pixmap_converter(ctx, ds, pix->colorspace);
- pc(ctx, cvt, pix);
+ pc(ctx, cvt, pix, prf, default_cs, color_params);
}
fz_catch(ctx)
{
diff --git a/source/fitz/stext-device.c b/source/fitz/stext-device.c
index 0213a945..f942babe 100644
--- a/source/fitz/stext-device.c
+++ b/source/fitz/stext-device.c
@@ -867,7 +867,7 @@ fz_stext_extract(fz_context *ctx, fz_stext_device *dev, fz_text_span *span, cons
static void
fz_stext_fill_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_matrix *ctm,
- fz_colorspace *colorspace, const float *color, float alpha)
+ fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params)
{
fz_stext_device *tdev = (fz_stext_device*)dev;
fz_stext_style *style;
@@ -881,7 +881,7 @@ fz_stext_fill_text(fz_context *ctx, fz_device *dev, const fz_text *text, const f
static void
fz_stext_stroke_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_stroke_state *stroke, const fz_matrix *ctm,
- fz_colorspace *colorspace, const float *color, float alpha)
+ fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params)
{
fz_stext_device *tdev = (fz_stext_device*)dev;
fz_stext_style *style;
@@ -934,7 +934,7 @@ fz_stext_ignore_text(fz_context *ctx, fz_device *dev, const fz_text *text, const
static void
fz_stext_fill_image_mask(fz_context *ctx, fz_device *dev, fz_image *img, const fz_matrix *ctm,
- fz_colorspace *cspace, const float *color, float alpha)
+ fz_colorspace *cspace, const float *color, float alpha, const fz_color_params *color_params)
{
fz_stext_device *tdev = (fz_stext_device*)dev;
fz_stext_page *page = tdev->page;
@@ -969,9 +969,9 @@ fz_stext_fill_image_mask(fz_context *ctx, fz_device *dev, fz_image *img, const f
}
static void
-fz_stext_fill_image(fz_context *ctx, fz_device *dev, fz_image *img, const fz_matrix *ctm, float alpha)
+fz_stext_fill_image(fz_context *ctx, fz_device *dev, fz_image *img, const fz_matrix *ctm, float alpha, const fz_color_params *color_params)
{
- fz_stext_fill_image_mask(ctx, dev, img, ctm, NULL, NULL, alpha);
+ fz_stext_fill_image_mask(ctx, dev, img, ctm, NULL, NULL, alpha, color_params);
}
static int
diff --git a/source/fitz/stext-output.c b/source/fitz/stext-output.c
index 49ef2ea5..a247fc8d 100644
--- a/source/fitz/stext-output.c
+++ b/source/fitz/stext-output.c
@@ -240,7 +240,7 @@ fz_print_stext_page_html(fz_context *ctx, fz_output *out, fz_stext_page *page)
break;
default:
{
- fz_buffer *buf = fz_new_buffer_from_image_as_png(ctx, image->image);
+ fz_buffer *buf = fz_new_buffer_from_image_as_png(ctx, image->image, NULL);
fz_write_printf(ctx, out, "image/png;base64,");
send_data_base64_stext(ctx, out, buf);
fz_drop_buffer(ctx, buf);
diff --git a/source/fitz/svg-device.c b/source/fitz/svg-device.c
index 7c6c8826..1bd6987f 100644
--- a/source/fitz/svg-device.c
+++ b/source/fitz/svg-device.c
@@ -200,14 +200,14 @@ svg_dev_stroke_state(fz_context *ctx, svg_device *sdev, const fz_stroke_state *s
}
static unsigned int
-svg_hex_color(fz_context *ctx, fz_colorspace *colorspace, const float *color)
+svg_hex_color(fz_context *ctx, fz_colorspace *colorspace, const float *color, const fz_color_params *color_params)
{
float rgb[3];
int r, g, b;
if (colorspace != fz_device_rgb(ctx))
{
- fz_convert_color(ctx, fz_device_rgb(ctx), rgb, colorspace, color);
+ fz_convert_color(ctx, color_params, NULL, fz_device_rgb(ctx), rgb, colorspace, color);
color = rgb;
}
@@ -219,12 +219,12 @@ svg_hex_color(fz_context *ctx, fz_colorspace *colorspace, const float *color)
}
static void
-svg_dev_fill_color(fz_context *ctx, svg_device *sdev, fz_colorspace *colorspace, const float *color, float alpha)
+svg_dev_fill_color(fz_context *ctx, svg_device *sdev, fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params)
{
fz_output *out = sdev->out;
if (colorspace)
{
- int rgb = svg_hex_color(ctx, colorspace, color);
+ int rgb = svg_hex_color(ctx, colorspace, color, color_params);
if (rgb != 0) /* black is the default value */
fz_write_printf(ctx, out, " fill=\"#%06x\"", rgb);
}
@@ -235,11 +235,11 @@ svg_dev_fill_color(fz_context *ctx, svg_device *sdev, fz_colorspace *colorspace,
}
static void
-svg_dev_stroke_color(fz_context *ctx, svg_device *sdev, fz_colorspace *colorspace, const float *color, float alpha)
+svg_dev_stroke_color(fz_context *ctx, svg_device *sdev, fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params)
{
fz_output *out = sdev->out;
if (colorspace)
- fz_write_printf(ctx, out, " fill=\"none\" stroke=\"#%06x\"", svg_hex_color(ctx, colorspace, color));
+ fz_write_printf(ctx, out, " fill=\"none\" stroke=\"#%06x\"", svg_hex_color(ctx, colorspace, color, color_params));
else
fz_write_printf(ctx, out, " fill=\"none\" stroke=\"none\"");
if (alpha != 1)
@@ -505,7 +505,7 @@ svg_dev_text_span_as_paths_defs(fz_context *ctx, fz_device *dev, fz_text_span *s
static void
svg_dev_text_span_as_paths_fill(fz_context *ctx, fz_device *dev, const fz_text_span *span, const fz_matrix *ctm,
- fz_colorspace *colorspace, const float *color, float alpha, font *fnt)
+ fz_colorspace *colorspace, const float *color, float alpha, font *fnt, const fz_color_params *color_params)
{
svg_device *sdev = (svg_device*)dev;
fz_output *out = sdev->out;
@@ -538,7 +538,7 @@ svg_dev_text_span_as_paths_fill(fz_context *ctx, fz_device *dev, const fz_text_s
fz_concat(&local_trm2, &shift, &local_trm2);
fz_write_printf(ctx, out, "<use xlink:href=\"#font_%x_%x\"", fnt->id, gid);
svg_dev_ctm(ctx, sdev, &local_trm2);
- svg_dev_fill_color(ctx, sdev, colorspace, color, alpha);
+ svg_dev_fill_color(ctx, sdev, colorspace, color, alpha, color_params);
fz_write_printf(ctx, out, "/>\n");
}
}
@@ -546,7 +546,7 @@ svg_dev_text_span_as_paths_fill(fz_context *ctx, fz_device *dev, const fz_text_s
static void
svg_dev_text_span_as_paths_stroke(fz_context *ctx, fz_device *dev, const fz_text_span *span,
const fz_stroke_state *stroke, const fz_matrix *ctm,
- fz_colorspace *colorspace, const float *color, float alpha, font *fnt)
+ fz_colorspace *colorspace, const float *color, float alpha, font *fnt, const fz_color_params *color_params)
{
svg_device *sdev = (svg_device*)dev;
fz_output *out = sdev->out;
@@ -579,7 +579,7 @@ svg_dev_text_span_as_paths_stroke(fz_context *ctx, fz_device *dev, const fz_text
fz_write_printf(ctx, out, "<use xlink:href=\"#font_%x_%x\"", fnt->id, gid);
svg_dev_stroke_state(ctx, sdev, stroke, &local_trm2);
svg_dev_ctm(ctx, sdev, &local_trm2);
- svg_dev_stroke_color(ctx, sdev, colorspace, color, alpha);
+ svg_dev_stroke_color(ctx, sdev, colorspace, color, alpha, color_params);
fz_write_printf(ctx, out, "/>\n");
}
}
@@ -588,7 +588,7 @@ svg_dev_text_span_as_paths_stroke(fz_context *ctx, fz_device *dev, const fz_text
static void
svg_dev_fill_path(fz_context *ctx, fz_device *dev, const fz_path *path, int even_odd, const fz_matrix *ctm,
- fz_colorspace *colorspace, const float *color, float alpha)
+ fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params)
{
svg_device *sdev = (svg_device*)dev;
fz_output *out = sdev->out;
@@ -596,7 +596,7 @@ svg_dev_fill_path(fz_context *ctx, fz_device *dev, const fz_path *path, int even
fz_write_printf(ctx, out, "<path");
svg_dev_ctm(ctx, sdev, ctm);
svg_dev_path(ctx, sdev, path);
- svg_dev_fill_color(ctx, sdev, colorspace, color, alpha);
+ svg_dev_fill_color(ctx, sdev, colorspace, color, alpha, color_params);
if (even_odd)
fz_write_printf(ctx, out, " fill-rule=\"evenodd\"");
fz_write_printf(ctx, out, "/>\n");
@@ -604,7 +604,7 @@ svg_dev_fill_path(fz_context *ctx, fz_device *dev, const fz_path *path, int even
static void
svg_dev_stroke_path(fz_context *ctx, fz_device *dev, const fz_path *path, const fz_stroke_state *stroke, const fz_matrix *ctm,
- fz_colorspace *colorspace, const float *color, float alpha)
+ fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params)
{
svg_device *sdev = (svg_device*)dev;
fz_output *out = sdev->out;
@@ -612,7 +612,7 @@ svg_dev_stroke_path(fz_context *ctx, fz_device *dev, const fz_path *path, const
fz_write_printf(ctx, out, "<path");
svg_dev_ctm(ctx, sdev, ctm);
svg_dev_stroke_state(ctx, sdev, stroke, &fz_identity);
- svg_dev_stroke_color(ctx, sdev, colorspace, color, alpha);
+ svg_dev_stroke_color(ctx, sdev, colorspace, color, alpha, color_params);
svg_dev_path(ctx, sdev, path);
fz_write_printf(ctx, out, "/>\n");
}
@@ -655,7 +655,7 @@ svg_dev_clip_stroke_path(fz_context *ctx, fz_device *dev, const fz_path *path, c
fz_write_printf(ctx, out, "<path");
svg_dev_ctm(ctx, sdev, ctm);
svg_dev_stroke_state(ctx, sdev, stroke, &fz_identity);
- svg_dev_stroke_color(ctx, sdev, fz_device_rgb(ctx), white, 1);
+ svg_dev_stroke_color(ctx, sdev, fz_device_rgb(ctx), white, 1, NULL);
svg_dev_path(ctx, sdev, path);
fz_write_printf(ctx, out, "/>\n</mask>\n");
out = end_def(ctx, sdev);
@@ -664,7 +664,7 @@ svg_dev_clip_stroke_path(fz_context *ctx, fz_device *dev, const fz_path *path, c
static void
svg_dev_fill_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_matrix *ctm,
- fz_colorspace *colorspace, const float *color, float alpha)
+ fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params)
{
svg_device *sdev = (svg_device*)dev;
fz_output *out = sdev->out;
@@ -676,7 +676,7 @@ svg_dev_fill_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz
for (span = text->head; span; span = span->next)
{
fz_write_printf(ctx, out, "<text");
- svg_dev_fill_color(ctx, sdev, colorspace, color, alpha);
+ svg_dev_fill_color(ctx, sdev, colorspace, color, alpha, color_params);
svg_dev_text_span(ctx, sdev, ctm, span);
}
}
@@ -685,14 +685,14 @@ svg_dev_fill_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz
for (span = text->head; span; span = span->next)
{
fnt = svg_dev_text_span_as_paths_defs(ctx, dev, span, ctm);
- svg_dev_text_span_as_paths_fill(ctx, dev, span, ctm, colorspace, color, alpha, fnt);
+ svg_dev_text_span_as_paths_fill(ctx, dev, span, ctm, colorspace, color, alpha, fnt, color_params);
}
}
}
static void
svg_dev_stroke_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_stroke_state *stroke, const fz_matrix *ctm,
- fz_colorspace *colorspace, const float *color, float alpha)
+ fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params)
{
svg_device *sdev = (svg_device*)dev;
fz_output *out = sdev->out;
@@ -704,7 +704,7 @@ svg_dev_stroke_text(fz_context *ctx, fz_device *dev, const fz_text *text, const
for (span = text->head; span; span = span->next)
{
fz_write_printf(ctx, out, "<text");
- svg_dev_fill_color(ctx, sdev, colorspace, color, alpha);
+ svg_dev_fill_color(ctx, sdev, colorspace, color, alpha, color_params);
svg_dev_text_span(ctx, sdev, ctm, span);
}
}
@@ -713,7 +713,7 @@ svg_dev_stroke_text(fz_context *ctx, fz_device *dev, const fz_text *text, const
for (span = text->head; span; span = span->next)
{
fnt = svg_dev_text_span_as_paths_defs(ctx, dev, span, ctm);
- svg_dev_text_span_as_paths_stroke(ctx, dev, span, stroke, ctm, colorspace, color, alpha, fnt);
+ svg_dev_text_span_as_paths_stroke(ctx, dev, span, stroke, ctm, colorspace, color, alpha, fnt, color_params);
}
}
}
@@ -741,7 +741,7 @@ svg_dev_clip_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz
for (span = text->head; span; span = span->next)
{
fz_write_printf(ctx, out, "<text");
- svg_dev_fill_color(ctx, sdev, fz_device_rgb(ctx), white, 1);
+ svg_dev_fill_color(ctx, sdev, fz_device_rgb(ctx), white, 1, NULL);
svg_dev_text_span(ctx, sdev, ctm, span);
}
}
@@ -750,7 +750,7 @@ svg_dev_clip_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz
for (span = text->head; span; span = span->next)
{
fnt = svg_dev_text_span_as_paths_defs(ctx, dev, span, ctm);
- svg_dev_text_span_as_paths_fill(ctx, dev, span, ctm, fz_device_rgb(ctx), white, 1.0f, fnt);
+ svg_dev_text_span_as_paths_fill(ctx, dev, span, ctm, fz_device_rgb(ctx), white, 1.0f, fnt, NULL);
}
}
fz_write_printf(ctx, out, "</mask>\n");
@@ -782,7 +782,7 @@ svg_dev_clip_stroke_text(fz_context *ctx, fz_device *dev, const fz_text *text, c
{
fz_write_printf(ctx, out, "<text");
svg_dev_stroke_state(ctx, sdev, stroke, &fz_identity);
- svg_dev_stroke_color(ctx, sdev, fz_device_rgb(ctx), white, 1);
+ svg_dev_stroke_color(ctx, sdev, fz_device_rgb(ctx), white, 1, NULL);
svg_dev_text_span(ctx, sdev, ctm, span);
}
}
@@ -791,7 +791,7 @@ svg_dev_clip_stroke_text(fz_context *ctx, fz_device *dev, const fz_text *text, c
for (span = text->head; span; span = span->next)
{
fnt = svg_dev_text_span_as_paths_defs(ctx, dev, span, ctm);
- svg_dev_text_span_as_paths_stroke(ctx, dev, span, stroke, ctm, fz_device_rgb(ctx), white, 1.0f, fnt);
+ svg_dev_text_span_as_paths_stroke(ctx, dev, span, stroke, ctm, fz_device_rgb(ctx), white, 1.0f, fnt, NULL);
}
}
fz_write_printf(ctx, out, "</mask>\n");
@@ -813,7 +813,7 @@ svg_dev_ignore_text(fz_context *ctx, fz_device *dev, const fz_text *text, const
for (span = text->head; span; span = span->next)
{
fz_write_printf(ctx, out, "<text");
- svg_dev_fill_color(ctx, sdev, fz_device_rgb(ctx), black, 0.0f);
+ svg_dev_fill_color(ctx, sdev, fz_device_rgb(ctx), black, 0.0f, NULL);
svg_dev_text_span(ctx, sdev, ctm, span);
}
}
@@ -863,7 +863,7 @@ send_data_base64(fz_context *ctx, fz_output *out, fz_buffer *buffer)
* have conniptions. We therefore have an option that is
* made to avoid this (reuse-images=no). */
static void
-svg_send_image(fz_context *ctx, svg_device *sdev, fz_image *img)
+svg_send_image(fz_context *ctx, svg_device *sdev, fz_image *img, const fz_color_params *color_params)
{
fz_output *out = sdev->out;
fz_compressed_buffer *buffer;
@@ -917,7 +917,7 @@ svg_send_image(fz_context *ctx, svg_device *sdev, fz_image *img)
/*@fallthough@*/
default:
{
- fz_buffer *buf = fz_new_buffer_from_image_as_png(ctx, img);
+ fz_buffer *buf = fz_new_buffer_from_image_as_png(ctx, img, color_params);
fz_write_printf(ctx, out, "image/png;base64,");
send_data_base64(ctx, out, buf);
fz_drop_buffer(ctx, buf);
@@ -941,7 +941,7 @@ svg_send_image(fz_context *ctx, svg_device *sdev, fz_image *img)
}
static void
-svg_dev_fill_image(fz_context *ctx, fz_device *dev, fz_image *image, const fz_matrix *ctm, float alpha)
+svg_dev_fill_image(fz_context *ctx, fz_device *dev, fz_image *image, const fz_matrix *ctm, float alpha, const fz_color_params *color_params)
{
svg_device *sdev = (svg_device*)dev;
fz_output *out = sdev->out;
@@ -958,12 +958,12 @@ svg_dev_fill_image(fz_context *ctx, fz_device *dev, fz_image *image, const fz_ma
fz_write_printf(ctx, out, " opacity=\"%g\"", alpha);
svg_dev_ctm(ctx, sdev, &local_ctm);
fz_write_printf(ctx, out, ">\n");
- svg_send_image(ctx, sdev, image);
+ svg_send_image(ctx, sdev, image, color_params);
fz_write_printf(ctx, out, "</g>\n");
}
static void
-svg_dev_fill_shade(fz_context *ctx, fz_device *dev, fz_shade *shade, const fz_matrix *ctm, float alpha)
+svg_dev_fill_shade(fz_context *ctx, fz_device *dev, fz_shade *shade, const fz_matrix *ctm, float alpha, const fz_color_params *color_params)
{
svg_device *sdev = (svg_device*)dev;
fz_output *out = sdev->out;
@@ -985,8 +985,8 @@ svg_dev_fill_shade(fz_context *ctx, fz_device *dev, fz_shade *shade, const fz_ma
fz_try(ctx)
{
- fz_paint_shade(ctx, shade, ctm, pix, &bbox);
- buf = fz_new_buffer_from_pixmap_as_png(ctx, pix);
+ fz_paint_shade(ctx, shade, ctm, pix, NULL, color_params, &bbox);
+ buf = fz_new_buffer_from_pixmap_as_png(ctx, pix, color_params);
if (alpha != 1.0f)
fz_write_printf(ctx, out, "<g opacity=\"%g\">\n", alpha);
fz_write_printf(ctx, out, "<image x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" xlink:href=\"data:image/png;base64,", pix->x, pix->y, pix->w, pix->h);
@@ -1008,7 +1008,7 @@ svg_dev_fill_shade(fz_context *ctx, fz_device *dev, fz_shade *shade, const fz_ma
static void
svg_dev_fill_image_mask(fz_context *ctx, fz_device *dev, fz_image *image, const fz_matrix *ctm,
- fz_colorspace *colorspace, const float *color, float alpha)
+ fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params)
{
svg_device *sdev = (svg_device*)dev;
fz_output *out;
@@ -1022,11 +1022,11 @@ svg_dev_fill_image_mask(fz_context *ctx, fz_device *dev, fz_image *image, const
fz_concat(&local_ctm, &scale, ctm);
out = start_def(ctx, sdev);
fz_write_printf(ctx, out, "<mask id=\"ma%d\">\n", mask);
- svg_send_image(ctx, sdev, image);
+ svg_send_image(ctx, sdev, image, color_params);
fz_write_printf(ctx, out, "</mask>\n");
out = end_def(ctx, sdev);
fz_write_printf(ctx, out, "<rect x=\"0\" y=\"0\" width=\"%d\" height=\"%d\"", image->w, image->h);
- svg_dev_fill_color(ctx, sdev, colorspace, color, alpha);
+ svg_dev_fill_color(ctx, sdev, colorspace, color, alpha, color_params);
svg_dev_ctm(ctx, sdev, &local_ctm);
fz_write_printf(ctx, out, " mask=\"url(#ma%d)\"/>\n", mask);
}
@@ -1048,7 +1048,7 @@ svg_dev_clip_image_mask(fz_context *ctx, fz_device *dev, fz_image *image, const
fz_write_printf(ctx, out, "<mask id=\"ma%d\">\n<g", mask);
svg_dev_ctm(ctx, sdev, &local_ctm);
fz_write_printf(ctx, out, ">\n");
- svg_send_image(ctx, sdev, image);
+ svg_send_image(ctx, sdev, image, NULL/* FIXME */);
fz_write_printf(ctx, out, "</g>\n</mask>\n");
out = end_def(ctx, sdev);
fz_write_printf(ctx, out, "<g mask=\"url(#ma%d)\">\n", mask);
@@ -1065,7 +1065,7 @@ svg_dev_pop_clip(fz_context *ctx, fz_device *dev)
}
static void
-svg_dev_begin_mask(fz_context *ctx, fz_device *dev, const fz_rect *bbox, int luminosity, fz_colorspace *colorspace, const float *color)
+svg_dev_begin_mask(fz_context *ctx, fz_device *dev, const fz_rect *bbox, int luminosity, fz_colorspace *colorspace, const float *color, const fz_color_params *color_params)
{
svg_device *sdev = (svg_device*)dev;
fz_output *out;
diff --git a/source/fitz/test-device.c b/source/fitz/test-device.c
index 38dc331b..aa6631a8 100644
--- a/source/fitz/test-device.c
+++ b/source/fitz/test-device.c
@@ -29,7 +29,7 @@ is_rgb_color_u8(int threshold_u8, int r, int g, int b)
}
static void
-fz_test_color(fz_context *ctx, fz_test_device *t, fz_colorspace *colorspace, const float *color)
+fz_test_color(fz_context *ctx, fz_test_device *t, fz_colorspace *colorspace, const float *color, const fz_color_params *color_params)
{
if (!*t->is_color && colorspace && colorspace != fz_device_gray(ctx))
{
@@ -46,7 +46,7 @@ fz_test_color(fz_context *ctx, fz_test_device *t, fz_colorspace *colorspace, con
else
{
float rgb[3];
- fz_convert_color(ctx, fz_device_rgb(ctx), rgb, colorspace, color);
+ fz_convert_color(ctx, color_params, NULL, fz_device_rgb(ctx), rgb, colorspace, color);
if (is_rgb_color(t->threshold, rgb[0], rgb[1], rgb[2]))
{
*t->is_color = 2;
@@ -62,68 +62,73 @@ fz_test_color(fz_context *ctx, fz_test_device *t, fz_colorspace *colorspace, con
static void
fz_test_fill_path(fz_context *ctx, fz_device *dev_, const fz_path *path, int even_odd, const fz_matrix *ctm,
- fz_colorspace *colorspace, const float *color, float alpha)
+ fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params)
{
fz_test_device *dev = (fz_test_device*)dev_;
- if (dev->resolved == 0)
+ if (dev->resolved == 0 && alpha != 0.0f)
{
- if (alpha != 0.0f)
- fz_test_color(ctx, dev, colorspace, color);
+ if (color_params == NULL)
+ color_params = fz_default_color_params(ctx);
+ fz_test_color(ctx, dev, colorspace, color, color_params);
}
if (dev->passthrough)
- fz_fill_path(ctx, dev->passthrough, path, even_odd, ctm, colorspace, color, alpha);
+ fz_fill_path(ctx, dev->passthrough, path, even_odd, ctm, colorspace, color, alpha, color_params);
}
static void
fz_test_stroke_path(fz_context *ctx, fz_device *dev_, const fz_path *path, const fz_stroke_state *stroke,
- const fz_matrix *ctm, fz_colorspace *colorspace, const float *color, float alpha)
+ const fz_matrix *ctm, fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params)
{
fz_test_device *dev = (fz_test_device*)dev_;
- if (dev->resolved == 0)
+ if (dev->resolved == 0 && alpha != 0.0f)
{
- if (alpha != 0.0f)
- fz_test_color(ctx, dev, colorspace, color);
+ if (color_params == NULL)
+ color_params = fz_default_color_params(ctx);
+ fz_test_color(ctx, dev, colorspace, color, color_params);
}
if (dev->passthrough)
- fz_stroke_path(ctx, dev->passthrough, path, stroke, ctm, colorspace, color, alpha);
+ fz_stroke_path(ctx, dev->passthrough, path, stroke, ctm, colorspace, color, alpha, color_params);
}
static void
fz_test_fill_text(fz_context *ctx, fz_device *dev_, const fz_text *text, const fz_matrix *ctm,
- fz_colorspace *colorspace, const float *color, float alpha)
+ fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params)
{
fz_test_device *dev = (fz_test_device*)dev_;
- if (dev->resolved == 0)
+ if (dev->resolved == 0 && alpha != 0.0f)
{
- if (alpha != 0.0f)
- fz_test_color(ctx, dev, colorspace, color);
+ if (color_params == NULL)
+ color_params = fz_default_color_params(ctx);
+ fz_test_color(ctx, dev, colorspace, color, color_params);
}
if (dev->passthrough)
- fz_fill_text(ctx, dev->passthrough, text, ctm, colorspace, color, alpha);
+ fz_fill_text(ctx, dev->passthrough, text, ctm, colorspace, color, alpha, color_params);
}
static void
fz_test_stroke_text(fz_context *ctx, fz_device *dev_, const fz_text *text, const fz_stroke_state *stroke,
- const fz_matrix *ctm, fz_colorspace *colorspace, const float *color, float alpha)
+ const fz_matrix *ctm, fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params)
{
fz_test_device *dev = (fz_test_device*)dev_;
- if (dev->resolved == 0)
+ if (dev->resolved == 0 && alpha != 0.0f)
{
- if (alpha != 0.0f)
- fz_test_color(ctx, dev, colorspace, color);
+ if (color_params == NULL)
+ color_params = fz_default_color_params(ctx);
+ fz_test_color(ctx, dev, colorspace, color, color_params);
}
if (dev->passthrough)
- fz_stroke_text(ctx, dev->passthrough, text, stroke, ctm, colorspace, color, alpha);
+ fz_stroke_text(ctx, dev->passthrough, text, stroke, ctm, colorspace, color, alpha, color_params);
}
struct shadearg
{
fz_test_device *dev;
fz_shade *shade;
+ const fz_color_params *color_params;
};
static void
@@ -133,14 +138,17 @@ prepare_vertex(fz_context *ctx, void *arg_, fz_vertex *v, const float *color)
fz_test_device *dev = arg->dev;
fz_shade *shade = arg->shade;
if (!shade->use_function)
- fz_test_color(ctx, dev, shade->colorspace, color);
+ fz_test_color(ctx, dev, shade->colorspace, color, arg->color_params);
}
static void
-fz_test_fill_shade(fz_context *ctx, fz_device *dev_, fz_shade *shade, const fz_matrix *ctm, float alpha)
+fz_test_fill_shade(fz_context *ctx, fz_device *dev_, fz_shade *shade, const fz_matrix *ctm, float alpha, const fz_color_params *color_params)
{
fz_test_device *dev = (fz_test_device*)dev_;
+ if (color_params == NULL)
+ color_params = fz_default_color_params(ctx);
+
if (dev->resolved == 0)
{
if ((dev->options & FZ_TEST_OPT_SHADINGS) == 0)
@@ -161,23 +169,24 @@ fz_test_fill_shade(fz_context *ctx, fz_device *dev_, fz_shade *shade, const fz_m
{
int i;
for (i = 0; i < 256; i++)
- fz_test_color(ctx, dev, shade->colorspace, shade->function[i]);
+ fz_test_color(ctx, dev, shade->colorspace, shade->function[i], color_params);
}
else
{
struct shadearg arg;
arg.dev = dev;
arg.shade = shade;
+ arg.color_params = color_params;
fz_process_shade(ctx, shade, ctm, prepare_vertex, NULL, &arg);
}
}
}
if (dev->passthrough)
- fz_fill_shade(ctx, dev->passthrough, shade, ctm, alpha);
+ fz_fill_shade(ctx, dev->passthrough, shade, ctm, alpha, color_params);
}
static void
-fz_test_fill_image(fz_context *ctx, fz_device *dev_, fz_image *image, const fz_matrix *ctm, float alpha)
+fz_test_fill_image(fz_context *ctx, fz_device *dev_, fz_image *image, const fz_matrix *ctm, float alpha, const fz_color_params *color_params)
{
fz_test_device *dev = (fz_test_device*)dev_;
@@ -231,7 +240,7 @@ fz_test_fill_image(fz_context *ctx, fz_device *dev_, fz_image *image, const fz_m
fz_color_converter cc;
unsigned int n = (unsigned int)image->n;
- fz_init_cached_color_converter(ctx, &cc, fz_device_rgb(ctx), image->colorspace);
+ fz_init_cached_color_converter(ctx, &cc, NULL, fz_device_rgb(ctx), image->colorspace, color_params);
for (i = 0; i < count; i++)
{
float cs[FZ_MAX_COLORS];
@@ -299,7 +308,7 @@ fz_test_fill_image(fz_context *ctx, fz_device *dev_, fz_image *image, const fz_m
fz_color_converter cc;
unsigned int n = (unsigned int)pix->n-1;
- fz_init_cached_color_converter(ctx, &cc, fz_device_rgb(ctx), pix->colorspace);
+ fz_init_cached_color_converter(ctx, &cc, NULL, fz_device_rgb(ctx), pix->colorspace, color_params);
while (h--)
{
for (i = 0; i < count; i++)
@@ -336,22 +345,25 @@ fz_test_fill_image(fz_context *ctx, fz_device *dev_, fz_image *image, const fz_m
break;
}
if (dev->passthrough)
- fz_fill_image(ctx, dev->passthrough, image, ctm, alpha);
+ fz_fill_image(ctx, dev->passthrough, image, ctm, alpha, color_params);
}
static void
fz_test_fill_image_mask(fz_context *ctx, fz_device *dev_, fz_image *image, const fz_matrix *ctm,
- fz_colorspace *colorspace, const float *color, float alpha)
+ fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params)
{
fz_test_device *dev = (fz_test_device*)dev_;
+ if (color_params == NULL)
+ color_params = fz_default_color_params(ctx);
+
if (dev->resolved == 0)
{
/* We assume that at least some of the image pixels are non-zero */
- fz_test_color(ctx, dev, colorspace, color);
+ fz_test_color(ctx, dev, colorspace, color, color_params);
}
if (dev->passthrough)
- fz_fill_image_mask(ctx, dev->passthrough, image, ctm, colorspace, color, alpha);
+ fz_fill_image_mask(ctx, dev->passthrough, image, ctm, colorspace, color, alpha, color_params);
}
static void
@@ -411,11 +423,11 @@ fz_test_pop_clip(fz_context *ctx, fz_device *dev_)
}
static void
-fz_test_begin_mask(fz_context *ctx, fz_device *dev_, const fz_rect *rect, int luminosity, fz_colorspace *cs, const float *bc)
+fz_test_begin_mask(fz_context *ctx, fz_device *dev_, const fz_rect *rect, int luminosity, fz_colorspace *cs, const float *bc, const fz_color_params *color_params)
{
fz_test_device *dev = (fz_test_device*)dev_;
- fz_begin_mask(ctx, dev->passthrough, rect, luminosity, cs, bc);
+ fz_begin_mask(ctx, dev->passthrough, rect, luminosity, cs, bc, color_params);
}
static void
diff --git a/source/fitz/trace-device.c b/source/fitz/trace-device.c
index c2f8b4c2..db08aa52 100644
--- a/source/fitz/trace-device.c
+++ b/source/fitz/trace-device.c
@@ -117,7 +117,7 @@ fz_trace_path(fz_context *ctx, fz_output *out, const fz_path *path)
static void
fz_trace_fill_path(fz_context *ctx, fz_device *dev, const fz_path *path, int even_odd, const fz_matrix *ctm,
- fz_colorspace *colorspace, const float *color, float alpha)
+ fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params)
{
fz_output *out = ((fz_trace_device*)dev)->out;
fz_write_printf(ctx, out, "<fill_path");
@@ -134,7 +134,7 @@ fz_trace_fill_path(fz_context *ctx, fz_device *dev, const fz_path *path, int eve
static void
fz_trace_stroke_path(fz_context *ctx, fz_device *dev, const fz_path *path, const fz_stroke_state *stroke, const fz_matrix *ctm,
- fz_colorspace *colorspace, const float *color, float alpha)
+ fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params)
{
fz_output *out = ((fz_trace_device*)dev)->out;
int i;
@@ -190,7 +190,7 @@ fz_trace_clip_stroke_path(fz_context *ctx, fz_device *dev, const fz_path *path,
static void
fz_trace_fill_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_matrix *ctm,
- fz_colorspace *colorspace, const float *color, float alpha)
+ fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params)
{
fz_output *out = ((fz_trace_device*)dev)->out;
fz_write_printf(ctx, out, "<fill_text");
@@ -203,7 +203,7 @@ fz_trace_fill_text(fz_context *ctx, fz_device *dev, const fz_text *text, const f
static void
fz_trace_stroke_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_stroke_state *stroke, const fz_matrix *ctm,
- fz_colorspace *colorspace, const float *color, float alpha)
+ fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params)
{
fz_output *out = ((fz_trace_device*)dev)->out;
fz_write_printf(ctx, out, "<stroke_text");
@@ -248,7 +248,7 @@ fz_trace_ignore_text(fz_context *ctx, fz_device *dev, const fz_text *text, const
}
static void
-fz_trace_fill_image(fz_context *ctx, fz_device *dev, fz_image *image, const fz_matrix *ctm, float alpha)
+fz_trace_fill_image(fz_context *ctx, fz_device *dev, fz_image *image, const fz_matrix *ctm, float alpha, const fz_color_params *color_params)
{
fz_output *out = ((fz_trace_device*)dev)->out;
fz_write_printf(ctx, out, "<fill_image alpha=\"%g\"", alpha);
@@ -258,7 +258,7 @@ fz_trace_fill_image(fz_context *ctx, fz_device *dev, fz_image *image, const fz_m
}
static void
-fz_trace_fill_shade(fz_context *ctx, fz_device *dev, fz_shade *shade, const fz_matrix *ctm, float alpha)
+fz_trace_fill_shade(fz_context *ctx, fz_device *dev, fz_shade *shade, const fz_matrix *ctm, float alpha, const fz_color_params *color_params)
{
fz_output *out = ((fz_trace_device*)dev)->out;
fz_write_printf(ctx, out, "<fill_shade alpha=\"%g\"", alpha);
@@ -268,7 +268,7 @@ fz_trace_fill_shade(fz_context *ctx, fz_device *dev, fz_shade *shade, const fz_m
static void
fz_trace_fill_image_mask(fz_context *ctx, fz_device *dev, fz_image *image, const fz_matrix *ctm,
- fz_colorspace *colorspace, const float *color, float alpha)
+ fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params)
{
fz_output *out = ((fz_trace_device*)dev)->out;
fz_write_printf(ctx, out, "<fill_image_mask");
@@ -296,7 +296,7 @@ fz_trace_pop_clip(fz_context *ctx, fz_device *dev)
}
static void
-fz_trace_begin_mask(fz_context *ctx, fz_device *dev, const fz_rect *bbox, int luminosity, fz_colorspace *colorspace, const float *color)
+fz_trace_begin_mask(fz_context *ctx, fz_device *dev, const fz_rect *bbox, int luminosity, fz_colorspace *colorspace, const float *color, const fz_color_params *color_params)
{
fz_output *out = ((fz_trace_device*)dev)->out;
fz_write_printf(ctx, out, "<mask bbox=\"%g %g %g %g\" s=\"%s\"",
diff --git a/source/gprf/gprf-doc.c b/source/gprf/gprf-doc.c
index b0111fd4..34a293bd 100644
--- a/source/gprf/gprf-doc.c
+++ b/source/gprf/gprf-doc.c
@@ -827,7 +827,7 @@ gprf_run_page(fz_context *ctx, fz_page *page_, fz_device *dev, const fz_matrix *
local.e = x * scale;
local.f = y * scale;
fz_concat(&local, &local, ctm);
- fz_fill_image(ctx, dev, page->tiles[i++], &local, 1.0f);
+ fz_fill_image(ctx, dev, page->tiles[i++], &local, 1.0f, NULL);
}
}
fz_render_flags(ctx, dev, 0, FZ_DEVFLAG_GRIDFIT_AS_TILED);
diff --git a/source/html/html-layout.c b/source/html/html-layout.c
index 6c3600ca..1ad37f8f 100644
--- a/source/html/html-layout.c
+++ b/source/html/html-layout.c
@@ -1536,7 +1536,7 @@ static void draw_flow_box(fz_context *ctx, fz_html_box *box, float page_top, flo
{
if (text)
{
- fz_fill_text(ctx, dev, text, ctm, fz_device_rgb(ctx), prev_color, 1);
+ fz_fill_text(ctx, dev, text, ctm, fz_device_rgb(ctx), prev_color, 1, NULL);
fz_drop_text(ctx, text);
text = NULL;
}
@@ -1623,7 +1623,7 @@ static void draw_flow_box(fz_context *ctx, fz_html_box *box, float page_top, flo
{
if (text)
{
- fz_fill_text(ctx, dev, text, ctm, fz_device_rgb(ctx), color, 1);
+ fz_fill_text(ctx, dev, text, ctm, fz_device_rgb(ctx), color, 1, NULL);
fz_drop_text(ctx, text);
text = NULL;
}
@@ -1632,14 +1632,14 @@ static void draw_flow_box(fz_context *ctx, fz_html_box *box, float page_top, flo
fz_matrix local_ctm = *ctm;
fz_pre_translate(&local_ctm, node->x, node->y - page_top);
fz_pre_scale(&local_ctm, node->w, node->h);
- fz_fill_image(ctx, dev, node->content.image, &local_ctm, 1);
+ fz_fill_image(ctx, dev, node->content.image, &local_ctm, 1, NULL);
}
}
}
if (text)
{
- fz_fill_text(ctx, dev, text, ctm, fz_device_rgb(ctx), color, 1);
+ fz_fill_text(ctx, dev, text, ctm, fz_device_rgb(ctx), color, 1, NULL);
fz_drop_text(ctx, text);
text = NULL;
}
@@ -1663,7 +1663,7 @@ static void draw_rect(fz_context *ctx, fz_device *dev, const fz_matrix *ctm, flo
rgb[1] = color.g / 255.0f;
rgb[2] = color.b / 255.0f;
- fz_fill_path(ctx, dev, path, 0, ctm, fz_device_rgb(ctx), rgb, color.a / 255.0f);
+ fz_fill_path(ctx, dev, path, 0, ctm, fz_device_rgb(ctx), rgb, color.a / 255.0f, NULL);
fz_drop_path(ctx, path);
}
@@ -1821,7 +1821,7 @@ static void draw_list_mark(fz_context *ctx, fz_html_box *box, float page_top, fl
color[1] = box->style.color.g / 255.0f;
color[2] = box->style.color.b / 255.0f;
- fz_fill_text(ctx, dev, text, ctm, fz_device_rgb(ctx), color, 1);
+ fz_fill_text(ctx, dev, text, ctm, fz_device_rgb(ctx), color, 1, NULL);
}
fz_always(ctx)
fz_drop_text(ctx, text);
diff --git a/source/pdf/pdf-appearance.c b/source/pdf/pdf-appearance.c
index fbd50434..da351de9 100644
--- a/source/pdf/pdf-appearance.c
+++ b/source/pdf/pdf-appearance.c
@@ -1727,7 +1727,7 @@ void pdf_set_markup_appearance(fz_context *ctx, pdf_document *doc, pdf_annot *an
if (stroke)
{
// assert(path)
- fz_stroke_path(ctx, dev, path, stroke, &page_ctm, fz_device_rgb(ctx), color, alpha);
+ fz_stroke_path(ctx, dev, path, stroke, &page_ctm, fz_device_rgb(ctx), color, alpha, NULL);
fz_drop_stroke_state(ctx, stroke);
stroke = NULL;
fz_drop_path(ctx, path);
@@ -1745,7 +1745,7 @@ void pdf_set_markup_appearance(fz_context *ctx, pdf_document *doc, pdf_annot *an
if (stroke)
{
- fz_stroke_path(ctx, dev, path, stroke, &page_ctm, fz_device_rgb(ctx), color, alpha);
+ fz_stroke_path(ctx, dev, path, stroke, &page_ctm, fz_device_rgb(ctx), color, alpha, NULL);
}
fz_close_device(ctx, dev);
@@ -1860,7 +1860,7 @@ void pdf_update_ink_appearance(fz_context *ctx, pdf_document *doc, pdf_annot *an
}
cs = pdf_to_color(ctx, doc, pdf_dict_get(ctx, annot->obj, PDF_NAME_C), color);
- fz_stroke_path(ctx, dev, path, stroke, &page_ctm, cs, color, 1.0f);
+ fz_stroke_path(ctx, dev, path, stroke, &page_ctm, cs, color, 1.0f, NULL);
fz_expand_rect(&rect, width);
/*
@@ -2115,15 +2115,15 @@ void pdf_update_text_annot_appearance(fz_context *ctx, pdf_document *doc, pdf_an
center_rect_within_rect(&bounds, &rect, &tm);
fz_concat(&tm, &tm, &page_ctm);
cs = fz_device_rgb(ctx);
- fz_fill_path(ctx, dev, path, 0, &tm, cs, yellow, 1.0f);
- fz_stroke_path(ctx, dev, path, stroke, &tm, cs, black, 1.0f);
+ fz_fill_path(ctx, dev, path, 0, &tm, cs, yellow, 1.0f, NULL);
+ fz_stroke_path(ctx, dev, path, stroke, &tm, cs, black, 1.0f, NULL);
fz_drop_path(ctx, path);
path = NULL;
path = fz_new_path(ctx);
draw_speech_bubble(ctx, path);
- fz_fill_path(ctx, dev, path, 0, &tm, cs, white, 1.0f);
- fz_stroke_path(ctx, dev, path, stroke, &tm, cs, black, 1.0f);
+ fz_fill_path(ctx, dev, path, 0, &tm, cs, white, 1.0f, NULL);
+ fz_stroke_path(ctx, dev, path, stroke, &tm, cs, black, 1.0f, NULL);
fz_close_device(ctx, dev);
@@ -2198,7 +2198,7 @@ void pdf_update_free_text_annot_appearance(fz_context *ctx, pdf_document *doc, p
dlist = fz_new_display_list(ctx, NULL);
dev = fz_new_list_device(ctx, dlist);
- fz_fill_text(ctx, dev, text, &page_ctm, cs, font_rec.da_rec.col, 1.0f);
+ fz_fill_text(ctx, dev, text, &page_ctm, cs, font_rec.da_rec.col, 1.0f, NULL);
fz_close_device(ctx, dev);
fz_transform_rect(&rect, &page_ctm);
@@ -2384,7 +2384,7 @@ void pdf_set_signature_appearance(fz_context *ctx, pdf_document *doc, pdf_annot
center_rect_within_rect(&logo_bounds, &rect, &logo_tm);
fz_concat(&logo_tm, &logo_tm, &page_ctm);
cs = fz_device_rgb(ctx);
- fz_fill_path(ctx, dev, path, 0, &logo_tm, cs, logo_color, 1.0f);
+ fz_fill_path(ctx, dev, path, 0, &logo_tm, cs, logo_color, 1.0f, NULL);
fz_drop_colorspace(ctx, cs);
cs = NULL;
@@ -2400,7 +2400,7 @@ void pdf_set_signature_appearance(fz_context *ctx, pdf_document *doc, pdf_annot
/* Display the name in the left-hand half of the form field */
rect.x1 = (rect.x0 + rect.x1)/2.0f;
text = fit_text(ctx, &font_rec, name, &rect);
- fz_fill_text(ctx, dev, text, &page_ctm, cs, font_rec.da_rec.col, 1.0f);
+ fz_fill_text(ctx, dev, text, &page_ctm, cs, font_rec.da_rec.col, 1.0f, NULL);
fz_drop_text(ctx, text);
text = NULL;
@@ -2413,7 +2413,7 @@ void pdf_set_signature_appearance(fz_context *ctx, pdf_document *doc, pdf_annot
rect = annot_rect;
rect.x0 = (rect.x0 + rect.x1)/2.0f;
text = fit_text(ctx, &font_rec, fz_string_from_buffer(ctx, fzbuf), &rect);
- fz_fill_text(ctx, dev, text, &page_ctm, cs, font_rec.da_rec.col, 1.0f);
+ fz_fill_text(ctx, dev, text, &page_ctm, cs, font_rec.da_rec.col, 1.0f, NULL);
fz_close_device(ctx, dev);
diff --git a/source/pdf/pdf-colorspace.c b/source/pdf/pdf-colorspace.c
index 2a862c65..9b840cc9 100644
--- a/source/pdf/pdf-colorspace.c
+++ b/source/pdf/pdf-colorspace.c
@@ -6,52 +6,119 @@
#include <string.h>
/* ICCBased */
-
static fz_colorspace *
-load_icc_based(fz_context *ctx, pdf_obj *dict)
+load_icc_based(fz_context *ctx, pdf_obj *dict, int alt)
{
int n;
pdf_obj *obj;
+ fz_buffer *buffer = NULL;
+ fz_colorspace *cs = NULL;
+ fz_colorspace *cs_alt = NULL;
+ fz_colorspace_clamp_fn *alt_lab_clamping = NULL;
+
+ fz_var(cs);
+ fz_var(cs_alt);
+ fz_var(buffer);
+
+ /*
+ alt => "If ICC unreadable/unsupported, then return the
+ alternate instead".
+
+ Regardless of whether alt is set or not, we DO read the
+ alternate space, because we need to know whether it's a
+ LAB space or not to affect our clamping. We just might
+ not return it.
+ */
+ fz_try(ctx)
+ {
+ obj = pdf_dict_get(ctx, dict, PDF_NAME_Alternate);
+ if (obj)
+ {
+ cs_alt = pdf_load_colorspace(ctx, obj);
+ if (fz_colorspace_is_lab_icc(ctx, cs_alt))
+ alt_lab_clamping = cs_alt->clamp;
+ }
+ }
+ fz_catch(ctx)
+ {
+ fz_drop_colorspace(ctx, cs_alt);
+ cs_alt = NULL;
+ }
+
+ /* If we're not going to be allowed to return it, drop it! */
+ if (!alt)
+ {
+ fz_drop_colorspace(ctx, cs_alt);
+ cs_alt = NULL;
+ }
n = pdf_to_int(ctx, pdf_dict_get(ctx, dict, PDF_NAME_N));
- obj = pdf_dict_get(ctx, dict, PDF_NAME_Alternate);
- if (obj)
+ fz_try(ctx)
{
- fz_colorspace *cs_alt = NULL;
-
- fz_try(ctx)
+ if (fz_get_cmm_engine(ctx))
{
- cs_alt = pdf_load_colorspace(ctx, obj);
- if (cs_alt->n != n)
- {
- fz_drop_colorspace(ctx, cs_alt);
- fz_throw(ctx, FZ_ERROR_SYNTAX, "ICCBased /Alternate colorspace must have %d components", n);
- }
+ buffer = pdf_load_stream(ctx, dict);
+ cs = fz_new_icc_colorspace(ctx, 0, n, buffer, NULL);
}
- fz_catch(ctx)
+ }
+ fz_always(ctx)
+ fz_drop_buffer(ctx, buffer);
+ fz_catch(ctx)
+ {
+ if (!alt)
+ fz_rethrow(ctx);
+ }
+
+ if (cs)
+ {
+ if (n != 1 && n != 3 && n != 4)
{
- cs_alt = NULL;
+ fz_drop_colorspace(ctx, cs);
+ fz_throw(ctx, FZ_ERROR_GENERIC, "ICC Based must have 1, 3 or 4 components");
}
- if (cs_alt)
- return cs_alt;
+ /* Override the clamping if the alternate was LAB */
+ if (alt_lab_clamping)
+ cs->clamp = alt_lab_clamping;
+ fz_drop_colorspace(ctx, cs_alt);
+ return cs;
+ }
+
+ /* Failed to load the ICC profile - either because it was broken,
+ * or because we aren't in an ICC workflow. If we aren't allowed
+ * to return the alternate, then that's all she wrote. */
+ if (!alt)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "Unable to read ICC workflow");
+
+ /* If we have an alternate we are allowed to use, return that. */
+ if (cs_alt)
+ {
+ if (n != 1 && n != 3 && n != 4)
+ {
+ fz_drop_colorspace(ctx, cs_alt);
+ fz_throw(ctx, FZ_ERROR_GENERIC, "ICC Based must have 1, 3 or 4 components");
+ }
+ return cs_alt;
}
switch (n)
{
- case 1: return fz_device_gray(ctx);
- case 3: return fz_device_rgb(ctx);
- case 4: return fz_device_cmyk(ctx);
+ case 1:
+ cs = fz_device_gray(ctx);
+ break;
+ case 3:
+ cs = fz_device_rgb(ctx);
+ break;
+ case 4:
+ cs = fz_device_cmyk(ctx);
+ break;
+ default: fz_throw(ctx, FZ_ERROR_SYNTAX, "ICCBased must have 1, 3 or 4 components");
}
- fz_throw(ctx, FZ_ERROR_SYNTAX, "ICCBased must have 1, 3 or 4 components");
+ return cs;
}
-/* Lab */
-
-/* Separation and DeviceN */
-
struct separation
{
fz_colorspace *base;
@@ -59,12 +126,19 @@ struct separation
};
static void
+separation_to_alt(fz_context *ctx, fz_colorspace *cs, const float *color, float *alt)
+{
+ struct separation *sep = cs->data;
+ pdf_eval_function(ctx, sep->tint, color, cs->n, alt, sep->base->n);
+}
+
+static void
separation_to_rgb(fz_context *ctx, fz_colorspace *cs, const float *color, float *rgb)
{
struct separation *sep = cs->data;
float alt[FZ_MAX_COLORS];
pdf_eval_function(ctx, sep->tint, color, cs->n, alt, sep->base->n);
- fz_convert_color(ctx, fz_device_rgb(ctx), rgb, sep->base, alt);
+ fz_convert_color(ctx, fz_default_color_params(ctx), NULL, fz_device_rgb(ctx), rgb, sep->base, alt);
}
static void
@@ -77,6 +151,14 @@ free_separation(fz_context *ctx, fz_colorspace *cs)
}
static fz_colorspace *
+base_separation(const fz_colorspace *cs)
+{
+ struct separation *sep = cs->data;
+
+ return sep->base;
+}
+
+static fz_colorspace *
load_separation(fz_context *ctx, pdf_obj *array)
{
fz_colorspace *cs;
@@ -108,10 +190,11 @@ load_separation(fz_context *ctx, pdf_obj *array)
* "cannot load tint function (%d 0 R)", pdf_to_num(ctx, tintobj) */
sep = fz_malloc_struct(ctx, struct separation);
- sep->base = base;
+ sep->base = fz_keep_colorspace(ctx, base); /* We drop it during the sep free... */
sep->tint = tint;
- cs = fz_new_colorspace(ctx, n == 1 ? "Separation" : "DeviceN", n, 1, separation_to_rgb, NULL, free_separation, sep,
+ cs = fz_new_colorspace(ctx, n == 1 ? "Separation" : "DeviceN", 0, n, 1,
+ fz_colorspace_is_icc(ctx, fz_device_rgb(ctx)) ? separation_to_alt : separation_to_rgb, NULL, base_separation, NULL, free_separation, sep,
sizeof(struct separation) + (base ? base->size : 0) + pdf_function_size(ctx, tint));
}
fz_catch(ctx)
@@ -128,7 +211,7 @@ load_separation(fz_context *ctx, pdf_obj *array)
int
pdf_is_tint_colorspace(fz_context *ctx, fz_colorspace *cs)
{
- return fz_colorspace_is(ctx, cs, separation_to_rgb);
+ return cs && cs->free_data == free_separation;
}
/* Indexed */
@@ -201,6 +284,104 @@ load_indexed(fz_context *ctx, pdf_obj *array)
return cs;
}
+static void
+pdf_load_cal_common(fz_context *ctx, pdf_obj *dict, float *wp, float *bp, float *gamma)
+{
+ pdf_obj *obj;
+ int i;
+
+ obj = pdf_dict_get(ctx, dict, PDF_NAME_WhitePoint);
+ if (pdf_array_len(ctx, obj) != 3)
+ fz_throw(ctx, FZ_ERROR_SYNTAX, "WhitePoint must be a 3-element array");
+
+ for (i = 0; i < 3; i++)
+ {
+ wp[i] = pdf_to_real(ctx, pdf_array_get(ctx, obj, i));
+ if (wp[i] < 0)
+ fz_throw(ctx, FZ_ERROR_SYNTAX, "WhitePoint numbers must be positive");
+ }
+ if (wp[1] != 1)
+ fz_throw(ctx, FZ_ERROR_SYNTAX, "WhitePoint Yw must be 1.0");
+
+ obj = pdf_dict_get(ctx, dict, PDF_NAME_BlackPoint);
+ if (pdf_array_len(ctx, obj) == 3)
+ {
+ for (i = 0; i < 3; i++)
+ {
+ bp[i] = pdf_to_real(ctx, pdf_array_get(ctx, obj, i));
+ if (bp[i] < 0)
+ fz_throw(ctx, FZ_ERROR_SYNTAX, "BlackPoint numbers must be positive");
+ }
+ }
+
+ obj = pdf_dict_get(ctx, dict, PDF_NAME_Gamma);
+ if (pdf_is_number(ctx, obj))
+ {
+ gamma[0] = pdf_to_real(ctx, obj);
+ gamma[1] = gamma[2];
+ if (gamma[0] <= 0)
+ fz_throw(ctx, FZ_ERROR_SYNTAX, "Gamma must be greater than zero");
+ }
+ else if (pdf_array_len(ctx, obj) == 3)
+ {
+ for (i = 0; i < 3; i++)
+ {
+ gamma[i] = pdf_to_real(ctx, pdf_array_get(ctx, obj, i));
+ if (gamma[i] <= 0)
+ fz_throw(ctx, FZ_ERROR_SYNTAX, "Gamma must be greater than zero");
+ }
+ }
+}
+
+static fz_colorspace *
+pdf_load_cal_gray(fz_context *ctx, pdf_obj *dict)
+{
+ float wp[3];
+ float bp[3] = { 0, 0, 0 };
+ float gamma[3] = { 1, 1, 1 };
+
+ if (dict == NULL)
+ return fz_device_gray(ctx);
+
+ fz_try(ctx)
+ {
+ pdf_load_cal_common(ctx, dict, wp, bp, gamma);
+ gamma[2] = gamma[1] = gamma[0];
+ }
+ fz_catch(ctx)
+ return fz_device_gray(ctx);
+ return fz_new_cal_colorspace(ctx, wp, bp, gamma, NULL);
+}
+
+static fz_colorspace *
+pdf_load_cal_rgb(fz_context *ctx, pdf_obj *dict)
+{
+ pdf_obj *obj;
+ float matrix[9] = { 1, 0, 0, 0, 1, 0, 0, 0, 1 };
+ float wp[3];
+ float bp[3] = { 0, 0, 0 };
+ float gamma[3] = { 1, 1, 1 };
+ int i;
+
+ if (dict == NULL)
+ return fz_device_rgb(ctx);
+
+ fz_try(ctx)
+ {
+ pdf_load_cal_common(ctx, dict, wp, bp, gamma);
+
+ obj = pdf_dict_get(ctx, dict, PDF_NAME_Matrix);
+ if (pdf_array_len(ctx, obj) == 9)
+ {
+ for (i = 0; i < 9; i++)
+ matrix[i] = pdf_to_real(ctx, pdf_array_get(ctx, obj, i));
+ }
+ }
+ fz_catch(ctx)
+ return fz_device_rgb(ctx);
+ return fz_new_cal_colorspace(ctx, wp, bp, gamma, matrix);
+}
+
/* Parse and create colorspace from PDF object */
static fz_colorspace *
@@ -249,9 +430,19 @@ pdf_load_colorspace_imp(fz_context *ctx, pdf_obj *obj)
else if (pdf_name_eq(ctx, name, PDF_NAME_DeviceCMYK))
return fz_device_cmyk(ctx);
else if (pdf_name_eq(ctx, name, PDF_NAME_CalGray))
- return fz_device_gray(ctx);
+ {
+ if (fz_get_cmm_engine(ctx))
+ return pdf_load_cal_gray(ctx, pdf_array_get(ctx, obj, 1));
+ else
+ return fz_device_gray(ctx);
+ }
else if (pdf_name_eq(ctx, name, PDF_NAME_CalRGB))
- return fz_device_rgb(ctx);
+ {
+ if (fz_get_cmm_engine(ctx))
+ return pdf_load_cal_rgb(ctx, pdf_array_get(ctx, obj, 1));
+ else
+ return fz_device_rgb(ctx);
+ }
else if (pdf_name_eq(ctx, name, PDF_NAME_CalCMYK))
return fz_device_cmyk(ctx);
else if (pdf_name_eq(ctx, name, PDF_NAME_Lab))
@@ -264,7 +455,7 @@ pdf_load_colorspace_imp(fz_context *ctx, pdf_obj *obj)
if (pdf_mark_obj(ctx, obj))
fz_throw(ctx, FZ_ERROR_SYNTAX, "recursive colorspace");
if (pdf_name_eq(ctx, name, PDF_NAME_ICCBased))
- cs = load_icc_based(ctx, pdf_array_get(ctx, obj, 1));
+ cs = load_icc_based(ctx, pdf_array_get(ctx, obj, 1), 1);
else if (pdf_name_eq(ctx, name, PDF_NAME_Indexed))
cs = load_indexed(ctx, obj);
@@ -305,6 +496,16 @@ pdf_load_colorspace_imp(fz_context *ctx, pdf_obj *obj)
}
}
+ /* We have seen files where /DefaultRGB is specified as 1 0 R,
+ * and 1 0 obj << /Length 3144 /Alternate /DeviceRGB /N 3 >>
+ * stream ...iccprofile... endstream endobj.
+ * This *should* be [ /ICCBased 1 0 R ], but Acrobat seems to
+ * handle it, so do our best. */
+ else if (pdf_is_dict(ctx, obj))
+ {
+ return load_icc_based(ctx, obj, 1);
+ }
+
fz_throw(ctx, FZ_ERROR_SYNTAX, "could not parse color space (%d 0 R)", pdf_to_num(ctx, obj));
}
@@ -324,3 +525,48 @@ pdf_load_colorspace(fz_context *ctx, pdf_obj *obj)
return cs;
}
+
+static fz_colorspace *
+pdf_load_output_intent(fz_context *ctx, pdf_document *doc)
+{
+ pdf_obj *root = pdf_dict_get(ctx, pdf_trailer(ctx, doc), PDF_NAME_Root);
+ pdf_obj *intents = pdf_dict_get(ctx, root, PDF_NAME_OutputIntents);
+ pdf_obj *intent_dict;
+ pdf_obj *dest_profile;
+ fz_colorspace *cs = NULL;
+
+ /* An array of intents */
+ if (!intents)
+ return NULL;
+
+ /* For now, always just use the first intent. I have never even seen a file
+ * with multiple intents but it could happen */
+ intent_dict = pdf_array_get(ctx, intents, 0);
+ if (!intent_dict)
+ return NULL;
+ dest_profile = pdf_dict_get(ctx, intent_dict, PDF_NAME_DestOutputProfile);
+ if (!dest_profile)
+ return NULL;
+
+ fz_var(cs);
+
+ fz_try(ctx)
+ cs = load_icc_based(ctx, dest_profile, 0);
+ fz_catch(ctx)
+ {
+ /* Swallow the error */
+ fz_warn(ctx, "Attempt to read Output Intent failed");
+ }
+
+ return cs;
+}
+
+fz_colorspace *
+pdf_document_output_intent(fz_context *ctx, pdf_document *doc)
+{
+#ifndef NOICC
+ if (!doc->oi)
+ doc->oi = pdf_load_output_intent(ctx, doc);
+#endif
+ return doc->oi;
+}
diff --git a/source/pdf/pdf-device.c b/source/pdf/pdf-device.c
index 23fed0fd..ba51265a 100644
--- a/source/pdf/pdf-device.c
+++ b/source/pdf/pdf-device.c
@@ -214,7 +214,7 @@ pdf_dev_ctm(fz_context *ctx, pdf_device *pdev, const fz_matrix *ctm)
}
static void
-pdf_dev_color(fz_context *ctx, pdf_device *pdev, fz_colorspace *colorspace, const float *color, int stroke)
+pdf_dev_color(fz_context *ctx, pdf_device *pdev, fz_colorspace *colorspace, const float *color, int stroke, const fz_color_params *color_params)
{
int diff = 0;
int i;
@@ -232,7 +232,7 @@ pdf_dev_color(fz_context *ctx, pdf_device *pdev, fz_colorspace *colorspace, cons
if (cspace == 0)
{
/* If it's an unknown colorspace, fallback to rgb */
- fz_convert_color(ctx, fz_device_rgb(ctx), rgb, colorspace, color);
+ fz_convert_color(ctx, color_params, NULL, fz_device_rgb(ctx), rgb, colorspace, color);
color = rgb;
colorspace = fz_device_rgb(ctx);
cspace = 3;
@@ -631,14 +631,14 @@ pdf_dev_new_form(fz_context *ctx, pdf_obj **form_ref, pdf_device *pdev, const fz
static void
pdf_dev_fill_path(fz_context *ctx, fz_device *dev, const fz_path *path, int even_odd, const fz_matrix *ctm,
- fz_colorspace *colorspace, const float *color, float alpha)
+ fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params)
{
pdf_device *pdev = (pdf_device*)dev;
gstate *gs = CURRENT_GSTATE(pdev);
pdf_dev_end_text(ctx, pdev);
pdf_dev_alpha(ctx, pdev, alpha, 0);
- pdf_dev_color(ctx, pdev, colorspace, color, 0);
+ pdf_dev_color(ctx, pdev, colorspace, color, 0, color_params);
pdf_dev_ctm(ctx, pdev, ctm);
pdf_dev_path(ctx, pdev, path);
fz_append_string(ctx, gs->buf, (even_odd ? "f*\n" : "f\n"));
@@ -646,14 +646,14 @@ pdf_dev_fill_path(fz_context *ctx, fz_device *dev, const fz_path *path, int even
static void
pdf_dev_stroke_path(fz_context *ctx, fz_device *dev, const fz_path *path, const fz_stroke_state *stroke, const fz_matrix *ctm,
- fz_colorspace *colorspace, const float *color, float alpha)
+ fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params)
{
pdf_device *pdev = (pdf_device*)dev;
gstate *gs = CURRENT_GSTATE(pdev);
pdf_dev_end_text(ctx, pdev);
pdf_dev_alpha(ctx, pdev, alpha, 1);
- pdf_dev_color(ctx, pdev, colorspace, color, 1);
+ pdf_dev_color(ctx, pdev, colorspace, color, 1, color_params);
pdf_dev_ctm(ctx, pdev, ctm);
pdf_dev_stroke_state(ctx, pdev, stroke);
pdf_dev_path(ctx, pdev, path);
@@ -694,7 +694,7 @@ pdf_dev_clip_stroke_path(fz_context *ctx, fz_device *dev, const fz_path *path, c
static void
pdf_dev_fill_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_matrix *ctm,
- fz_colorspace *colorspace, const float *color, float alpha)
+ fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params)
{
pdf_device *pdev = (pdf_device*)dev;
fz_text_span *span;
@@ -706,14 +706,14 @@ pdf_dev_fill_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz
pdf_dev_font(ctx, pdev, span->font);
pdf_dev_ctm(ctx, pdev, ctm);
pdf_dev_alpha(ctx, pdev, alpha, 0);
- pdf_dev_color(ctx, pdev, colorspace, color, 0);
+ pdf_dev_color(ctx, pdev, colorspace, color, 0, color_params);
pdf_dev_text_span(ctx, pdev, span);
}
}
static void
pdf_dev_stroke_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_stroke_state *stroke, const fz_matrix *ctm,
- fz_colorspace *colorspace, const float *color, float alpha)
+ fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params)
{
pdf_device *pdev = (pdf_device*)dev;
fz_text_span *span;
@@ -724,7 +724,7 @@ pdf_dev_stroke_text(fz_context *ctx, fz_device *dev, const fz_text *text, const
pdf_dev_font(ctx, pdev, span->font);
pdf_dev_ctm(ctx, pdev, ctm);
pdf_dev_alpha(ctx, pdev, alpha, 1);
- pdf_dev_color(ctx, pdev, colorspace, color, 1);
+ pdf_dev_color(ctx, pdev, colorspace, color, 1, color_params);
pdf_dev_text_span(ctx, pdev, span);
}
}
@@ -804,7 +804,7 @@ pdf_dev_add_image_res(fz_context *ctx, fz_device *dev, pdf_obj *im_res)
}
static void
-pdf_dev_fill_image(fz_context *ctx, fz_device *dev, fz_image *image, const fz_matrix *ctm, float alpha)
+pdf_dev_fill_image(fz_context *ctx, fz_device *dev, fz_image *image, const fz_matrix *ctm, float alpha, const fz_color_params *color_params)
{
pdf_device *pdev = (pdf_device*)dev;
pdf_obj *im_res;
@@ -832,7 +832,7 @@ pdf_dev_fill_image(fz_context *ctx, fz_device *dev, fz_image *image, const fz_ma
}
static void
-pdf_dev_fill_shade(fz_context *ctx, fz_device *dev, fz_shade *shade, const fz_matrix *ctm, float alpha)
+pdf_dev_fill_shade(fz_context *ctx, fz_device *dev, fz_shade *shade, const fz_matrix *ctm, float alpha, const fz_color_params *color_params)
{
pdf_device *pdev = (pdf_device*)dev;
@@ -842,7 +842,7 @@ pdf_dev_fill_shade(fz_context *ctx, fz_device *dev, fz_shade *shade, const fz_ma
static void
pdf_dev_fill_image_mask(fz_context *ctx, fz_device *dev, fz_image *image, const fz_matrix *ctm,
- fz_colorspace *colorspace, const float *color, float alpha)
+ fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params)
{
pdf_device *pdev = (pdf_device*)dev;
pdf_obj *im_res = NULL;
@@ -858,7 +858,7 @@ pdf_dev_fill_image_mask(fz_context *ctx, fz_device *dev, fz_image *image, const
}
fz_append_string(ctx, gs->buf, "q\n");
pdf_dev_alpha(ctx, pdev, alpha, 0);
- pdf_dev_color(ctx, pdev, colorspace, color, 0);
+ pdf_dev_color(ctx, pdev, colorspace, color, 0, color_params);
/* PDF images are upside down, so fiddle the ctm */
fz_pre_scale(&local_ctm, 1, -1);
@@ -892,7 +892,7 @@ pdf_dev_pop_clip(fz_context *ctx, fz_device *dev)
}
static void
-pdf_dev_begin_mask(fz_context *ctx, fz_device *dev, const fz_rect *bbox, int luminosity, fz_colorspace *colorspace, const float *color)
+pdf_dev_begin_mask(fz_context *ctx, fz_device *dev, const fz_rect *bbox, int luminosity, fz_colorspace *colorspace, const float *color, const fz_color_params *color_params)
{
pdf_device *pdev = (pdf_device*)dev;
pdf_document *doc = pdev->doc;
diff --git a/source/pdf/pdf-image.c b/source/pdf/pdf-image.c
index b19f1e39..cf82b540 100644
--- a/source/pdf/pdf-image.c
+++ b/source/pdf/pdf-image.c
@@ -18,7 +18,7 @@ pdf_load_jpx_imp(fz_context *ctx, pdf_document *doc, pdf_obj *rdb, pdf_obj *dict
if (tile->n != 1)
{
- fz_pixmap *gray = fz_convert_pixmap(ctx, tile, fz_device_gray(ctx), 0);
+ fz_pixmap *gray = fz_convert_pixmap(ctx, tile, fz_device_gray(ctx), NULL, NULL, fz_default_color_params(ctx), 0);
fz_drop_pixmap(ctx, tile);
tile = gray;
}
diff --git a/source/pdf/pdf-interpret.c b/source/pdf/pdf-interpret.c
index f98326e6..d9620212 100644
--- a/source/pdf/pdf-interpret.c
+++ b/source/pdf/pdf-interpret.c
@@ -200,6 +200,24 @@ pdf_process_extgstate(fz_context *ctx, pdf_processor *proc, pdf_csi *csi, pdf_ob
fz_rethrow(ctx);
}
+ /* overprint and color management */
+
+ obj = pdf_dict_get(ctx, dict, PDF_NAME_OP);
+ if (pdf_is_name(ctx, obj) && proc->op_gs_OP)
+ proc->op_gs_OP(ctx, proc, pdf_to_bool(ctx, obj));
+
+ obj = pdf_dict_get(ctx, dict, PDF_NAME_op);
+ if (pdf_is_name(ctx, obj) && proc->op_gs_op)
+ proc->op_gs_op(ctx, proc, pdf_to_bool(ctx, obj));
+
+ obj = pdf_dict_get(ctx, dict, PDF_NAME_OPM);
+ if (pdf_is_name(ctx, obj) && proc->op_gs_OPM)
+ proc->op_gs_OPM(ctx, proc, pdf_to_int(ctx, obj));
+
+ obj = pdf_dict_get(ctx, dict, PDF_NAME_UseBlackPtComp);
+ if (pdf_is_name(ctx, obj) && proc->op_gs_UseBlackPtComp)
+ proc->op_gs_UseBlackPtComp(ctx, proc, obj);
+
/* transfer functions */
obj = pdf_dict_get(ctx, dict, PDF_NAME_TR2);
@@ -253,10 +271,7 @@ pdf_process_extgstate(fz_context *ctx, pdf_processor *proc, pdf_csi *csi, pdf_ob
{
colorspace = pdf_xobject_colorspace(ctx, xobj);
if (colorspace)
- {
colorspace_n = fz_colorspace_n(ctx, colorspace);
- fz_drop_colorspace(ctx, colorspace);
- }
/* Default background color is black. */
for (k = 0; k < colorspace_n; k++)
@@ -266,6 +281,7 @@ pdf_process_extgstate(fz_context *ctx, pdf_processor *proc, pdf_csi *csi, pdf_ob
* to do for now. */
if (colorspace == fz_device_cmyk(ctx))
softmask_bc[3] = 1.0f;
+ fz_drop_colorspace(ctx, colorspace);
bc = pdf_dict_get(ctx, obj, PDF_NAME_BC);
if (pdf_is_array(ctx, bc))
diff --git a/source/pdf/pdf-op-buffer.c b/source/pdf/pdf-op-buffer.c
index d5585766..6974fb00 100644
--- a/source/pdf/pdf-op-buffer.c
+++ b/source/pdf/pdf-op-buffer.c
@@ -65,6 +65,26 @@ pdf_out_ri(fz_context *ctx, pdf_processor *proc, const char *intent)
}
static void
+pdf_out_gs_OP(fz_context *ctx, pdf_processor *proc, int b)
+{
+}
+
+static void
+pdf_out_gs_op(fz_context *ctx, pdf_processor *proc, int b)
+{
+}
+
+static void
+pdf_out_gs_OPM(fz_context *ctx, pdf_processor *proc, int i)
+{
+}
+
+static void
+pdf_out_gs_UseBlackPtComp(fz_context *ctx, pdf_processor *proc, pdf_obj *name)
+{
+}
+
+static void
pdf_out_i(fz_context *ctx, pdf_processor *proc, float flatness)
{
fz_output *out = ((pdf_output_processor*)proc)->out;
@@ -891,6 +911,12 @@ pdf_new_output_processor(fz_context *ctx, fz_output *out, int ahxencode)
/* compatibility */
proc->super.op_BX = pdf_out_BX;
proc->super.op_EX = pdf_out_EX;
+
+ /* extgstate */
+ proc->super.op_gs_OP = pdf_out_gs_OP;
+ proc->super.op_gs_op = pdf_out_gs_op;
+ proc->super.op_gs_OPM = pdf_out_gs_OPM;
+ proc->super.op_gs_UseBlackPtComp = pdf_out_gs_UseBlackPtComp;
}
proc->out = out;
diff --git a/source/pdf/pdf-op-filter.c b/source/pdf/pdf-op-filter.c
index ad80d3cd..a71f2fa7 100644
--- a/source/pdf/pdf-op-filter.c
+++ b/source/pdf/pdf-op-filter.c
@@ -389,6 +389,42 @@ pdf_filter_ri(fz_context *ctx, pdf_processor *proc, const char *intent)
}
static void
+pdf_filter_gs_OP(fz_context *ctx, pdf_processor *proc, int b)
+{
+ pdf_filter_processor *p = (pdf_filter_processor*)proc;
+ filter_flush(ctx, p, 0);
+ if (p->chain->op_gs_OP)
+ p->chain->op_gs_OP(ctx, p->chain, b);
+}
+
+static void
+pdf_filter_gs_op(fz_context *ctx, pdf_processor *proc, int b)
+{
+ pdf_filter_processor *p = (pdf_filter_processor*)proc;
+ filter_flush(ctx, p, 0);
+ if (p->chain->op_gs_op)
+ p->chain->op_gs_op(ctx, p->chain, b);
+}
+
+static void
+pdf_filter_gs_OPM(fz_context *ctx, pdf_processor *proc, int i)
+{
+ pdf_filter_processor *p = (pdf_filter_processor*)proc;
+ filter_flush(ctx, p, 0);
+ if (p->chain->op_gs_OPM)
+ p->chain->op_gs_OPM(ctx, p->chain, i);
+}
+
+static void
+pdf_filter_gs_UseBlackPtComp(fz_context *ctx, pdf_processor *proc, pdf_obj *name)
+{
+ pdf_filter_processor *p = (pdf_filter_processor*)proc;
+ filter_flush(ctx, p, 0);
+ if (p->chain->op_gs_UseBlackPtComp)
+ p->chain->op_gs_UseBlackPtComp(ctx, p->chain, name);
+}
+
+static void
pdf_filter_i(fz_context *ctx, pdf_processor *proc, float flatness)
{
pdf_filter_processor *p = (pdf_filter_processor*)proc;
@@ -1238,6 +1274,12 @@ pdf_new_filter_processor(fz_context *ctx, pdf_processor *chain, pdf_obj *old_rdb
proc->super.op_BX = pdf_filter_BX;
proc->super.op_EX = pdf_filter_EX;
+ /* extgstate */
+ proc->super.op_gs_OP = pdf_filter_gs_OP;
+ proc->super.op_gs_op = pdf_filter_gs_op;
+ proc->super.op_gs_OPM = pdf_filter_gs_OPM;
+ proc->super.op_gs_UseBlackPtComp = pdf_filter_gs_UseBlackPtComp;
+
proc->super.op_END = pdf_filter_END;
}
diff --git a/source/pdf/pdf-op-run.c b/source/pdf/pdf-op-run.c
index fddc9b91..f028732e 100644
--- a/source/pdf/pdf-op-run.c
+++ b/source/pdf/pdf-op-run.c
@@ -36,6 +36,7 @@ struct pdf_material_s
pdf_pattern *pattern;
fz_shade *shade;
int gstate_num;
+ fz_color_params color_params;
float alpha;
float v[FZ_MAX_COLORS];
};
@@ -148,7 +149,7 @@ begin_softmask(fz_context *ctx, pdf_run_processor *pr, softmask_save *save)
fz_try(ctx)
{
- fz_begin_mask(ctx, pr->dev, &mask_bbox, gstate->luminosity, mask_colorspace, gstate->softmask_bc);
+ fz_begin_mask(ctx, pr->dev, &mask_bbox, gstate->luminosity, mask_colorspace, gstate->softmask_bc, &gstate->fill.color_params);
pdf_run_xobject(ctx, pr, softmask, save->page_resources, &fz_identity);
}
fz_always(ctx)
@@ -224,7 +225,7 @@ pdf_show_shade(fz_context *ctx, pdf_run_processor *pr, fz_shade *shd)
/* FIXME: The gstate->ctm in the next line may be wrong; maybe
* it should be the parent gstates ctm? */
- fz_fill_shade(ctx, pr->dev, shd, &gstate->ctm, gstate->fill.alpha);
+ fz_fill_shade(ctx, pr->dev, shd, &gstate->ctm, gstate->fill.alpha, &gstate->fill.color_params);
pdf_end_group(ctx, pr, &softmask);
}
@@ -540,7 +541,7 @@ pdf_show_image(fz_context *ctx, pdf_run_processor *pr, fz_image *image)
break;
case PDF_MAT_COLOR:
fz_fill_image_mask(ctx, pr->dev, image, &image_ctm,
- gstate->fill.colorspace, gstate->fill.v, gstate->fill.alpha);
+ gstate->fill.colorspace, gstate->fill.v, gstate->fill.alpha, &gstate->fill.color_params);
break;
case PDF_MAT_PATTERN:
if (gstate->fill.pattern)
@@ -554,7 +555,7 @@ pdf_show_image(fz_context *ctx, pdf_run_processor *pr, fz_image *image)
if (gstate->fill.shade)
{
fz_clip_image_mask(ctx, pr->dev, image, &image_ctm, &bbox);
- fz_fill_shade(ctx, pr->dev, gstate->fill.shade, &pr->gstate[gstate->fill.gstate_num].ctm, gstate->fill.alpha);
+ fz_fill_shade(ctx, pr->dev, gstate->fill.shade, &pr->gstate[gstate->fill.gstate_num].ctm, gstate->fill.alpha, &gstate->fill.color_params);
fz_pop_clip(ctx, pr->dev);
}
break;
@@ -562,7 +563,7 @@ pdf_show_image(fz_context *ctx, pdf_run_processor *pr, fz_image *image)
}
else
{
- fz_fill_image(ctx, pr->dev, image, &image_ctm, gstate->fill.alpha);
+ fz_fill_image(ctx, pr->dev, image, &image_ctm, gstate->fill.alpha, &gstate->fill.color_params);
}
if (image->mask)
@@ -646,7 +647,7 @@ pdf_show_path(fz_context *ctx, pdf_run_processor *pr, int doclose, int dofill, i
break;
case PDF_MAT_COLOR:
fz_fill_path(ctx, pr->dev, path, even_odd, &gstate->ctm,
- gstate->fill.colorspace, gstate->fill.v, gstate->fill.alpha);
+ gstate->fill.colorspace, gstate->fill.v, gstate->fill.alpha, &gstate->fill.color_params);
break;
case PDF_MAT_PATTERN:
if (gstate->fill.pattern)
@@ -661,7 +662,7 @@ pdf_show_path(fz_context *ctx, pdf_run_processor *pr, int doclose, int dofill, i
{
fz_clip_path(ctx, pr->dev, path, even_odd, &gstate->ctm, &bbox);
/* The cluster and page 2 of patterns.pdf shows that fz_fill_shade should NOT be called with gstate->ctm. */
- fz_fill_shade(ctx, pr->dev, gstate->fill.shade, &pr->gstate[gstate->fill.gstate_num].ctm, gstate->fill.alpha);
+ fz_fill_shade(ctx, pr->dev, gstate->fill.shade, &pr->gstate[gstate->fill.gstate_num].ctm, gstate->fill.alpha, &gstate->fill.color_params);
fz_pop_clip(ctx, pr->dev);
}
break;
@@ -676,7 +677,7 @@ pdf_show_path(fz_context *ctx, pdf_run_processor *pr, int doclose, int dofill, i
break;
case PDF_MAT_COLOR:
fz_stroke_path(ctx, pr->dev, path, gstate->stroke_state, &gstate->ctm,
- gstate->stroke.colorspace, gstate->stroke.v, gstate->stroke.alpha);
+ gstate->stroke.colorspace, gstate->stroke.v, gstate->stroke.alpha, &gstate->stroke.color_params);
break;
case PDF_MAT_PATTERN:
if (gstate->stroke.pattern)
@@ -690,7 +691,7 @@ pdf_show_path(fz_context *ctx, pdf_run_processor *pr, int doclose, int dofill, i
if (gstate->stroke.shade)
{
fz_clip_stroke_path(ctx, pr->dev, path, gstate->stroke_state, &gstate->ctm, &bbox);
- fz_fill_shade(ctx, pr->dev, gstate->stroke.shade, &pr->gstate[gstate->stroke.gstate_num].ctm, gstate->stroke.alpha);
+ fz_fill_shade(ctx, pr->dev, gstate->stroke.shade, &pr->gstate[gstate->stroke.gstate_num].ctm, gstate->stroke.alpha, &gstate->stroke.color_params);
fz_pop_clip(ctx, pr->dev);
}
break;
@@ -794,7 +795,7 @@ pdf_flush_text(fz_context *ctx, pdf_run_processor *pr)
break;
case PDF_MAT_COLOR:
fz_fill_text(ctx, pr->dev, text, &gstate->ctm,
- gstate->fill.colorspace, gstate->fill.v, gstate->fill.alpha);
+ gstate->fill.colorspace, gstate->fill.v, gstate->fill.alpha, &gstate->fill.color_params);
break;
case PDF_MAT_PATTERN:
if (gstate->fill.pattern)
@@ -809,7 +810,7 @@ pdf_flush_text(fz_context *ctx, pdf_run_processor *pr)
{
fz_clip_text(ctx, pr->dev, text, &gstate->ctm, &tb);
/* Page 2 of patterns.pdf shows that fz_fill_shade should NOT be called with gstate->ctm */
- fz_fill_shade(ctx, pr->dev, gstate->fill.shade, &pr->gstate[gstate->fill.gstate_num].ctm, gstate->fill.alpha);
+ fz_fill_shade(ctx, pr->dev, gstate->fill.shade, &pr->gstate[gstate->fill.gstate_num].ctm, gstate->fill.alpha, &gstate->fill.color_params);
fz_pop_clip(ctx, pr->dev);
}
break;
@@ -824,7 +825,7 @@ pdf_flush_text(fz_context *ctx, pdf_run_processor *pr)
break;
case PDF_MAT_COLOR:
fz_stroke_text(ctx, pr->dev, text, gstate->stroke_state, &gstate->ctm,
- gstate->stroke.colorspace, gstate->stroke.v, gstate->stroke.alpha);
+ gstate->stroke.colorspace, gstate->stroke.v, gstate->stroke.alpha, &gstate->stroke.color_params);
break;
case PDF_MAT_PATTERN:
if (gstate->stroke.pattern)
@@ -838,7 +839,7 @@ pdf_flush_text(fz_context *ctx, pdf_run_processor *pr)
if (gstate->stroke.shade)
{
fz_clip_stroke_text(ctx, pr->dev, text, gstate->stroke_state, &gstate->ctm, &tb);
- fz_fill_shade(ctx, pr->dev, gstate->stroke.shade, &pr->gstate[gstate->stroke.gstate_num].ctm, gstate->stroke.alpha);
+ fz_fill_shade(ctx, pr->dev, gstate->stroke.shade, &pr->gstate[gstate->stroke.gstate_num].ctm, gstate->stroke.alpha, &gstate->stroke.color_params);
fz_pop_clip(ctx, pr->dev);
}
break;
@@ -1085,6 +1086,9 @@ pdf_init_gstate(fz_context *ctx, pdf_gstate *gs, const fz_matrix *ctm)
gs->softmask_resources = NULL;
gs->softmask_ctm = fz_identity;
gs->luminosity = 0;
+
+ gs->fill.color_params = *fz_default_color_params(ctx);
+ gs->stroke.color_params = *fz_default_color_params(ctx);
}
static void
@@ -1133,7 +1137,6 @@ pdf_set_color(fz_context *ctx, pdf_run_processor *pr, int what, float *v)
{
pdf_gstate *gstate = pr->gstate + pr->gtop;
pdf_material *mat;
- int i, n;
gstate = pdf_flush_text(ctx, pr);
@@ -1143,25 +1146,7 @@ pdf_set_color(fz_context *ctx, pdf_run_processor *pr, int what, float *v)
{
case PDF_MAT_PATTERN:
case PDF_MAT_COLOR:
- /* ICC Colorspaces would be handled here too, if we handled them */
- if (fz_colorspace_is_indexed(ctx, mat->colorspace))
- {
- mat->v[0] = fz_clamp(v[0], 0, 1) / 255;
- break;
- }
- else if (fz_colorspace_is_lab(ctx, mat->colorspace))
- {
- n = fz_colorspace_n(ctx, mat->colorspace);
- /* input is in range (0..100, -128..127, -128..127) not (0..1, 0..1, 0..1) */
- for (i = 0; i < n; i++)
- mat->v[i] = fz_clamp(v[i], i ? -128 : 0, i ? 127 : 100);
- }
- else
- {
- n = fz_colorspace_n(ctx, mat->colorspace);
- for (i = 0; i < n; i++)
- mat->v[i] = fz_clamp(v[i], 0, 1);
- }
+ fz_clamp_color(ctx, mat->colorspace, v, mat->v);
break;
default:
fz_warn(ctx, "color incompatible with material");
@@ -1435,6 +1420,44 @@ static void pdf_run_d(fz_context *ctx, pdf_processor *proc, pdf_obj *array, floa
static void pdf_run_ri(fz_context *ctx, pdf_processor *proc, const char *intent)
{
+ pdf_run_processor *pr = (pdf_run_processor *)proc;
+ pdf_gstate *gstate = pdf_flush_text(ctx, pr);
+ gstate->fill.color_params.ri = fz_lookup_rendering_intent(intent);
+ gstate->stroke.color_params.ri = gstate->fill.color_params.ri;
+}
+
+static void pdf_run_gs_OP(fz_context *ctx, pdf_processor *proc, int b)
+{
+ pdf_run_processor *pr = (pdf_run_processor *)proc;
+ pdf_gstate *gstate = pdf_flush_text(ctx, pr);
+ gstate->stroke.color_params.op = b;
+ gstate->fill.color_params.op = b;
+}
+
+static void pdf_run_gs_op(fz_context *ctx, pdf_processor *proc, int b)
+{
+ pdf_run_processor *pr = (pdf_run_processor *)proc;
+ pdf_gstate *gstate = pdf_flush_text(ctx, pr);
+ gstate->fill.color_params.op = b;
+}
+
+static void pdf_run_gs_OPM(fz_context *ctx, pdf_processor *proc, int i)
+{
+ pdf_run_processor *pr = (pdf_run_processor *)proc;
+ pdf_gstate *gstate = pdf_flush_text(ctx, pr);
+ gstate->stroke.color_params.opm = i;
+ gstate->fill.color_params.opm = i;
+}
+
+static void pdf_run_gs_UseBlackPtComp(fz_context *ctx, pdf_processor *proc, pdf_obj *obj)
+{
+ pdf_run_processor *pr = (pdf_run_processor *)proc;
+ pdf_gstate *gstate = pdf_flush_text(ctx, pr);
+ int on = pdf_name_eq(ctx, obj, PDF_NAME_ON);
+ /* The spec says that "ON" means on, "OFF" means "Off", and
+ * "Default" or anything else means "Meh, do what you want." */
+ gstate->stroke.color_params.bp = on;
+ gstate->fill.color_params.bp = on;
}
static void pdf_run_i(fz_context *ctx, pdf_processor *proc, float flatness)
@@ -1491,10 +1514,7 @@ static void pdf_run_gs_SMask(fz_context *ctx, pdf_processor *proc, pdf_xobject *
fz_colorspace *cs = pdf_xobject_colorspace(ctx, smask);
int cs_n = 1;
if (cs)
- {
cs_n = fz_colorspace_n(ctx, cs);
- fz_drop_colorspace(ctx, cs);
- }
gstate->softmask_ctm = gstate->ctm;
gstate->softmask = pdf_keep_xobject(ctx, smask);
gstate->softmask_resources = pdf_keep_obj(ctx, page_resources);
@@ -2149,6 +2169,12 @@ pdf_new_run_processor(fz_context *ctx, fz_device *dev, const fz_matrix *ctm, con
proc->super.op_BX = pdf_run_BX;
proc->super.op_EX = pdf_run_EX;
+ /* extgstate */
+ proc->super.op_gs_OP = pdf_run_gs_OP;
+ proc->super.op_gs_op = pdf_run_gs_op;
+ proc->super.op_gs_OPM = pdf_run_gs_OPM;
+ proc->super.op_gs_UseBlackPtComp = pdf_run_gs_UseBlackPtComp;
+
proc->super.op_END = pdf_run_END;
}
diff --git a/source/pdf/pdf-page.c b/source/pdf/pdf-page.c
index 8f24ef91..f243bdcd 100644
--- a/source/pdf/pdf-page.c
+++ b/source/pdf/pdf-page.c
@@ -676,6 +676,61 @@ pdf_new_page(fz_context *ctx, pdf_document *doc)
return page;
}
+fz_default_colorspaces *
+pdf_load_default_colorspaces(fz_context *ctx, pdf_document *doc, pdf_page *page)
+{
+ pdf_obj *res;
+ pdf_obj *obj;
+ pdf_obj *cs_obj;
+ fz_default_colorspaces *default_cs;
+ fz_colorspace *oi;
+
+ /* If we are doing color management check for internal default color spaces. */
+ /* Photoshop is notorious for doing this in its PDF creation. */
+ if (!fz_colorspace_is_icc(ctx, fz_device_rgb(ctx)))
+ return NULL;
+
+ default_cs = fz_new_default_colorspaces(ctx);
+ res = pdf_page_resources(ctx, page);
+ obj = pdf_dict_get(ctx, res, PDF_NAME_ColorSpace);
+ if (obj)
+ {
+ /* The spec says to ignore any colors we can't understand */
+ fz_try(ctx)
+ {
+ cs_obj = pdf_dict_get(ctx, obj, PDF_NAME_DefaultGray);
+ if (cs_obj)
+ fz_set_default_gray(ctx, default_cs, pdf_load_colorspace(ctx, cs_obj));
+ }
+ fz_catch(ctx)
+ {}
+
+ fz_try(ctx)
+ {
+ cs_obj = pdf_dict_get(ctx, obj, PDF_NAME_DefaultRGB);
+ if (cs_obj)
+ fz_set_default_rgb(ctx, default_cs, pdf_load_colorspace(ctx, cs_obj));
+ }
+ fz_catch(ctx)
+ {}
+
+ fz_try(ctx)
+ {
+ cs_obj = pdf_dict_get(ctx, obj, PDF_NAME_DefaultCMYK);
+ if (cs_obj)
+ fz_set_default_cmyk(ctx, default_cs, pdf_load_colorspace(ctx, cs_obj));
+ }
+ fz_catch(ctx)
+ {}
+ }
+
+ oi = pdf_document_output_intent(ctx, doc);
+ if (oi)
+ fz_set_default_output_intent(ctx, default_cs, oi);
+
+ return default_cs;
+}
+
pdf_page *
pdf_load_page(fz_context *ctx, pdf_document *doc, int number)
{
diff --git a/source/pdf/pdf-run.c b/source/pdf/pdf-run.c
index 4fa1071f..e4a773ba 100644
--- a/source/pdf/pdf-run.c
+++ b/source/pdf/pdf-run.c
@@ -7,6 +7,11 @@ pdf_run_annot_with_usage(fz_context *ctx, pdf_document *doc, pdf_page *page, pdf
fz_matrix local_ctm, page_ctm;
fz_rect mediabox;
pdf_processor *proc;
+ fz_default_colorspaces *default_cs;
+
+ default_cs = pdf_load_default_colorspaces(ctx, doc, page);
+ if (default_cs)
+ fz_set_default_colorspaces(ctx, dev, default_cs);
pdf_page_transform(ctx, page, &mediabox, &page_ctm);
fz_concat(&local_ctm, &page_ctm, ctm);
@@ -31,6 +36,11 @@ pdf_run_page_contents_with_usage(fz_context *ctx, pdf_document *doc, pdf_page *p
pdf_obj *contents;
fz_rect mediabox;
pdf_processor *proc;
+ fz_default_colorspaces *default_cs;
+
+ default_cs = pdf_load_default_colorspaces(ctx, doc, page);
+ if (default_cs)
+ fz_set_default_colorspaces(ctx, dev, default_cs);
pdf_page_transform(ctx, page, &mediabox, &page_ctm);
fz_concat(&local_ctm, &page_ctm, ctm);
diff --git a/source/pdf/pdf-xref.c b/source/pdf/pdf-xref.c
index 256ebfec..ce62e6b7 100644
--- a/source/pdf/pdf-xref.c
+++ b/source/pdf/pdf-xref.c
@@ -1540,6 +1540,8 @@ pdf_drop_document_imp(fz_context *ctx, pdf_document *doc)
pdf_drop_resource_tables(ctx, doc);
+ fz_drop_colorspace(ctx, doc->oi);
+
for (i = 0; i < doc->orphans_count; i++)
pdf_drop_obj(ctx, doc->orphans[i]);
@@ -2230,6 +2232,7 @@ pdf_new_document(fz_context *ctx, fz_stream *file)
pdf_document *doc = fz_new_derived_document(ctx, pdf_document);
doc->super.drop_document = (fz_document_drop_fn*)pdf_drop_document_imp;
+ doc->super.get_output_intent = (fz_document_output_intent_fn*)pdf_document_output_intent;
doc->super.needs_password = (fz_document_needs_password_fn*)pdf_needs_password;
doc->super.authenticate_password = (fz_document_authenticate_password_fn*)pdf_authenticate_password;
doc->super.has_permission = (fz_document_has_permission_fn*)pdf_has_permission;
diff --git a/source/svg/svg-run.c b/source/svg/svg-run.c
index f02a8aca..f974c675 100644
--- a/source/svg/svg-run.c
+++ b/source/svg/svg-run.c
@@ -39,13 +39,13 @@ static void svg_run_element(fz_context *ctx, fz_device *dev, svg_document *doc,
static void svg_fill(fz_context *ctx, fz_device *dev, svg_document *doc, fz_path *path, svg_state *state)
{
float opacity = state->opacity * state->fill_opacity;
- fz_fill_path(ctx, dev, path, state->fill_rule, &state->transform, fz_device_rgb(ctx), state->fill_color, opacity);
+ fz_fill_path(ctx, dev, path, state->fill_rule, &state->transform, fz_device_rgb(ctx), state->fill_color, opacity, NULL);
}
static void svg_stroke(fz_context *ctx, fz_device *dev, svg_document *doc, fz_path *path, svg_state *state)
{
float opacity = state->opacity * state->stroke_opacity;
- fz_stroke_path(ctx, dev, path, &state->stroke, &state->transform, fz_device_rgb(ctx), state->stroke_color, opacity);
+ fz_stroke_path(ctx, dev, path, &state->stroke, &state->transform, fz_device_rgb(ctx), state->stroke_color, opacity, NULL);
}
static void svg_draw_path(fz_context *ctx, fz_device *dev, svg_document *doc, fz_path *path, svg_state *state)
diff --git a/source/tools/mudraw.c b/source/tools/mudraw.c
index ef95f1d3..aebe441e 100644
--- a/source/tools/mudraw.c
+++ b/source/tools/mudraw.c
@@ -254,6 +254,12 @@ static int files = 0;
static int num_workers = 0;
static worker_t *workers;
+#ifdef NO_ICC
+static fz_cmm_engine *icc_engine = NULL;
+#else
+static fz_cmm_engine *icc_engine = &fz_cmm_engine_lcms;
+#endif
+
static const char *layer_config = NULL;
static struct {
@@ -327,6 +333,7 @@ static void usage(void)
"\t-i\tignore errors\n"
"\t-L\tlow memory mode (avoid caching, clear objects after each page)\n"
"\t-P\tparallel interpretation/rendering\n"
+ "\t-N\tdisable ICC workflow (\"N\"o color management)\n"
"\n"
"\t-y l\tList the layer configs to stderr\n"
"\t-y -\tSelect layer config (by number)\n"
@@ -797,7 +804,9 @@ static void dodrawpage(fz_context *ctx, fz_page *page, fz_display_list *list, in
bander = fz_new_color_pcl_band_writer(ctx, out, NULL);
}
if (bander)
- fz_write_header(ctx, bander, pix->w, totalheight, pix->n, pix->alpha, pix->xres, pix->yres, output_pagenum++);
+ {
+ fz_write_header(ctx, bander, pix->w, totalheight, pix->n, pix->alpha, pix->xres, pix->yres, output_pagenum++, pix->colorspace);
+ }
}
for (band = 0; band < bands; band++)
@@ -1345,10 +1354,11 @@ int mudraw_main(int argc, char **argv)
fz_context *ctx;
fz_alloc_context alloc_ctx = { NULL, trace_malloc, trace_realloc, trace_free };
fz_locks_context *locks = NULL;
+ fz_colorspace *oi = NULL;
fz_var(doc);
- while ((c = fz_getopt(argc, argv, "p:o:F:R:r:w:h:fB:c:G:Is:A:DiW:H:S:T:U:XLvPl:y:")) != -1)
+ while ((c = fz_getopt(argc, argv, "p:o:F:R:r:w:h:fB:c:G:Is:A:DiW:H:S:T:U:XLvPl:y:N")) != -1)
{
switch (c)
{
@@ -1397,6 +1407,7 @@ int mudraw_main(int argc, char **argv)
case 'D': uselist = 0; break;
case 'l': min_line_width = fz_atof(fz_optarg); break;
case 'i': ignore_errors = 1; break;
+ case 'N': icc_engine = NULL; break;
case 'T':
#ifndef DISABLE_MUTHREADS
@@ -1459,6 +1470,7 @@ int mudraw_main(int argc, char **argv)
fz_set_text_aa_level(ctx, alphabits_text);
fz_set_graphics_aa_level(ctx, alphabits_graphics);
fz_set_graphics_min_line_width(ctx, min_line_width);
+ fz_set_cmm_engine(ctx, icc_engine);
#ifndef DISABLE_MUTHREADS
if (bgprint.active)
@@ -1659,6 +1671,17 @@ int mudraw_main(int argc, char **argv)
doc = fz_open_document(ctx, filename);
+ /* Once document is open check for output intent colorspace */
+ oi = fz_document_output_intent(ctx, doc);
+ if (oi)
+ {
+ if (fz_colorspace_n(ctx, oi) == fz_colorspace_n(ctx, colorspace))
+ {
+ fz_drop_colorspace(ctx, colorspace);
+ colorspace = fz_keep_colorspace(ctx, oi);
+ }
+ }
+
if (fz_needs_password(ctx, doc))
{
if (!fz_authenticate_password(ctx, doc, password))
diff --git a/source/tools/muraster.c b/source/tools/muraster.c
index 41d5e3bf..77d60b8f 100644
--- a/source/tools/muraster.c
+++ b/source/tools/muraster.c
@@ -615,7 +615,7 @@ static int dodrawpage(fz_context *ctx, int pagenum, fz_cookie *cookie, render_de
pix = fz_new_pixmap_with_bbox(ctx, colorspace, &ibounds, 0);
fz_set_pixmap_resolution(ctx, pix, x_resolution, y_resolution);
}
- fz_write_header(ctx, render->bander, pix->w, total_height, pix->n, pix->alpha, pix->xres, pix->yres, pagenum);
+ fz_write_header(ctx, render->bander, pix->w, total_height, pix->n, pix->alpha, pix->xres, pix->yres, pagenum, pix->colorspace);
for (band = 0; band < bands; band++)
{
@@ -718,7 +718,7 @@ static int try_render_page(fz_context *ctx, int pagenum, fz_cookie *cookie, int
{
int w = render->ibounds.x1 - render->ibounds.x0;
int h = render->ibounds.y1 - render->ibounds.y0;
- fz_write_header(ctx, render->bander, w, h, render->n, 0, 0, 0, 0);
+ fz_write_header(ctx, render->bander, w, h, render->n, 0, 0, 0, 0, NULL);
}
fz_catch(ctx)
{
diff --git a/source/tools/murun.c b/source/tools/murun.c
index 205e8f91..47cc1884 100644
--- a/source/tools/murun.c
+++ b/source/tools/murun.c
@@ -538,6 +538,18 @@ static struct color ffi_tocolor(js_State *J, int idx)
return c;
}
+static fz_color_params *ffi_tocolorparams(js_State *J, int idx)
+{
+ /* TODO */
+ return NULL;
+}
+
+static void ffi_pushcolorparams(js_State *J, const fz_color_params *color_params)
+{
+ /* TODO */
+ js_pushnull(J);
+}
+
static const char *string_from_cap(fz_linecap cap)
{
switch (cap) {
@@ -771,7 +783,7 @@ typedef struct js_device_s
static void
js_dev_fill_path(fz_context *ctx, fz_device *dev, const fz_path *path, int even_odd, const fz_matrix *ctm,
- fz_colorspace *colorspace, const float *color, float alpha)
+ fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params)
{
js_State *J = ((js_device*)dev)->J;
if (js_try(J))
@@ -782,7 +794,8 @@ js_dev_fill_path(fz_context *ctx, fz_device *dev, const fz_path *path, int even_
js_pushboolean(J, even_odd);
ffi_pushmatrix(J, *ctm);
ffi_pushcolor(J, colorspace, color, alpha);
- js_call(J, 6);
+ ffi_pushcolorparams(J, color_params);
+ js_call(J, 7);
js_pop(J, 1);
}
js_endtry(J);
@@ -809,7 +822,7 @@ js_dev_clip_path(fz_context *ctx, fz_device *dev, const fz_path *path, int even_
static void
js_dev_stroke_path(fz_context *ctx, fz_device *dev, const fz_path *path,
const fz_stroke_state *stroke, const fz_matrix *ctm,
- fz_colorspace *colorspace, const float *color, float alpha)
+ fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params)
{
js_State *J = ((js_device*)dev)->J;
if (js_try(J))
@@ -820,7 +833,8 @@ js_dev_stroke_path(fz_context *ctx, fz_device *dev, const fz_path *path,
ffi_pushstroke(J, stroke);
ffi_pushmatrix(J, *ctm);
ffi_pushcolor(J, colorspace, color, alpha);
- js_call(J, 6);
+ ffi_pushcolorparams(J, color_params);
+ js_call(J, 7);
js_pop(J, 1);
}
js_endtry(J);
@@ -846,7 +860,7 @@ js_dev_clip_stroke_path(fz_context *ctx, fz_device *dev, const fz_path *path, co
static void
js_dev_fill_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_matrix *ctm,
- fz_colorspace *colorspace, const float *color, float alpha)
+ fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params)
{
js_State *J = ((js_device*)dev)->J;
if (js_try(J))
@@ -856,7 +870,8 @@ js_dev_fill_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_
ffi_pushtext(J, text);
ffi_pushmatrix(J, *ctm);
ffi_pushcolor(J, colorspace, color, alpha);
- js_call(J, 5);
+ ffi_pushcolorparams(J, color_params);
+ js_call(J, 6);
js_pop(J, 1);
}
js_endtry(J);
@@ -864,7 +879,7 @@ js_dev_fill_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_
static void
js_dev_stroke_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_stroke_state *stroke,
- const fz_matrix *ctm, fz_colorspace *colorspace, const float *color, float alpha)
+ const fz_matrix *ctm, fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params)
{
js_State *J = ((js_device*)dev)->J;
if (js_try(J))
@@ -875,7 +890,8 @@ js_dev_stroke_text(fz_context *ctx, fz_device *dev, const fz_text *text, const f
ffi_pushstroke(J, stroke);
ffi_pushmatrix(J, *ctm);
ffi_pushcolor(J, colorspace, color, alpha);
- js_call(J, 6);
+ ffi_pushcolorparams(J, color_params);
+ js_call(J, 7);
js_pop(J, 1);
}
js_endtry(J);
@@ -932,7 +948,7 @@ js_dev_ignore_text(fz_context *ctx, fz_device *dev, const fz_text *text, const f
}
static void
-js_dev_fill_shade(fz_context *ctx, fz_device *dev, fz_shade *shade, const fz_matrix *ctm, float alpha)
+js_dev_fill_shade(fz_context *ctx, fz_device *dev, fz_shade *shade, const fz_matrix *ctm, float alpha, const fz_color_params *color_params)
{
js_State *J = ((js_device*)dev)->J;
if (js_try(J))
@@ -942,14 +958,15 @@ js_dev_fill_shade(fz_context *ctx, fz_device *dev, fz_shade *shade, const fz_mat
ffi_pushshade(J, shade);
ffi_pushmatrix(J, *ctm);
js_pushnumber(J, alpha);
- js_call(J, 3);
+ ffi_pushcolorparams(J, color_params);
+ js_call(J, 4);
js_pop(J, 1);
}
js_endtry(J);
}
static void
-js_dev_fill_image(fz_context *ctx, fz_device *dev, fz_image *image, const fz_matrix *ctm, float alpha)
+js_dev_fill_image(fz_context *ctx, fz_device *dev, fz_image *image, const fz_matrix *ctm, float alpha, const fz_color_params *color_params)
{
js_State *J = ((js_device*)dev)->J;
if (js_try(J))
@@ -959,7 +976,8 @@ js_dev_fill_image(fz_context *ctx, fz_device *dev, fz_image *image, const fz_mat
ffi_pushimage(J, image);
ffi_pushmatrix(J, *ctm);
js_pushnumber(J, alpha);
- js_call(J, 3);
+ ffi_pushcolorparams(J, color_params);
+ js_call(J, 4);
js_pop(J, 1);
}
js_endtry(J);
@@ -967,7 +985,7 @@ js_dev_fill_image(fz_context *ctx, fz_device *dev, fz_image *image, const fz_mat
static void
js_dev_fill_image_mask(fz_context *ctx, fz_device *dev, fz_image *image, const fz_matrix *ctm,
- fz_colorspace *colorspace, const float *color, float alpha)
+ fz_colorspace *colorspace, const float *color, float alpha, const fz_color_params *color_params)
{
js_State *J = ((js_device*)dev)->J;
if (js_try(J))
@@ -977,7 +995,8 @@ js_dev_fill_image_mask(fz_context *ctx, fz_device *dev, fz_image *image, const f
ffi_pushimage(J, image);
ffi_pushmatrix(J, *ctm);
ffi_pushcolor(J, colorspace, color, alpha);
- js_call(J, 5);
+ ffi_pushcolorparams(J, color_params);
+ js_call(J, 6);
js_pop(J, 1);
}
js_endtry(J);
@@ -1015,7 +1034,7 @@ js_dev_pop_clip(fz_context *ctx, fz_device *dev)
static void
js_dev_begin_mask(fz_context *ctx, fz_device *dev, const fz_rect *bbox, int luminosity,
- fz_colorspace *colorspace, const float *color)
+ fz_colorspace *colorspace, const float *color, const fz_color_params *color_params)
{
js_State *J = ((js_device*)dev)->J;
if (js_try(J))
@@ -1024,14 +1043,9 @@ js_dev_begin_mask(fz_context *ctx, fz_device *dev, const fz_rect *bbox, int lumi
js_copy(J, -2);
ffi_pushrect(J, *bbox);
js_pushboolean(J, luminosity);
- if (colorspace) {
- ffi_pushcolorspace(J, colorspace);
- ffi_pusharray(J, color, fz_colorspace_n(ctx, colorspace));
- } else {
- js_pushnull(J);
- js_pushnull(J);
- }
- js_call(J, 4);
+ ffi_pushcolor(J, colorspace, color, 1);
+ ffi_pushcolorparams(J, color_params);
+ js_call(J, 6);
js_pop(J, 1);
}
js_endtry(J);
@@ -1178,8 +1192,9 @@ static void ffi_Device_fillPath(js_State *J)
int even_odd = js_toboolean(J, 2);
fz_matrix ctm = ffi_tomatrix(J, 3);
struct color c = ffi_tocolor(J, 4);
+ fz_color_params *color_params = ffi_tocolorparams(J, 7);
fz_try(ctx)
- fz_fill_path(ctx, dev, path, even_odd, &ctm, c.colorspace, c.color, c.alpha);
+ fz_fill_path(ctx, dev, path, even_odd, &ctm, c.colorspace, c.color, c.alpha, color_params);
fz_catch(ctx)
rethrow(J);
}
@@ -1192,8 +1207,9 @@ static void ffi_Device_strokePath(js_State *J)
fz_stroke_state stroke = ffi_tostroke(J, 2);
fz_matrix ctm = ffi_tomatrix(J, 3);
struct color c = ffi_tocolor(J, 4);
+ fz_color_params *color_params = ffi_tocolorparams(J, 7);
fz_try(ctx)
- fz_stroke_path(ctx, dev, path, &stroke, &ctm, c.colorspace, c.color, c.alpha);
+ fz_stroke_path(ctx, dev, path, &stroke, &ctm, c.colorspace, c.color, c.alpha, color_params);
fz_catch(ctx)
rethrow(J);
}
@@ -1231,8 +1247,9 @@ static void ffi_Device_fillText(js_State *J)
fz_text *text = js_touserdata(J, 1, "fz_text");
fz_matrix ctm = ffi_tomatrix(J, 2);
struct color c = ffi_tocolor(J, 3);
+ fz_color_params *color_params = ffi_tocolorparams(J, 6);
fz_try(ctx)
- fz_fill_text(ctx, dev, text, &ctm, c.colorspace, c.color, c.alpha);
+ fz_fill_text(ctx, dev, text, &ctm, c.colorspace, c.color, c.alpha, color_params);
fz_catch(ctx)
rethrow(J);
}
@@ -1245,8 +1262,9 @@ static void ffi_Device_strokeText(js_State *J)
fz_stroke_state stroke = ffi_tostroke(J, 2);
fz_matrix ctm = ffi_tomatrix(J, 3);
struct color c = ffi_tocolor(J, 4);
+ fz_color_params *color_params = ffi_tocolorparams(J, 7);
fz_try(ctx)
- fz_stroke_text(ctx, dev, text, &stroke, &ctm, c.colorspace, c.color, c.alpha);
+ fz_stroke_text(ctx, dev, text, &stroke, &ctm, c.colorspace, c.color, c.alpha, color_params);
fz_catch(ctx)
rethrow(J);
}
@@ -1295,8 +1313,9 @@ static void ffi_Device_fillShade(js_State *J)
fz_shade *shade = js_touserdata(J, 1, "fz_shade");
fz_matrix ctm = ffi_tomatrix(J, 2);
float alpha = js_tonumber(J, 3);
+ fz_color_params *color_params = ffi_tocolorparams(J, 4);
fz_try(ctx)
- fz_fill_shade(ctx, dev, shade, &ctm, alpha);
+ fz_fill_shade(ctx, dev, shade, &ctm, alpha, color_params);
fz_catch(ctx)
rethrow(J);
}
@@ -1308,8 +1327,9 @@ static void ffi_Device_fillImage(js_State *J)
fz_image *image = js_touserdata(J, 1, "fz_image");
fz_matrix ctm = ffi_tomatrix(J, 2);
float alpha = js_tonumber(J, 3);
+ fz_color_params *color_params = ffi_tocolorparams(J, 4);
fz_try(ctx)
- fz_fill_image(ctx, dev, image, &ctm, alpha);
+ fz_fill_image(ctx, dev, image, &ctm, alpha, color_params);
fz_catch(ctx)
rethrow(J);
}
@@ -1321,8 +1341,9 @@ static void ffi_Device_fillImageMask(js_State *J)
fz_image *image = js_touserdata(J, 1, "fz_image");
fz_matrix ctm = ffi_tomatrix(J, 2);
struct color c = ffi_tocolor(J, 3);
+ fz_color_params *color_params = ffi_tocolorparams(J, 6);
fz_try(ctx)
- fz_fill_image_mask(ctx, dev, image, &ctm, c.colorspace, c.color, c.alpha);
+ fz_fill_image_mask(ctx, dev, image, &ctm, c.colorspace, c.color, c.alpha, color_params);
fz_catch(ctx)
rethrow(J);
}
@@ -1356,8 +1377,9 @@ static void ffi_Device_beginMask(js_State *J)
fz_rect area = ffi_torect(J, 1);
int luminosity = js_toboolean(J, 2);
struct color c = ffi_tocolor(J, 3);
+ fz_color_params *color_params = ffi_tocolorparams(J, 6);
fz_try(ctx)
- fz_begin_mask(ctx, dev, &area, luminosity, c.colorspace, c.color);
+ fz_begin_mask(ctx, dev, &area, luminosity, c.colorspace, c.color, color_params);
fz_catch(ctx)
rethrow(J);
}
@@ -4312,25 +4334,25 @@ int murun_main(int argc, char **argv)
{
jsB_propfun(J, "Device.close", ffi_Device_close, 0);
- jsB_propfun(J, "Device.fillPath", ffi_Device_fillPath, 6);
- jsB_propfun(J, "Device.strokePath", ffi_Device_strokePath, 6);
+ jsB_propfun(J, "Device.fillPath", ffi_Device_fillPath, 7);
+ jsB_propfun(J, "Device.strokePath", ffi_Device_strokePath, 7);
jsB_propfun(J, "Device.clipPath", ffi_Device_clipPath, 3);
jsB_propfun(J, "Device.clipStrokePath", ffi_Device_clipStrokePath, 3);
- jsB_propfun(J, "Device.fillText", ffi_Device_fillText, 5);
- jsB_propfun(J, "Device.strokeText", ffi_Device_strokeText, 6);
+ jsB_propfun(J, "Device.fillText", ffi_Device_fillText, 6);
+ jsB_propfun(J, "Device.strokeText", ffi_Device_strokeText, 7);
jsB_propfun(J, "Device.clipText", ffi_Device_clipText, 2);
jsB_propfun(J, "Device.clipStrokeText", ffi_Device_clipStrokeText, 3);
jsB_propfun(J, "Device.ignoreText", ffi_Device_ignoreText, 2);
- jsB_propfun(J, "Device.fillShade", ffi_Device_fillShade, 3);
- jsB_propfun(J, "Device.fillImage", ffi_Device_fillImage, 3);
- jsB_propfun(J, "Device.fillImageMask", ffi_Device_fillImageMask, 5);
+ jsB_propfun(J, "Device.fillShade", ffi_Device_fillShade, 4);
+ jsB_propfun(J, "Device.fillImage", ffi_Device_fillImage, 4);
+ jsB_propfun(J, "Device.fillImageMask", ffi_Device_fillImageMask, 6);
jsB_propfun(J, "Device.clipImageMask", ffi_Device_clipImageMask, 2);
jsB_propfun(J, "Device.popClip", ffi_Device_popClip, 0);
- jsB_propfun(J, "Device.beginMask", ffi_Device_beginMask, 5); /* should be 4 */
+ jsB_propfun(J, "Device.beginMask", ffi_Device_beginMask, 6);
jsB_propfun(J, "Device.endMask", ffi_Device_endMask, 0);
jsB_propfun(J, "Device.beginGroup", ffi_Device_beginGroup, 5);
jsB_propfun(J, "Device.endGroup", ffi_Device_endGroup, 0);
diff --git a/source/tools/pdfextract.c b/source/tools/pdfextract.c
index 49a2747e..984cda16 100644
--- a/source/tools/pdfextract.c
+++ b/source/tools/pdfextract.c
@@ -42,7 +42,7 @@ static void writepixmap(fz_context *ctx, fz_pixmap *pix, char *file, int dorgb)
if (dorgb && pix->colorspace && pix->colorspace != fz_device_rgb(ctx))
{
- rgb = fz_convert_pixmap(ctx, pix, fz_device_rgb(ctx), 1);
+ rgb = fz_convert_pixmap(ctx, pix, fz_device_rgb(ctx), NULL, NULL, NULL /* FIXME */, 1);
pix = rgb;
}
diff --git a/source/xps/xps-common.c b/source/xps/xps-common.c
index 9e590788..cc7fed94 100644
--- a/source/xps/xps-common.c
+++ b/source/xps/xps-common.c
@@ -109,7 +109,7 @@ xps_begin_opacity(fz_context *ctx, xps_document *doc, const fz_matrix *ctm, cons
if (opacity_mask_tag)
{
- fz_begin_mask(ctx, dev, area, 0, NULL, NULL);
+ fz_begin_mask(ctx, dev, area, 0, NULL, NULL, NULL);
xps_parse_brush(ctx, doc, ctm, area, base_uri, dict, opacity_mask_tag);
fz_end_mask(ctx, dev);
}
diff --git a/source/xps/xps-glyphs.c b/source/xps/xps-glyphs.c
index bfe38432..55a8a362 100644
--- a/source/xps/xps-glyphs.c
+++ b/source/xps/xps-glyphs.c
@@ -610,7 +610,7 @@ xps_parse_glyphs(fz_context *ctx, xps_document *doc, const fz_matrix *ctm,
xps_set_color(ctx, doc, colorspace, samples);
fz_fill_text(ctx, dev, text, &local_ctm,
- doc->colorspace, doc->color, doc->alpha);
+ doc->colorspace, doc->color, doc->alpha, NULL);
}
/* If it's a complex brush, use the charpath as a clip mask */
diff --git a/source/xps/xps-gradient.c b/source/xps/xps-gradient.c
index a7a7cf44..349132d5 100644
--- a/source/xps/xps-gradient.c
+++ b/source/xps/xps-gradient.c
@@ -68,7 +68,7 @@ xps_parse_gradient_stops(fz_context *ctx, xps_document *doc, char *base_uri, fz_
xps_parse_color(ctx, doc, base_uri, color, &colorspace, sample);
- fz_convert_color(ctx, fz_device_rgb(ctx), rgb, colorspace, sample + 1);
+ fz_convert_color(ctx, fz_default_color_params(ctx), NULL, fz_device_rgb(ctx), rgb, colorspace, sample + 1);
stops[count].r = rgb[0];
stops[count].g = rgb[1];
@@ -240,7 +240,7 @@ xps_draw_one_radial_gradient(fz_context *ctx, xps_document *doc, const fz_matrix
shade->u.l_or_r.coords[1][1] = y1;
shade->u.l_or_r.coords[1][2] = r1;
- fz_fill_shade(ctx, dev, shade, ctm, 1);
+ fz_fill_shade(ctx, dev, shade, ctm, 1, fz_default_color_params(ctx));
fz_drop_shade(ctx, shade);
}
@@ -279,7 +279,7 @@ xps_draw_one_linear_gradient(fz_context *ctx, xps_document *doc, const fz_matrix
shade->u.l_or_r.coords[1][1] = y1;
shade->u.l_or_r.coords[1][2] = 0;
- fz_fill_shade(ctx, dev, shade, ctm, doc->opacity[doc->opacity_top]);
+ fz_fill_shade(ctx, dev, shade, ctm, doc->opacity[doc->opacity_top], fz_default_color_params(ctx));
fz_drop_shade(ctx, shade);
}
diff --git a/source/xps/xps-image.c b/source/xps/xps-image.c
index 2996b4ee..9408c528 100644
--- a/source/xps/xps-image.c
+++ b/source/xps/xps-image.c
@@ -23,7 +23,7 @@ xps_paint_image_brush(fz_context *ctx, xps_document *doc, const fz_matrix *ctm,
xs = image->w * 96 / image->xres;
ys = image->h * 96 / image->yres;
fz_pre_scale(&local_ctm, xs, ys);
- fz_fill_image(ctx, doc->dev, image, &local_ctm, doc->opacity[doc->opacity_top]);
+ fz_fill_image(ctx, doc->dev, image, &local_ctm, doc->opacity[doc->opacity_top], fz_default_color_params(ctx));
}
static void
diff --git a/source/xps/xps-path.c b/source/xps/xps-path.c
index c60934a2..c9bd64e0 100644
--- a/source/xps/xps-path.c
+++ b/source/xps/xps-path.c
@@ -1002,7 +1002,7 @@ xps_parse_path(fz_context *ctx, xps_document *doc, const fz_matrix *ctm, char *b
xps_set_color(ctx, doc, colorspace, samples);
fz_fill_path(ctx, dev, path, fill_rule == 0, &local_ctm,
- doc->colorspace, doc->color, doc->alpha);
+ doc->colorspace, doc->color, doc->alpha, NULL);
}
if (fill_tag)
@@ -1020,7 +1020,7 @@ xps_parse_path(fz_context *ctx, xps_document *doc, const fz_matrix *ctm, char *b
xps_set_color(ctx, doc, colorspace, samples);
fz_stroke_path(ctx, dev, stroke_path, stroke, &local_ctm,
- doc->colorspace, doc->color, doc->alpha);
+ doc->colorspace, doc->color, doc->alpha, NULL);
}
if (stroke_tag)
diff --git a/thirdparty/lcms2 b/thirdparty/lcms2
new file mode 160000
+Subproject 6b4828a5c9156c2f7a656e69a20ec3d760635c0