diff --git a/jni/devil-1.7.8/Android.mk b/jni/devil-1.7.8/Android.mk index c602188c..4bf6a61c 100644 --- a/jni/devil-1.7.8/Android.mk +++ b/jni/devil-1.7.8/Android.mk @@ -16,7 +16,7 @@ LOCAL_C_INCLUDES := \ ${LOCAL_PATH}/../libpng-1.5.6/ \ ${LOCAL_PATH}/../libmng-1.0.10/ \ ${LOCAL_PATH}/../jpeg-8c/ \ - ${LOCAL_PATH}/../lcms2-2.2/include \ + ${LOCAL_PATH}/../lcms2-2.5/include \ ${LOCAL_PATH}/../tiff-3.9.5/libtiff LOCAL_SRC_FILES := \ diff --git a/jni/lcms2-2.5/AUTHORS b/jni/lcms2-2.5/AUTHORS new file mode 100644 index 00000000..b989606b --- /dev/null +++ b/jni/lcms2-2.5/AUTHORS @@ -0,0 +1,42 @@ + +Main Author +------------ +Marti Maria + + +Contributors +------------ +Bob Friesenhahn +Kai-Uwe Behrmann +Stuart Nixon +Jordi Vilar +Richard Hughes +Auke Nauta +Chris Evans (Google) +Lorenzo Ridolfi +Robin Watts (Artifex) +Shawn Pedersen +Andrew Brygin +Samuli Suominen +Florian Höch +Aurelien Jarno +Claudiu Cebuc +Michael Vhrel (Artifex) +Michal Cihar +Daniel Kaneider +Mateusz Jurczyk (Google) +Paul Miller +Sébastien Léon +Christian Schmitz +XhmikosR +Stanislav Brabec (SuSe) + +Special Thanks +-------------- +Jan Morovic +Jos Vernon (WebSupergoo) +Harald Schneider (Maxon) +Christian Albrecht +Dimitrios Anastassakis +Lemke Software +Tim Zaman \ No newline at end of file diff --git a/jni/lcms2-2.5/Android.mk b/jni/lcms2-2.5/Android.mk new file mode 100644 index 00000000..ef6f5c77 --- /dev/null +++ b/jni/lcms2-2.5/Android.mk @@ -0,0 +1,23 @@ +LOCAL_PATH:= $(call my-dir) + +# libogg +include $(CLEAR_VARS) + +LOCAL_MODULE := liblcms +LOCAL_CFLAGS := -fexceptions -g -Dlinux -Dunix \ + -DHAVE_GCC_DESTRUCTOR=1 -DOPT_GENERIC -DREAL_IS_FLOAT + +LOCAL_CPPFLAGS := ${LOCAL_CFLAGS} + +LOCAL_C_INCLUDES := \ + ${LOCAL_PATH}/include + +LOCAL_SRC_FILES := \ + $(filter-out \ + ,$(subst $(LOCAL_PATH)/,,\ + $(wildcard ${LOCAL_PATH}/src/*.c) )) + +# $(info liblcms: include dirs $(LOCAL_C_INCLUDES)) +# $(info liblcms: src files $(LOCAL_SRC_FILES)) + +include $(BUILD_STATIC_LIBRARY) diff --git a/jni/lcms2-2.5/COPYING b/jni/lcms2-2.5/COPYING new file mode 100644 index 00000000..fda5c9eb --- /dev/null +++ b/jni/lcms2-2.5/COPYING @@ -0,0 +1,8 @@ +Little CMS +Copyright (c) 1998-2011 Marti Maria Saguer + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/jni/lcms2-2.5/ChangeLog b/jni/lcms2-2.5/ChangeLog new file mode 100644 index 00000000..6ef13036 --- /dev/null +++ b/jni/lcms2-2.5/ChangeLog @@ -0,0 +1,127 @@ + + +This is a timeline change log, see features included in each release ABOVE release number + + +----------------------- +2.0 Major version bump +----------------------- + +Fixed a bug on V2 CHAD construction, affects absolute colorimetric intent +Fixed a bug that prevented linkicc to work +Fixed a bug on transicc that made profiles with output colorants info to malfunction +Fixed a bug on Lab + Alpha float formatters, added such predefined formatters as well +Added cmsChangeBufferFormat for backwards compatibility +Added UTILS_UNUSED_PARAMETER for samples +Added a check on jpgicc for NULL transforms +Fixed VC2010, VC2008 projects +Added cmsTagLinkedTo +Fixed some typos in error messages +Peliminary Delphi wrapper +Fixed a bug in tificc in floating point formats +Fixed a bug in device link creation on v4 profiles +Fixed a bug in psid and profile sequence tags +Fixed memory leaks on when recovering from errors +Fixed an issue on curve inversion +Fixed several integer overflow and other integrity checks, thanks to Chris Evans +linkicc now stores the rendering intent in the profile header +Fixed delphi interface +Added Duotone support (Bilinear interpolation) +Fixed a bug on curve reversing when source curves have few points +Added bound check in floating point interpolation + +----------------------- +2.1 Maintenance release +----------------------- + +Fixed severa bugs in absolute colorimetric intent +Removed pthreads need +Updated linkicc to 2.1, cleanup +Fixed some potential issues as NULL dereferencing +Fixed GBD bug (out of bounds memory overwrite) +changed memmove to memcpy in cache for xput improvement +Profiles with weird curves are not prone to p`relinearization optimization. +Added functions to retrieve formatters from transforms +Fixed a bug that made crash black preservation on CMYK2CMYK devicelinks +Added named color functionality +Fixed a bug in black preservation and sligtly non-monotonic curves +Added dictionary metatag support +Fixed a bug on ReadRAWtag +Pascal unit now is supported by Free Pascal Compiler + +----------------------- +2.2 Maintenance release +----------------------- + +Fixed a 0 byte allocation issue in _cmsCreateSubAllocChunk +Fixed encoding for floating point tags in Lab/XYZ +Fixed Absolute colorimetric intent issues +Fixed a bug on the range of data in transicc, when colorant tag is specified +Adding a memory alignment macro for CGATS parser +Updated to ICC spec 4.3 +Added compatibilty with Argyll's CGATS parser + +----------------------- +2.3 Maintenance release +----------------------- + +Fixed a bug in the named color devicelink generation +Fixed uint64 to work in systems without long long native type +Added performance improvements from several contributors, mostly Artifex +Fixed a bug in black preservation checking +Added black point detection algorithm from Adobe paper +Added support for transforms on planar data with different stride +Added a new plug in entry for full transform +Exposed internal overview table for tone curves +gamma 1.0 can now operate in unbounded mode +Fixed a bug in pipeline duplication +Added getPipelineContextID +Added a new plug-in type +Internal stage structs are now accessible through plug-in API +Fixed a bug on ending zero when saving a IT8 to memory +Fixed a bug on IT8 reading of negative numbers. +Increased security checks, thanks to Mateusz Jurczyk, from Google. +Added half float support +Fixed a typo on tificc and jpgicc names, thanks to Elle Stone for reporting. +Fixed a bug on named color profiles. +Added a conditional compilatio flag for "half" support +Fixed a bug in transicc when clot tables are present +Added formatter resolution after xform optimization plugin +added half float variants (ABGR and so) +Fixed a bug in XYZ floating point PCS +Fixed an unitialized read on PatchLUT +Added a check for maximum input channels + +-------------------- +2.4 Featured release +-------------------- + +User defined parametric curves can now be saved in ICC profiles. +RGB profiles using same tone curves for several channels are storing now only one copy of the curve (saves space) +Fixed a multithead bug on optimization (StageDEF) +Fixed some 64 bit warnings on size_t to uint32 conversions +update black point detection algorithm to reflect ICC changes +Added new cmsPlugInTHR() and fixed some race conditions (thanks to Artifex) +Added error descriptions on cmsSmoothToneCurve +Fixed a bug on big endian platforms not supporting uint64 or long long. +Fixed some bugs on floating point curves. +Several improvements in cgats parser. +Several minor issues found by cppcheck +Fixed devicelink generation for 8 bits +Added a reference for Mac MLU tag +Added a way to read the profile creator from header +Added identity curves support for write V2 LUT +More changes from Artifex +Added TIFF Lab16 handling on tifficc +Added some fixes from XhmikosR +Fixed a bug in parametric curves +Remove spurious tabs added by git merge of pull request +Added support for VS2012 +Added a simple project for cppcheck +Rendering intent used when creating the transform is now propagated to profile header in cmsTransform2Devicelink. This is because 7.2.15 in spec 4.3 +Transform2Devicelink now keeps white point when guessing deviceclass is enabled +Added some checks for non-happy path, mostly failing mallocs + +----------------------- +2.5 Maintenance release +----------------------- diff --git a/jni/lcms2-2.5/INSTALL b/jni/lcms2-2.5/INSTALL new file mode 100644 index 00000000..2e5ee4ad --- /dev/null +++ b/jni/lcms2-2.5/INSTALL @@ -0,0 +1,2 @@ + + Please see the documentation in doc folder diff --git a/jni/lcms2-2.5/Lib/BC/BC.txt b/jni/lcms2-2.5/Lib/BC/BC.txt new file mode 100644 index 00000000..146228d6 --- /dev/null +++ b/jni/lcms2-2.5/Lib/BC/BC.txt @@ -0,0 +1 @@ +BC \ No newline at end of file diff --git a/jni/lcms2-2.5/Lib/MS/MS.TXT b/jni/lcms2-2.5/Lib/MS/MS.TXT new file mode 100644 index 00000000..32dfbc9f --- /dev/null +++ b/jni/lcms2-2.5/Lib/MS/MS.TXT @@ -0,0 +1 @@ +MS \ No newline at end of file diff --git a/jni/lcms2-2.5/Makefile.am b/jni/lcms2-2.5/Makefile.am new file mode 100644 index 00000000..e0cba529 --- /dev/null +++ b/jni/lcms2-2.5/Makefile.am @@ -0,0 +1,31 @@ +# +# Top-Level Makefile for building LittleCMS 2 +# + +# Don't require all the GNU mandated files +AUTOMAKE_OPTIONS = 1.7.2 dist-zip foreign + +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ + +# Directories containing Makefiles to 'make' +SUBDIRS = src include utils/tificc utils/transicc utils/linkicc utils/jpgicc utils/psicc testbed + +# Additional files to distribute +EXTRA_DIST = AUTHORS COPYING ChangeLog doc Projects include bin Lib INSTALL README.1ST lcms2.pc.in + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = lcms2.pc + +# Make sure get rid of VC stuff... +clean-local: + find Projects -name "*.user" | xargs rm -rf + find Projects -name "Release" | xargs rm -rf + find Projects -name "Debug" | xargs rm -rf + find Projects -name "*.aps" | xargs rm -rf + find Projects -name "*.suo" | xargs rm -rf + find Projects -name "*.log" | xargs rm -rf + find Projects -name "*.sdf" | xargs rm -rf + find Projects -name "*.opensdf" | xargs rm -rf + find Projects -name "*.log" | xargs rm -rf + find Projects -name "ipch" | xargs rm -rf diff --git a/jni/lcms2-2.5/Makefile.in b/jni/lcms2-2.5/Makefile.in new file mode 100644 index 00000000..89b9605b --- /dev/null +++ b/jni/lcms2-2.5/Makefile.in @@ -0,0 +1,843 @@ +# Makefile.in generated by automake 1.11.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# +# Top-Level Makefile for building LittleCMS 2 +# + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = . +DIST_COMMON = $(am__configure_deps) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(srcdir)/lcms2.pc.in \ + $(top_srcdir)/configure AUTHORS COPYING ChangeLog INSTALL \ + config.guess config.sub depcomp install-sh ltmain.sh missing +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno config.status.lineno +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = lcms2.pc +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(pkgconfigdir)" +DATA = $(pkgconfig_DATA) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + distdir dist dist-all distcheck +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) +am__remove_distdir = \ + if test -d "$(distdir)"; then \ + find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -rf "$(distdir)" \ + || { sleep 5 && rm -rf "$(distdir)"; }; \ + else :; fi +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +DIST_ARCHIVES = $(distdir).tar.gz $(distdir).zip +GZIP_ENV = --best +distuninstallcheck_listfiles = find . -type f -print +am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ + | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' +distcleancheck_listfiles = find . -type f -print +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +JPEGICC_DEPLIBS = @JPEGICC_DEPLIBS@ +LCMS_LIB_DEPLIBS = @LCMS_LIB_DEPLIBS@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBRARY_AGE = @LIBRARY_AGE@ +LIBRARY_CURRENT = @LIBRARY_CURRENT@ +LIBRARY_REVISION = @LIBRARY_REVISION@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBTOOL_DEPS = @LIBTOOL_DEPS@ +LIB_JPEG = @LIB_JPEG@ +LIB_MATH = @LIB_MATH@ +LIB_TIFF = @LIB_TIFF@ +LIB_ZLIB = @LIB_ZLIB@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +TIFFICC_DEPLIBS = @TIFFICC_DEPLIBS@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +inline = @inline@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ + +# Don't require all the GNU mandated files +AUTOMAKE_OPTIONS = 1.7.2 dist-zip foreign + +# Directories containing Makefiles to 'make' +SUBDIRS = src include utils/tificc utils/transicc utils/linkicc utils/jpgicc utils/psicc testbed + +# Additional files to distribute +EXTRA_DIST = AUTHORS COPYING ChangeLog doc Projects include bin Lib INSTALL README.1ST lcms2.pc.in +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = lcms2.pc +all: all-recursive + +.SUFFIXES: +am--refresh: Makefile + @: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ + $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + echo ' $(SHELL) ./config.status'; \ + $(SHELL) ./config.status;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + $(am__cd) $(srcdir) && $(AUTOCONF) +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) +$(am__aclocal_m4_deps): +lcms2.pc: $(top_builddir)/config.status $(srcdir)/lcms2.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $@ + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool config.lt +install-pkgconfigDATA: $(pkgconfig_DATA) + @$(NORMAL_INSTALL) + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \ + done + +uninstall-pkgconfigDATA: + @$(NORMAL_UNINSTALL) + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir) + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +$(RECURSIVE_CLEAN_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + $(am__remove_distdir) + test -d "$(distdir)" || mkdir "$(distdir)" + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done + -test -n "$(am__skip_mode_fix)" \ + || find "$(distdir)" -type d ! -perm -755 \ + -exec chmod u+rwx,go+rx {} \; -o \ + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r "$(distdir)" +dist-gzip: distdir + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__remove_distdir) + +dist-bzip2: distdir + tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 + $(am__remove_distdir) + +dist-lzip: distdir + tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz + $(am__remove_distdir) + +dist-lzma: distdir + tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma + $(am__remove_distdir) + +dist-xz: distdir + tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz + $(am__remove_distdir) + +dist-tarZ: distdir + tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z + $(am__remove_distdir) + +dist-shar: distdir + shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz + $(am__remove_distdir) +dist-zip: distdir + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__remove_distdir) + +dist dist-all: distdir + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__remove_distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + case '$(DIST_ARCHIVES)' in \ + *.tar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ + *.tar.bz2*) \ + bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.lzma*) \ + lzma -dc $(distdir).tar.lzma | $(am__untar) ;;\ + *.tar.lz*) \ + lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ + *.tar.xz*) \ + xz -dc $(distdir).tar.xz | $(am__untar) ;;\ + *.tar.Z*) \ + uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ + *.shar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ + *.zip*) \ + unzip $(distdir).zip ;;\ + esac + chmod -R a-w $(distdir); chmod u+w $(distdir) + mkdir $(distdir)/_build + mkdir $(distdir)/_inst + chmod a-w $(distdir) + test -d $(distdir)/_build || exit 0; \ + dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ + && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ + && am__cwd=`pwd` \ + && $(am__cd) $(distdir)/_build \ + && ../configure --srcdir=.. --prefix="$$dc_install_base" \ + $(AM_DISTCHECK_CONFIGURE_FLAGS) \ + $(DISTCHECK_CONFIGURE_FLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ + distuninstallcheck \ + && chmod -R a-w "$$dc_install_base" \ + && ({ \ + (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ + distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ + } || { rm -rf "$$dc_destdir"; exit 1; }) \ + && rm -rf "$$dc_destdir" \ + && $(MAKE) $(AM_MAKEFLAGS) dist \ + && rm -rf $(DIST_ARCHIVES) \ + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ + && cd "$$am__cwd" \ + || exit 1 + $(am__remove_distdir) + @(echo "$(distdir) archives ready for distribution: "; \ + list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ + sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' +distuninstallcheck: + @test -n '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: trying to run $@ with an empty' \ + '$$(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + $(am__cd) '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left after uninstall:" ; \ + if test -n "$(DESTDIR)"; then \ + echo " (check DESTDIR support)"; \ + fi ; \ + $(distuninstallcheck_listfiles) ; \ + exit 1; } >&2 +distcleancheck: distclean + @if test '$(srcdir)' = . ; then \ + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ + exit 1 ; \ + fi + @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left in build directory after distclean:" ; \ + $(distcleancheck_listfiles) ; \ + exit 1; } >&2 +check-am: all-am +check: check-recursive +all-am: Makefile $(DATA) +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(pkgconfigdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool clean-local mostlyclean-am + +distclean: distclean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-libtool \ + distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: install-pkgconfigDATA + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf $(top_srcdir)/autom4te.cache + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-pkgconfigDATA + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \ + install-am install-strip tags-recursive + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am am--refresh check check-am clean clean-generic \ + clean-libtool clean-local ctags ctags-recursive dist dist-all \ + dist-bzip2 dist-gzip dist-lzip dist-lzma dist-shar dist-tarZ \ + dist-xz dist-zip distcheck distclean distclean-generic \ + distclean-libtool distclean-tags distcleancheck distdir \ + distuninstallcheck dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-pkgconfigDATA install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-recursive \ + uninstall uninstall-am uninstall-pkgconfigDATA + + +# Make sure get rid of VC stuff... +clean-local: + find Projects -name "*.user" | xargs rm -rf + find Projects -name "Release" | xargs rm -rf + find Projects -name "Debug" | xargs rm -rf + find Projects -name "*.aps" | xargs rm -rf + find Projects -name "*.suo" | xargs rm -rf + find Projects -name "*.log" | xargs rm -rf + find Projects -name "*.sdf" | xargs rm -rf + find Projects -name "*.opensdf" | xargs rm -rf + find Projects -name "*.log" | xargs rm -rf + find Projects -name "ipch" | xargs rm -rf + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/jni/lcms2-2.5/README.1ST b/jni/lcms2-2.5/README.1ST new file mode 100644 index 00000000..2e5ee4ad --- /dev/null +++ b/jni/lcms2-2.5/README.1ST @@ -0,0 +1,2 @@ + + Please see the documentation in doc folder diff --git a/jni/lcms2-2.5/aclocal.m4 b/jni/lcms2-2.5/aclocal.m4 new file mode 100644 index 00000000..a6cac90b --- /dev/null +++ b/jni/lcms2-2.5/aclocal.m4 @@ -0,0 +1,9438 @@ +# generated automatically by aclocal 1.11.6 -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, +# 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, +# Inc. +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, +[m4_warning([this file was generated for autoconf 2.69. +You have another version of autoconf. It may work, but is not guaranteed to. +If you have problems, you may need to regenerate the build system entirely. +To do so, use the procedure documented by the package, typically `autoreconf'.])]) + +# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, +# 2006, 2007, 2008, 2009, 2010 Free Software Foundation, +# Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +m4_define([_LT_COPYING], [dnl +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, +# 2006, 2007, 2008, 2009, 2010 Free Software Foundation, +# Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is part of GNU Libtool. +# +# GNU Libtool is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Libtool; see the file COPYING. If not, a copy +# can be downloaded from http://www.gnu.org/licenses/gpl.html, or +# obtained by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +]) + +# serial 57 LT_INIT + + +# LT_PREREQ(VERSION) +# ------------------ +# Complain and exit if this libtool version is less that VERSION. +m4_defun([LT_PREREQ], +[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, + [m4_default([$3], + [m4_fatal([Libtool version $1 or higher is required], + 63)])], + [$2])]) + + +# _LT_CHECK_BUILDDIR +# ------------------ +# Complain if the absolute build directory name contains unusual characters +m4_defun([_LT_CHECK_BUILDDIR], +[case `pwd` in + *\ * | *\ *) + AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; +esac +]) + + +# LT_INIT([OPTIONS]) +# ------------------ +AC_DEFUN([LT_INIT], +[AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT +AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +AC_BEFORE([$0], [LT_LANG])dnl +AC_BEFORE([$0], [LT_OUTPUT])dnl +AC_BEFORE([$0], [LTDL_INIT])dnl +m4_require([_LT_CHECK_BUILDDIR])dnl + +dnl Autoconf doesn't catch unexpanded LT_ macros by default: +m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl +m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl +dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 +dnl unless we require an AC_DEFUNed macro: +AC_REQUIRE([LTOPTIONS_VERSION])dnl +AC_REQUIRE([LTSUGAR_VERSION])dnl +AC_REQUIRE([LTVERSION_VERSION])dnl +AC_REQUIRE([LTOBSOLETE_VERSION])dnl +m4_require([_LT_PROG_LTMAIN])dnl + +_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) + +dnl Parse OPTIONS +_LT_SET_OPTIONS([$0], [$1]) + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ltmain" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' +AC_SUBST(LIBTOOL)dnl + +_LT_SETUP + +# Only expand once: +m4_define([LT_INIT]) +])# LT_INIT + +# Old names: +AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) +AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PROG_LIBTOOL], []) +dnl AC_DEFUN([AM_PROG_LIBTOOL], []) + + +# _LT_CC_BASENAME(CC) +# ------------------- +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +m4_defun([_LT_CC_BASENAME], +[for cc_temp in $1""; do + case $cc_temp in + compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; + distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +]) + + +# _LT_FILEUTILS_DEFAULTS +# ---------------------- +# It is okay to use these file commands and assume they have been set +# sensibly after `m4_require([_LT_FILEUTILS_DEFAULTS])'. +m4_defun([_LT_FILEUTILS_DEFAULTS], +[: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} +])# _LT_FILEUTILS_DEFAULTS + + +# _LT_SETUP +# --------- +m4_defun([_LT_SETUP], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl + +_LT_DECL([], [host_alias], [0], [The host system])dnl +_LT_DECL([], [host], [0])dnl +_LT_DECL([], [host_os], [0])dnl +dnl +_LT_DECL([], [build_alias], [0], [The build system])dnl +_LT_DECL([], [build], [0])dnl +_LT_DECL([], [build_os], [0])dnl +dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +dnl +AC_REQUIRE([AC_PROG_LN_S])dnl +test -z "$LN_S" && LN_S="ln -s" +_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl +dnl +AC_REQUIRE([LT_CMD_MAX_LEN])dnl +_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl +_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl +dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl +m4_require([_LT_CMD_RELOAD])dnl +m4_require([_LT_CHECK_MAGIC_METHOD])dnl +m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl +m4_require([_LT_CMD_OLD_ARCHIVE])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_WITH_SYSROOT])dnl + +_LT_CONFIG_LIBTOOL_INIT([ +# See if we are running on zsh, and set the options which allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi +]) +if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi + +_LT_CHECK_OBJDIR + +m4_require([_LT_TAG_COMPILER])dnl + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld="$lt_cv_prog_gnu_ld" + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +_LT_CC_BASENAME([$compiler]) + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + _LT_PATH_MAGIC + fi + ;; +esac + +# Use C for the default configuration in the libtool script +LT_SUPPORTED_TAG([CC]) +_LT_LANG_C_CONFIG +_LT_LANG_DEFAULT_CONFIG +_LT_CONFIG_COMMANDS +])# _LT_SETUP + + +# _LT_PREPARE_SED_QUOTE_VARS +# -------------------------- +# Define a few sed substitution that help us do robust quoting. +m4_defun([_LT_PREPARE_SED_QUOTE_VARS], +[# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\([["`\\]]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' +]) + +# _LT_PROG_LTMAIN +# --------------- +# Note that this code is called both from `configure', and `config.status' +# now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, +# `config.status' has no value for ac_aux_dir unless we are using Automake, +# so we pass a copy along to make sure it has a sensible value anyway. +m4_defun([_LT_PROG_LTMAIN], +[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl +_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) +ltmain="$ac_aux_dir/ltmain.sh" +])# _LT_PROG_LTMAIN + + + +# So that we can recreate a full libtool script including additional +# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS +# in macros and then make a single call at the end using the `libtool' +# label. + + +# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) +# ---------------------------------------- +# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL_INIT], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_INIT], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_INIT]) + + +# _LT_CONFIG_LIBTOOL([COMMANDS]) +# ------------------------------ +# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) + + +# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) +# ----------------------------------------------------- +m4_defun([_LT_CONFIG_SAVE_COMMANDS], +[_LT_CONFIG_LIBTOOL([$1]) +_LT_CONFIG_LIBTOOL_INIT([$2]) +]) + + +# _LT_FORMAT_COMMENT([COMMENT]) +# ----------------------------- +# Add leading comment marks to the start of each line, and a trailing +# full-stop to the whole comment if one is not present already. +m4_define([_LT_FORMAT_COMMENT], +[m4_ifval([$1], [ +m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], + [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) +)]) + + + + + +# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) +# ------------------------------------------------------------------- +# CONFIGNAME is the name given to the value in the libtool script. +# VARNAME is the (base) name used in the configure script. +# VALUE may be 0, 1 or 2 for a computed quote escaped value based on +# VARNAME. Any other value will be used directly. +m4_define([_LT_DECL], +[lt_if_append_uniq([lt_decl_varnames], [$2], [, ], + [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], + [m4_ifval([$1], [$1], [$2])]) + lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) + m4_ifval([$4], + [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) + lt_dict_add_subkey([lt_decl_dict], [$2], + [tagged?], [m4_ifval([$5], [yes], [no])])]) +]) + + +# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) +# -------------------------------------------------------- +m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) + + +# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_tag_varnames], +[_lt_decl_filter([tagged?], [yes], $@)]) + + +# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) +# --------------------------------------------------------- +m4_define([_lt_decl_filter], +[m4_case([$#], + [0], [m4_fatal([$0: too few arguments: $#])], + [1], [m4_fatal([$0: too few arguments: $#: $1])], + [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], + [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], + [lt_dict_filter([lt_decl_dict], $@)])[]dnl +]) + + +# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) +# -------------------------------------------------- +m4_define([lt_decl_quote_varnames], +[_lt_decl_filter([value], [1], $@)]) + + +# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_dquote_varnames], +[_lt_decl_filter([value], [2], $@)]) + + +# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_varnames_tagged], +[m4_assert([$# <= 2])dnl +_$0(m4_quote(m4_default([$1], [[, ]])), + m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), + m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) +m4_define([_lt_decl_varnames_tagged], +[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) + + +# lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_all_varnames], +[_$0(m4_quote(m4_default([$1], [[, ]])), + m4_if([$2], [], + m4_quote(lt_decl_varnames), + m4_quote(m4_shift($@))))[]dnl +]) +m4_define([_lt_decl_all_varnames], +[lt_join($@, lt_decl_varnames_tagged([$1], + lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl +]) + + +# _LT_CONFIG_STATUS_DECLARE([VARNAME]) +# ------------------------------------ +# Quote a variable value, and forward it to `config.status' so that its +# declaration there will have the same value as in `configure'. VARNAME +# must have a single quote delimited value for this to work. +m4_define([_LT_CONFIG_STATUS_DECLARE], +[$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) + + +# _LT_CONFIG_STATUS_DECLARATIONS +# ------------------------------ +# We delimit libtool config variables with single quotes, so when +# we write them to config.status, we have to be sure to quote all +# embedded single quotes properly. In configure, this macro expands +# each variable declared with _LT_DECL (and _LT_TAGDECL) into: +# +# ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' +m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], +[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), + [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAGS +# ---------------- +# Output comment and list of tags supported by the script +m4_defun([_LT_LIBTOOL_TAGS], +[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl +available_tags="_LT_TAGS"dnl +]) + + +# _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) +# ----------------------------------- +# Extract the dictionary values for VARNAME (optionally with TAG) and +# expand to a commented shell variable setting: +# +# # Some comment about what VAR is for. +# visible_name=$lt_internal_name +m4_define([_LT_LIBTOOL_DECLARE], +[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], + [description])))[]dnl +m4_pushdef([_libtool_name], + m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl +m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), + [0], [_libtool_name=[$]$1], + [1], [_libtool_name=$lt_[]$1], + [2], [_libtool_name=$lt_[]$1], + [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl +m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl +]) + + +# _LT_LIBTOOL_CONFIG_VARS +# ----------------------- +# Produce commented declarations of non-tagged libtool config variables +# suitable for insertion in the LIBTOOL CONFIG section of the `libtool' +# script. Tagged libtool config variables (even for the LIBTOOL CONFIG +# section) are produced by _LT_LIBTOOL_TAG_VARS. +m4_defun([_LT_LIBTOOL_CONFIG_VARS], +[m4_foreach([_lt_var], + m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAG_VARS(TAG) +# ------------------------- +m4_define([_LT_LIBTOOL_TAG_VARS], +[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) + + +# _LT_TAGVAR(VARNAME, [TAGNAME]) +# ------------------------------ +m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) + + +# _LT_CONFIG_COMMANDS +# ------------------- +# Send accumulated output to $CONFIG_STATUS. Thanks to the lists of +# variables for single and double quote escaping we saved from calls +# to _LT_DECL, we can put quote escaped variables declarations +# into `config.status', and then the shell code to quote escape them in +# for loops in `config.status'. Finally, any additional code accumulated +# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. +m4_defun([_LT_CONFIG_COMMANDS], +[AC_PROVIDE_IFELSE([LT_OUTPUT], + dnl If the libtool generation code has been placed in $CONFIG_LT, + dnl instead of duplicating it all over again into config.status, + dnl then we will have config.status run $CONFIG_LT later, so it + dnl needs to know what name is stored there: + [AC_CONFIG_COMMANDS([libtool], + [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], + dnl If the libtool generation code is destined for config.status, + dnl expand the accumulated commands and init code now: + [AC_CONFIG_COMMANDS([libtool], + [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) +])#_LT_CONFIG_COMMANDS + + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], +[ + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +_LT_CONFIG_STATUS_DECLARATIONS +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$[]1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_quote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_dquote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +_LT_OUTPUT_LIBTOOL_INIT +]) + +# _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) +# ------------------------------------ +# Generate a child script FILE with all initialization necessary to +# reuse the environment learned by the parent script, and make the +# file executable. If COMMENT is supplied, it is inserted after the +# `#!' sequence but before initialization text begins. After this +# macro, additional text can be appended to FILE to form the body of +# the child script. The macro ends with non-zero status if the +# file could not be fully written (such as if the disk is full). +m4_ifdef([AS_INIT_GENERATED], +[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], +[m4_defun([_LT_GENERATED_FILE_INIT], +[m4_require([AS_PREPARE])]dnl +[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl +[lt_write_fail=0 +cat >$1 <<_ASEOF || lt_write_fail=1 +#! $SHELL +# Generated by $as_me. +$2 +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$1 <<\_ASEOF || lt_write_fail=1 +AS_SHELL_SANITIZE +_AS_PREPARE +exec AS_MESSAGE_FD>&1 +_ASEOF +test $lt_write_fail = 0 && chmod +x $1[]dnl +m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT + +# LT_OUTPUT +# --------- +# This macro allows early generation of the libtool script (before +# AC_OUTPUT is called), incase it is used in configure for compilation +# tests. +AC_DEFUN([LT_OUTPUT], +[: ${CONFIG_LT=./config.lt} +AC_MSG_NOTICE([creating $CONFIG_LT]) +_LT_GENERATED_FILE_INIT(["$CONFIG_LT"], +[# Run this file to recreate a libtool stub with the current configuration.]) + +cat >>"$CONFIG_LT" <<\_LTEOF +lt_cl_silent=false +exec AS_MESSAGE_LOG_FD>>config.log +{ + echo + AS_BOX([Running $as_me.]) +} >&AS_MESSAGE_LOG_FD + +lt_cl_help="\ +\`$as_me' creates a local libtool stub from the current configuration, +for use in further configure time tests before the real libtool is +generated. + +Usage: $[0] [[OPTIONS]] + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + +Report bugs to ." + +lt_cl_version="\ +m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl +m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) +configured by $[0], generated by m4_PACKAGE_STRING. + +Copyright (C) 2010 Free Software Foundation, Inc. +This config.lt script is free software; the Free Software Foundation +gives unlimited permision to copy, distribute and modify it." + +while test $[#] != 0 +do + case $[1] in + --version | --v* | -V ) + echo "$lt_cl_version"; exit 0 ;; + --help | --h* | -h ) + echo "$lt_cl_help"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --quiet | --q* | --silent | --s* | -q ) + lt_cl_silent=: ;; + + -*) AC_MSG_ERROR([unrecognized option: $[1] +Try \`$[0] --help' for more information.]) ;; + + *) AC_MSG_ERROR([unrecognized argument: $[1] +Try \`$[0] --help' for more information.]) ;; + esac + shift +done + +if $lt_cl_silent; then + exec AS_MESSAGE_FD>/dev/null +fi +_LTEOF + +cat >>"$CONFIG_LT" <<_LTEOF +_LT_OUTPUT_LIBTOOL_COMMANDS_INIT +_LTEOF + +cat >>"$CONFIG_LT" <<\_LTEOF +AC_MSG_NOTICE([creating $ofile]) +_LT_OUTPUT_LIBTOOL_COMMANDS +AS_EXIT(0) +_LTEOF +chmod +x "$CONFIG_LT" + +# configure is writing to config.log, but config.lt does its own redirection, +# appending to config.log, which fails on DOS, as config.log is still kept +# open by configure. Here we exec the FD to /dev/null, effectively closing +# config.log, so it can be properly (re)opened and appended to by config.lt. +lt_cl_success=: +test "$silent" = yes && + lt_config_lt_args="$lt_config_lt_args --quiet" +exec AS_MESSAGE_LOG_FD>/dev/null +$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false +exec AS_MESSAGE_LOG_FD>>config.log +$lt_cl_success || AS_EXIT(1) +])# LT_OUTPUT + + +# _LT_CONFIG(TAG) +# --------------- +# If TAG is the built-in tag, create an initial libtool script with a +# default configuration from the untagged config vars. Otherwise add code +# to config.status for appending the configuration named by TAG from the +# matching tagged config vars. +m4_defun([_LT_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_CONFIG_SAVE_COMMANDS([ + m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl + m4_if(_LT_TAG, [C], [ + # See if we are running on zsh, and set the options which allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + + cfgfile="${ofile}T" + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL + +# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +_LT_COPYING +_LT_LIBTOOL_TAGS + +# ### BEGIN LIBTOOL CONFIG +_LT_LIBTOOL_CONFIG_VARS +_LT_LIBTOOL_TAG_VARS +# ### END LIBTOOL CONFIG + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + _LT_PROG_LTMAIN + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + _LT_PROG_REPLACE_SHELLFNS + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" +], +[cat <<_LT_EOF >> "$ofile" + +dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded +dnl in a comment (ie after a #). +# ### BEGIN LIBTOOL TAG CONFIG: $1 +_LT_LIBTOOL_TAG_VARS(_LT_TAG) +# ### END LIBTOOL TAG CONFIG: $1 +_LT_EOF +])dnl /m4_if +], +[m4_if([$1], [], [ + PACKAGE='$PACKAGE' + VERSION='$VERSION' + TIMESTAMP='$TIMESTAMP' + RM='$RM' + ofile='$ofile'], []) +])dnl /_LT_CONFIG_SAVE_COMMANDS +])# _LT_CONFIG + + +# LT_SUPPORTED_TAG(TAG) +# --------------------- +# Trace this macro to discover what tags are supported by the libtool +# --tag option, using: +# autoconf --trace 'LT_SUPPORTED_TAG:$1' +AC_DEFUN([LT_SUPPORTED_TAG], []) + + +# C support is built-in for now +m4_define([_LT_LANG_C_enabled], []) +m4_define([_LT_TAGS], []) + + +# LT_LANG(LANG) +# ------------- +# Enable libtool support for the given language if not already enabled. +AC_DEFUN([LT_LANG], +[AC_BEFORE([$0], [LT_OUTPUT])dnl +m4_case([$1], + [C], [_LT_LANG(C)], + [C++], [_LT_LANG(CXX)], + [Java], [_LT_LANG(GCJ)], + [Fortran 77], [_LT_LANG(F77)], + [Fortran], [_LT_LANG(FC)], + [Windows Resource], [_LT_LANG(RC)], + [m4_ifdef([_LT_LANG_]$1[_CONFIG], + [_LT_LANG($1)], + [m4_fatal([$0: unsupported language: "$1"])])])dnl +])# LT_LANG + + +# _LT_LANG(LANGNAME) +# ------------------ +m4_defun([_LT_LANG], +[m4_ifdef([_LT_LANG_]$1[_enabled], [], + [LT_SUPPORTED_TAG([$1])dnl + m4_append([_LT_TAGS], [$1 ])dnl + m4_define([_LT_LANG_]$1[_enabled], [])dnl + _LT_LANG_$1_CONFIG($1)])dnl +])# _LT_LANG + + +# _LT_LANG_DEFAULT_CONFIG +# ----------------------- +m4_defun([_LT_LANG_DEFAULT_CONFIG], +[AC_PROVIDE_IFELSE([AC_PROG_CXX], + [LT_LANG(CXX)], + [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) + +AC_PROVIDE_IFELSE([AC_PROG_F77], + [LT_LANG(F77)], + [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) + +AC_PROVIDE_IFELSE([AC_PROG_FC], + [LT_LANG(FC)], + [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) + +dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal +dnl pulling things in needlessly. +AC_PROVIDE_IFELSE([AC_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([LT_PROG_GCJ], + [LT_LANG(GCJ)], + [m4_ifdef([AC_PROG_GCJ], + [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([A][M_PROG_GCJ], + [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([LT_PROG_GCJ], + [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) + +AC_PROVIDE_IFELSE([LT_PROG_RC], + [LT_LANG(RC)], + [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) +])# _LT_LANG_DEFAULT_CONFIG + +# Obsolete macros: +AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) +AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) +AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) +AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) +AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_CXX], []) +dnl AC_DEFUN([AC_LIBTOOL_F77], []) +dnl AC_DEFUN([AC_LIBTOOL_FC], []) +dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) +dnl AC_DEFUN([AC_LIBTOOL_RC], []) + + +# _LT_TAG_COMPILER +# ---------------- +m4_defun([_LT_TAG_COMPILER], +[AC_REQUIRE([AC_PROG_CC])dnl + +_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl +_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl +_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl +_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC +])# _LT_TAG_COMPILER + + +# _LT_COMPILER_BOILERPLATE +# ------------------------ +# Check for compiler boilerplate output or warnings with +# the simple compiler test code. +m4_defun([_LT_COMPILER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* +])# _LT_COMPILER_BOILERPLATE + + +# _LT_LINKER_BOILERPLATE +# ---------------------- +# Check for linker boilerplate output or warnings with +# the simple link test code. +m4_defun([_LT_LINKER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* +])# _LT_LINKER_BOILERPLATE + +# _LT_REQUIRED_DARWIN_CHECKS +# ------------------------- +m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ + case $host_os in + rhapsody* | darwin*) + AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) + AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) + AC_CHECK_TOOL([LIPO], [lipo], [:]) + AC_CHECK_TOOL([OTOOL], [otool], [:]) + AC_CHECK_TOOL([OTOOL64], [otool64], [:]) + _LT_DECL([], [DSYMUTIL], [1], + [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) + _LT_DECL([], [NMEDIT], [1], + [Tool to change global to local symbols on Mac OS X]) + _LT_DECL([], [LIPO], [1], + [Tool to manipulate fat objects and archives on Mac OS X]) + _LT_DECL([], [OTOOL], [1], + [ldd/readelf like tool for Mach-O binaries on Mac OS X]) + _LT_DECL([], [OTOOL64], [1], + [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) + + AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], + [lt_cv_apple_cc_single_mod=no + if test -z "${LT_MULTI_MODULE}"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi]) + AC_CACHE_CHECK([for -exported_symbols_list linker flag], + [lt_cv_ld_exported_symbols_list], + [lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [lt_cv_ld_exported_symbols_list=yes], + [lt_cv_ld_exported_symbols_list=no]) + LDFLAGS="$save_LDFLAGS" + ]) + AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], + [lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD + echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD + $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD + echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD + $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -f conftest && test ! -s conftest.err && test $_lt_result = 0 && $GREP forced_load conftest 2>&1 >/dev/null; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + ]) + case $host_os in + rhapsody* | darwin1.[[012]]) + _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + 10.[[012]]*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test "$lt_cv_apple_cc_single_mod" = "yes"; then + _lt_dar_single_mod='$single_module' + fi + if test "$lt_cv_ld_exported_symbols_list" = "yes"; then + _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac +]) + + +# _LT_DARWIN_LINKER_FEATURES +# -------------------------- +# Checks for linker and compiler features on darwin +m4_defun([_LT_DARWIN_LINKER_FEATURES], +[ + m4_require([_LT_REQUIRED_DARWIN_CHECKS]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_automatic, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + if test "$lt_cv_ld_force_load" = "yes"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='' + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined" + case $cc_basename in + ifort*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test "$_lt_dar_can_shared" = "yes"; then + output_verbose_link_cmd=func_echo_all + _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" + _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" + _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" + m4_if([$1], [CXX], +[ if test "$lt_cv_apple_cc_single_mod" != "yes"; then + _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" + fi +],[]) + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi +]) + +# _LT_SYS_MODULE_PATH_AIX([TAGNAME]) +# ---------------------------------- +# Links a minimal program and checks the executable +# for the system default hardcoded library path. In most cases, +# this is /usr/lib:/lib, but when the MPI compilers are used +# the location of the communication and MPI libs are included too. +# If we don't find anything, use the default library path according +# to the aix ld manual. +# Store the results from the different compilers for each TAGNAME. +# Allow to override them for all tags through lt_cv_aix_libpath. +m4_defun([_LT_SYS_MODULE_PATH_AIX], +[m4_require([_LT_DECL_SED])dnl +if test "${lt_cv_aix_libpath+set}" = set; then + aix_libpath=$lt_cv_aix_libpath +else + AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], + [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ + lt_aix_libpath_sed='[ + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }]' + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi],[]) + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])="/usr/lib:/lib" + fi + ]) + aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) +fi +])# _LT_SYS_MODULE_PATH_AIX + + +# _LT_SHELL_INIT(ARG) +# ------------------- +m4_define([_LT_SHELL_INIT], +[m4_divert_text([M4SH-INIT], [$1 +])])# _LT_SHELL_INIT + + + +# _LT_PROG_ECHO_BACKSLASH +# ----------------------- +# Find how we can fake an echo command that does not interpret backslash. +# In particular, with Autoconf 2.60 or later we add some code to the start +# of the generated configure script which will find a shell with a builtin +# printf (which we can use as an echo command). +m4_defun([_LT_PROG_ECHO_BACKSLASH], +[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +AC_MSG_CHECKING([how to print strings]) +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$[]1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + +case "$ECHO" in + printf*) AC_MSG_RESULT([printf]) ;; + print*) AC_MSG_RESULT([print -r]) ;; + *) AC_MSG_RESULT([cat]) ;; +esac + +m4_ifdef([_AS_DETECT_SUGGESTED], +[_AS_DETECT_SUGGESTED([ + test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test "X`printf %s $ECHO`" = "X$ECHO" \ + || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) + +_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) +_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) +])# _LT_PROG_ECHO_BACKSLASH + + +# _LT_WITH_SYSROOT +# ---------------- +AC_DEFUN([_LT_WITH_SYSROOT], +[AC_MSG_CHECKING([for sysroot]) +AC_ARG_WITH([sysroot], +[ --with-sysroot[=DIR] Search for dependent libraries within DIR + (or the compiler's sysroot if not specified).], +[], [with_sysroot=no]) + +dnl lt_sysroot will always be passed unquoted. We quote it here +dnl in case the user passed a directory name. +lt_sysroot= +case ${with_sysroot} in #( + yes) + if test "$GCC" = yes; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + AC_MSG_RESULT([${with_sysroot}]) + AC_MSG_ERROR([The sysroot must be an absolute path.]) + ;; +esac + + AC_MSG_RESULT([${lt_sysroot:-no}]) +_LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl +[dependent libraries, and in which our libraries should be installed.])]) + +# _LT_ENABLE_LOCK +# --------------- +m4_defun([_LT_ENABLE_LOCK], +[AC_ARG_ENABLE([libtool-lock], + [AS_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE="32" + ;; + *ELF-64*) + HPUX_IA64_MODE="64" + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out which ABI we are using. + echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + if test "$lt_cv_prog_gnu_ld" = yes; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_i386" + ;; + ppc64-*linux*|powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + ppc*-*linux*|powerpc*-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, + [AC_LANG_PUSH(C) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) + AC_LANG_POP]) + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; +sparc*-*solaris*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) LD="${LD-ld} -m elf64_sparc" ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks="$enable_libtool_lock" +])# _LT_ENABLE_LOCK + + +# _LT_PROG_AR +# ----------- +m4_defun([_LT_PROG_AR], +[AC_CHECK_TOOLS(AR, [ar], false) +: ${AR=ar} +: ${AR_FLAGS=cru} +_LT_DECL([], [AR], [1], [The archiver]) +_LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) + +AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], + [lt_cv_ar_at_file=no + AC_COMPILE_IFELSE([AC_LANG_PROGRAM], + [echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' + AC_TRY_EVAL([lt_ar_try]) + if test "$ac_status" -eq 0; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + AC_TRY_EVAL([lt_ar_try]) + if test "$ac_status" -ne 0; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + ]) + ]) + +if test "x$lt_cv_ar_at_file" = xno; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi +_LT_DECL([], [archiver_list_spec], [1], + [How to feed a file listing to the archiver]) +])# _LT_PROG_AR + + +# _LT_CMD_OLD_ARCHIVE +# ------------------- +m4_defun([_LT_CMD_OLD_ARCHIVE], +[_LT_PROG_AR + +AC_CHECK_TOOL(STRIP, strip, :) +test -z "$STRIP" && STRIP=: +_LT_DECL([], [STRIP], [1], [A symbol stripping program]) + +AC_CHECK_TOOL(RANLIB, ranlib, :) +test -z "$RANLIB" && RANLIB=: +_LT_DECL([], [RANLIB], [1], + [Commands used to install an old-style archive]) + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" +fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac +_LT_DECL([], [old_postinstall_cmds], [2]) +_LT_DECL([], [old_postuninstall_cmds], [2]) +_LT_TAGDECL([], [old_archive_cmds], [2], + [Commands used to build an old-style archive]) +_LT_DECL([], [lock_old_archive_extraction], [0], + [Whether to use a lock for old archive extraction]) +])# _LT_CMD_OLD_ARCHIVE + + +# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------------------- +# Check whether the given compiler option works +AC_DEFUN([_LT_COMPILER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$3" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + fi + $RM conftest* +]) + +if test x"[$]$2" = xyes; then + m4_if([$5], , :, [$5]) +else + m4_if([$6], , :, [$6]) +fi +])# _LT_COMPILER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) + + +# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------- +# Check whether the given linker option works +AC_DEFUN([_LT_LINKER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $3" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&AS_MESSAGE_LOG_FD + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + else + $2=yes + fi + fi + $RM -r conftest* + LDFLAGS="$save_LDFLAGS" +]) + +if test x"[$]$2" = xyes; then + m4_if([$4], , :, [$4]) +else + m4_if([$5], , :, [$5]) +fi +])# _LT_LINKER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) + + +# LT_CMD_MAX_LEN +#--------------- +AC_DEFUN([LT_CMD_MAX_LEN], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +# find the maximum length of command line arguments +AC_MSG_CHECKING([the maximum length of command line arguments]) +AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl + i=0 + teststring="ABCD" + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8 ; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac +]) +if test -n $lt_cv_sys_max_cmd_len ; then + AC_MSG_RESULT($lt_cv_sys_max_cmd_len) +else + AC_MSG_RESULT(none) +fi +max_cmd_len=$lt_cv_sys_max_cmd_len +_LT_DECL([], [max_cmd_len], [0], + [What is the maximum length of a command?]) +])# LT_CMD_MAX_LEN + +# Old name: +AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) + + +# _LT_HEADER_DLFCN +# ---------------- +m4_defun([_LT_HEADER_DLFCN], +[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl +])# _LT_HEADER_DLFCN + + +# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, +# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) +# ---------------------------------------------------------------- +m4_defun([_LT_TRY_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test "$cross_compiling" = yes; then : + [$4] +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +[#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisbility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +}] +_LT_EOF + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) $1 ;; + x$lt_dlneed_uscore) $2 ;; + x$lt_dlunknown|x*) $3 ;; + esac + else : + # compilation failed + $3 + fi +fi +rm -fr conftest* +])# _LT_TRY_DLOPEN_SELF + + +# LT_SYS_DLOPEN_SELF +# ------------------ +AC_DEFUN([LT_SYS_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen="dlopen" + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ + lt_cv_dlopen="dyld" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ]) + ;; + + *) + AC_CHECK_FUNC([shl_load], + [lt_cv_dlopen="shl_load"], + [AC_CHECK_LIB([dld], [shl_load], + [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"], + [AC_CHECK_FUNC([dlopen], + [lt_cv_dlopen="dlopen"], + [AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], + [AC_CHECK_LIB([svld], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], + [AC_CHECK_LIB([dld], [dld_link], + [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"]) + ]) + ]) + ]) + ]) + ]) + ;; + esac + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + else + enable_dlopen=no + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + AC_CACHE_CHECK([whether a program can dlopen itself], + lt_cv_dlopen_self, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, + lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) + ]) + + if test "x$lt_cv_dlopen_self" = xyes; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + AC_CACHE_CHECK([whether a statically linked program can dlopen itself], + lt_cv_dlopen_self_static, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, + lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) + ]) + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi +_LT_DECL([dlopen_support], [enable_dlopen], [0], + [Whether dlopen is supported]) +_LT_DECL([dlopen_self], [enable_dlopen_self], [0], + [Whether dlopen of programs is supported]) +_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], + [Whether dlopen of statically linked programs is supported]) +])# LT_SYS_DLOPEN_SELF + +# Old name: +AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) + + +# _LT_COMPILER_C_O([TAGNAME]) +# --------------------------- +# Check to see if options -c and -o are simultaneously supported by compiler. +# This macro does not hard code the compiler like AC_PROG_CC_C_O. +m4_defun([_LT_COMPILER_C_O], +[m4_require([_LT_DECL_SED])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + fi + fi + chmod u+w . 2>&AS_MESSAGE_LOG_FD + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* +]) +_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], + [Does compiler simultaneously support -c and -o options?]) +])# _LT_COMPILER_C_O + + +# _LT_COMPILER_FILE_LOCKS([TAGNAME]) +# ---------------------------------- +# Check to see if we can do hard links to lock some files if needed +m4_defun([_LT_COMPILER_FILE_LOCKS], +[m4_require([_LT_ENABLE_LOCK])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_COMPILER_C_O([$1]) + +hard_links="nottested" +if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + AC_MSG_CHECKING([if we can lock with hard links]) + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + AC_MSG_RESULT([$hard_links]) + if test "$hard_links" = no; then + AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) + need_locks=warn + fi +else + need_locks=no +fi +_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) +])# _LT_COMPILER_FILE_LOCKS + + +# _LT_CHECK_OBJDIR +# ---------------- +m4_defun([_LT_CHECK_OBJDIR], +[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], +[rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null]) +objdir=$lt_cv_objdir +_LT_DECL([], [objdir], [0], + [The name of the directory that contains temporary libtool files])dnl +m4_pattern_allow([LT_OBJDIR])dnl +AC_DEFINE_UNQUOTED(LT_OBJDIR, "$lt_cv_objdir/", + [Define to the sub-directory in which libtool stores uninstalled libraries.]) +])# _LT_CHECK_OBJDIR + + +# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) +# -------------------------------------- +# Check hardcoding attributes. +m4_defun([_LT_LINKER_HARDCODE_LIBPATH], +[AC_MSG_CHECKING([how to hardcode library paths into programs]) +_LT_TAGVAR(hardcode_action, $1)= +if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || + test -n "$_LT_TAGVAR(runpath_var, $1)" || + test "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then + + # We can hardcode non-existent directories. + if test "$_LT_TAGVAR(hardcode_direct, $1)" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" != no && + test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; then + # Linking always hardcodes the temporary library directory. + _LT_TAGVAR(hardcode_action, $1)=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + _LT_TAGVAR(hardcode_action, $1)=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + _LT_TAGVAR(hardcode_action, $1)=unsupported +fi +AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) + +if test "$_LT_TAGVAR(hardcode_action, $1)" = relink || + test "$_LT_TAGVAR(inherit_rpath, $1)" = yes; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi +_LT_TAGDECL([], [hardcode_action], [0], + [How to hardcode a shared library path into an executable]) +])# _LT_LINKER_HARDCODE_LIBPATH + + +# _LT_CMD_STRIPLIB +# ---------------- +m4_defun([_LT_CMD_STRIPLIB], +[m4_require([_LT_DECL_EGREP]) +striplib= +old_striplib= +AC_MSG_CHECKING([whether stripping libraries is possible]) +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + AC_MSG_RESULT([yes]) +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi + ;; + *) + AC_MSG_RESULT([no]) + ;; + esac +fi +_LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) +_LT_DECL([], [striplib], [1]) +])# _LT_CMD_STRIPLIB + + +# _LT_SYS_DYNAMIC_LINKER([TAG]) +# ----------------------------- +# PORTME Fill in your ld.so characteristics +m4_defun([_LT_SYS_DYNAMIC_LINKER], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_OBJDUMP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +AC_MSG_CHECKING([dynamic linker characteristics]) +m4_if([$1], + [], [ +if test "$GCC" = yes; then + case $host_os in + darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; + *) lt_awk_arg="/^libraries:/" ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq="s,=\([[A-Za-z]]:\),\1,g" ;; + *) lt_sed_strip_eq="s,=/,/,g" ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary. + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path/$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" + else + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS=" "; FS="/|\n";} { + lt_foo=""; + lt_count=0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo="/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[[lt_foo]]++; } + if (lt_freq[[lt_foo]] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's,/\([[A-Za-z]]:\),\1,g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi]) +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix[[4-9]]*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[[01]] | aix4.[[01]].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[[45]]*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + library_names_spec='${libname}.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec="$LIB" + if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[[123]]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[[01]]* | freebsdelf3.[[01]]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ + freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +haiku*) + version_type=linux + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=yes + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[[3-9]]*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], + [lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ + LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], + [lt_cv_shlibpath_overrides_runpath=yes])]) + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + ]) + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[[89]] | openbsd2.[[89]].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +AC_MSG_RESULT([$dynamic_linker]) +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then + sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" +fi +if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then + sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" +fi + +_LT_DECL([], [variables_saved_for_relink], [1], + [Variables whose values should be saved in libtool wrapper scripts and + restored at link time]) +_LT_DECL([], [need_lib_prefix], [0], + [Do we need the "lib" prefix for modules?]) +_LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) +_LT_DECL([], [version_type], [0], [Library versioning type]) +_LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) +_LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) +_LT_DECL([], [shlibpath_overrides_runpath], [0], + [Is shlibpath searched before the hard-coded library search path?]) +_LT_DECL([], [libname_spec], [1], [Format of library name prefix]) +_LT_DECL([], [library_names_spec], [1], + [[List of archive names. First name is the real one, the rest are links. + The last name is the one that the linker finds with -lNAME]]) +_LT_DECL([], [soname_spec], [1], + [[The coded name of the library, if different from the real name]]) +_LT_DECL([], [install_override_mode], [1], + [Permission mode override for installation of shared libraries]) +_LT_DECL([], [postinstall_cmds], [2], + [Command to use after installation of a shared archive]) +_LT_DECL([], [postuninstall_cmds], [2], + [Command to use after uninstallation of a shared archive]) +_LT_DECL([], [finish_cmds], [2], + [Commands used to finish a libtool library installation in a directory]) +_LT_DECL([], [finish_eval], [1], + [[As "finish_cmds", except a single script fragment to be evaled but + not shown]]) +_LT_DECL([], [hardcode_into_libs], [0], + [Whether we should hardcode library paths into libraries]) +_LT_DECL([], [sys_lib_search_path_spec], [2], + [Compile-time system search path for libraries]) +_LT_DECL([], [sys_lib_dlsearch_path_spec], [2], + [Run-time system search path for libraries]) +])# _LT_SYS_DYNAMIC_LINKER + + +# _LT_PATH_TOOL_PREFIX(TOOL) +# -------------------------- +# find a file program which can recognize shared library +AC_DEFUN([_LT_PATH_TOOL_PREFIX], +[m4_require([_LT_DECL_EGREP])dnl +AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, +[case $MAGIC_CMD in +[[\\/*] | ?:[\\/]*]) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="m4_if([$2], , $PATH, [$2])" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$1; then + lt_cv_path_MAGIC_CMD="$ac_dir/$1" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac]) +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + AC_MSG_RESULT($MAGIC_CMD) +else + AC_MSG_RESULT(no) +fi +_LT_DECL([], [MAGIC_CMD], [0], + [Used to examine libraries when file_magic_cmd begins with "file"])dnl +])# _LT_PATH_TOOL_PREFIX + +# Old name: +AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) + + +# _LT_PATH_MAGIC +# -------------- +# find a file program which can recognize a shared library +m4_defun([_LT_PATH_MAGIC], +[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) + else + MAGIC_CMD=: + fi +fi +])# _LT_PATH_MAGIC + + +# LT_PATH_LD +# ---------- +# find the pathname to the GNU or non-GNU linker +AC_DEFUN([LT_PATH_LD], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PROG_ECHO_BACKSLASH])dnl + +AC_ARG_WITH([gnu-ld], + [AS_HELP_STRING([--with-gnu-ld], + [assume the C compiler uses GNU ld @<:@default=no@:>@])], + [test "$withval" = no || with_gnu_ld=yes], + [with_gnu_ld=no])dnl + +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by $CC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(lt_cv_path_LD, +[if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &1 /dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[[3-9]]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be Linux ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +esac +]) + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` + fi + ;; + esac +fi + +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + +_LT_DECL([], [deplibs_check_method], [1], + [Method to check whether dependent libraries are shared objects]) +_LT_DECL([], [file_magic_cmd], [1], + [Command to use when deplibs_check_method = "file_magic"]) +_LT_DECL([], [file_magic_glob], [1], + [How to find potential files when deplibs_check_method = "file_magic"]) +_LT_DECL([], [want_nocaseglob], [1], + [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) +])# _LT_CHECK_MAGIC_METHOD + + +# LT_PATH_NM +# ---------- +# find the pathname to a BSD- or MS-compatible name lister +AC_DEFUN([LT_PATH_NM], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, +[if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + lt_nm_to_check="${ac_tool_prefix}nm" + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/$lt_tmp_nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS="$lt_save_ifs" + done + : ${lt_cv_path_NM=no} +fi]) +if test "$lt_cv_path_NM" != "no"; then + NM="$lt_cv_path_NM" +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) + case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols" + ;; + *) + DUMPBIN=: + ;; + esac + fi + AC_SUBST([DUMPBIN]) + if test "$DUMPBIN" != ":"; then + NM="$DUMPBIN" + fi +fi +test -z "$NM" && NM=nm +AC_SUBST([NM]) +_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl + +AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], + [lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) + cat conftest.out >&AS_MESSAGE_LOG_FD + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest*]) +])# LT_PATH_NM + +# Old names: +AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) +AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_PROG_NM], []) +dnl AC_DEFUN([AC_PROG_NM], []) + +# _LT_CHECK_SHAREDLIB_FROM_LINKLIB +# -------------------------------- +# how to determine the name of the shared library +# associated with a specific link library. +# -- PORTME fill in with the dynamic library characteristics +m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], +[m4_require([_LT_DECL_EGREP]) +m4_require([_LT_DECL_OBJDUMP]) +m4_require([_LT_DECL_DLLTOOL]) +AC_CACHE_CHECK([how to associate runtime and link libraries], +lt_cv_sharedlib_from_linklib_cmd, +[lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh + # decide which to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd="$ECHO" + ;; +esac +]) +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + +_LT_DECL([], [sharedlib_from_linklib_cmd], [1], + [Command to associate shared and link libraries]) +])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB + + +# _LT_PATH_MANIFEST_TOOL +# ---------------------- +# locate the manifest tool +m4_defun([_LT_PATH_MANIFEST_TOOL], +[AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], + [lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&AS_MESSAGE_LOG_FD + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest*]) +if test "x$lt_cv_path_mainfest_tool" != xyes; then + MANIFEST_TOOL=: +fi +_LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl +])# _LT_PATH_MANIFEST_TOOL + + +# LT_LIB_M +# -------- +# check for math library +AC_DEFUN([LT_LIB_M], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +LIBM= +case $host in +*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) + # These system don't have libm, or don't need it + ;; +*-ncr-sysv4.3*) + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") + AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") + ;; +*) + AC_CHECK_LIB(m, cos, LIBM="-lm") + ;; +esac +AC_SUBST([LIBM]) +])# LT_LIB_M + +# Old name: +AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_CHECK_LIBM], []) + + +# _LT_COMPILER_NO_RTTI([TAGNAME]) +# ------------------------------- +m4_defun([_LT_COMPILER_NO_RTTI], +[m4_require([_LT_TAG_COMPILER])dnl + +_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + +if test "$GCC" = yes; then + case $cc_basename in + nvcc*) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; + *) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; + esac + + _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], + lt_cv_prog_compiler_rtti_exceptions, + [-fno-rtti -fno-exceptions], [], + [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) +fi +_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], + [Compiler flag to turn off builtin functions]) +])# _LT_COMPILER_NO_RTTI + + +# _LT_CMD_GLOBAL_SYMBOLS +# ---------------------- +m4_defun([_LT_CMD_GLOBAL_SYMBOLS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([LT_PATH_NM])dnl +AC_REQUIRE([LT_PATH_LD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_TAG_COMPILER])dnl + +# Check for command to grab the raw symbol name followed by C symbol from nm. +AC_MSG_CHECKING([command to parse $NM output from $compiler object]) +AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], +[ +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[[BCDEGRST]]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[[BCDT]]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[[ABCDGISTW]]' + ;; +hpux*) + if test "$host_cpu" = ia64; then + symcode='[[ABCDEGRST]]' + fi + ;; +irix* | nonstopux*) + symcode='[[BCDEGRST]]' + ;; +osf*) + symcode='[[BCDEGQRST]]' + ;; +solaris*) + symcode='[[BDRT]]' + ;; +sco3.2v5*) + symcode='[[DT]]' + ;; +sysv4.2uw2*) + symcode='[[DT]]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[[ABDT]]' + ;; +sysv4) + symcode='[[DFNSTU]]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[[ABCDGIRSTW]]' ;; +esac + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'" +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function + # and D for any global variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK ['"\ +" {last_section=section; section=\$ 3};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ +" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ +" s[1]~/^[@?]/{print s[1], s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx]" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if AC_TRY_EVAL(ac_compile); then + # Now try to grab the symbols. + nlist=conftest.nm + if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) +/* DATA imports from DLLs on WIN32 con't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT@&t@_DLSYM_CONST +#elif defined(__osf__) +/* This system does not cope well with relocations in const data. */ +# define LT@&t@_DLSYM_CONST +#else +# define LT@&t@_DLSYM_CONST const +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +LT@&t@_DLSYM_CONST struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[[]] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS + else + echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD + fi + else + echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done +]) +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + AC_MSG_RESULT(failed) +else + AC_MSG_RESULT(ok) +fi + +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + +_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], + [Take the output of nm and produce a listing of raw symbols and C names]) +_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], + [Transform the output of nm in a proper C declaration]) +_LT_DECL([global_symbol_to_c_name_address], + [lt_cv_sys_global_symbol_to_c_name_address], [1], + [Transform the output of nm in a C name address pair]) +_LT_DECL([global_symbol_to_c_name_address_lib_prefix], + [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], + [Transform the output of nm in a C name address pair when lib prefix is needed]) +_LT_DECL([], [nm_file_list_spec], [1], + [Specify filename containing input files for $NM]) +]) # _LT_CMD_GLOBAL_SYMBOLS + + +# _LT_COMPILER_PIC([TAGNAME]) +# --------------------------- +m4_defun([_LT_COMPILER_PIC], +[m4_require([_LT_TAG_COMPILER])dnl +_LT_TAGVAR(lt_prog_compiler_wl, $1)= +_LT_TAGVAR(lt_prog_compiler_pic, $1)= +_LT_TAGVAR(lt_prog_compiler_static, $1)= + +m4_if([$1], [CXX], [ + # C++ specific cases for pic, static, wl, etc. + if test "$GXX" = yes; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + case $host_os in + aix[[4-9]]*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + dgux*) + case $cc_basename in + ec++*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + if test "$host_cpu" != ia64; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + fi + ;; + aCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + KCC*) + # KAI C++ Compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + ecpc* ) + # old Intel C++ for x86_64 which still supported -KPIC. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + icpc* ) + # Intel C++, used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) + # IBM XL 8.0, 9.0 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + esac + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd*) + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + cxx*) + # Digital/Compaq C++ + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + lcc*) + # Lucid + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + *) + ;; + esac + ;; + vxworks*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +], +[ + if test "$GCC" = yes; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Xcompiler -fPIC' + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + + hpux9* | hpux10* | hpux11*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC (with -KPIC) is the default. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + # old Intel for x86_64 which still supported -KPIC. + ecc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' + _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' + ;; + nagfor*) + # NAG Fortran compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + ccc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All Alpha code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ F* | *Sun*Fortran*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='' + ;; + *Sun\ C*) + # Sun C 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + esac + ;; + esac + ;; + + newsos6) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All OSF/1 code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + rdos*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + solaris*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; + *) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; + esac + ;; + + sunos4*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + unicos*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + + uts4*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +]) +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" + ;; +esac + +AC_CACHE_CHECK([for $compiler option to produce PIC], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) +_LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then + _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], + [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], + [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], + [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in + "" | " "*) ;; + *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; + esac], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) +fi +_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], + [Additional compiler flags for building library objects]) + +_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], + [How to pass a linker flag through the compiler]) +# +# Check to make sure the static flag actually works. +# +wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" +_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], + _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), + $lt_tmp_static_flag, + [], + [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) +_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], + [Compiler flag to prevent dynamic linking]) +])# _LT_COMPILER_PIC + + +# _LT_LINKER_SHLIBS([TAGNAME]) +# ---------------------------- +# See if the linker supports building shared libraries. +m4_defun([_LT_LINKER_SHLIBS], +[AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +m4_if([$1], [CXX], [ + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + case $host_os in + aix[[4-9]]*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + # Also, AIX nm treats weak defined symbols like other global defined + # symbols, whereas GNU nm marks them as "W". + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" + ;; + cygwin* | mingw* | cegcc*) + case $cc_basename in + cl*) ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + ;; + esac + ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac +], [ + runpath_var= + _LT_TAGVAR(allow_undefined_flag, $1)= + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(archive_cmds, $1)= + _LT_TAGVAR(archive_expsym_cmds, $1)= + _LT_TAGVAR(compiler_needs_object, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(hardcode_automatic, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= + _LT_TAGVAR(hardcode_libdir_separator, $1)= + _LT_TAGVAR(hardcode_minus_L, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_TAGVAR(inherit_rpath, $1)=no + _LT_TAGVAR(link_all_deplibs, $1)=unknown + _LT_TAGVAR(module_cmds, $1)= + _LT_TAGVAR(module_expsym_cmds, $1)= + _LT_TAGVAR(old_archive_from_new_cmds, $1)= + _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= + _LT_TAGVAR(thread_safe_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + _LT_TAGVAR(include_expsyms, $1)= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. +dnl Note also adjust exclude_expsyms for C++ above. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; + esac + + _LT_TAGVAR(ld_shlibs, $1)=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test "$with_gnu_ld" = yes; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; + *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test "$lt_use_gnu_ld_interface" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + supports_anon_versioning=no + case `$LD -v 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[[3-9]]*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test "$host_os" = linux-dietlibc; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test "$tmp_diet" = no + then + tmp_addflag=' $pic_flag' + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + _LT_TAGVAR(whole_archive_flag_spec, $1)= + tmp_sharedflag='--shared' ;; + xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test "x$supports_anon_versioning" = xyes; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir' + _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test "x$supports_anon_versioning" = xyes; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + sunos4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + + if test "$_LT_TAGVAR(ld_shlibs, $1)" = no; then + runpath_var= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + _LT_TAGVAR(hardcode_direct, $1)=unsupported + fi + ;; + + aix[[4-9]]*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + # Also, AIX nm treats weak defined symbols like other global + # defined symbols, whereas GNU nm marks them as "W". + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' + + if test "$GCC" = yes; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + if test "$with_gnu_ld" = yes; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds its shared libraries. + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + bsdi[[45]]*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + case $cc_basename in + cl*) + # Native MSVC + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; + else + sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile="$lt_outputfile.exe" + lt_tool_outputfile="$lt_tool_outputfile.exe" + ;; + esac~ + if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + # FIXME: Should let the user specify the lib program. + _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + esac + ;; + + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + dgux*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + freebsd1*) + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + hpux9*) + if test "$GCC" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + + hpux10*) + if test "$GCC" = yes && test "$with_gnu_ld" = no; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes && test "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + m4_if($1, [], [ + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + _LT_LINKER_OPTION([if $CC understands -b], + _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], + [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) + ;; + esac + fi + if test "$with_gnu_ld" = no; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + # This should be the same for all languages, so no per-tag cache variable. + AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], + [lt_cv_irix_exported_symbol], + [save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" + AC_LINK_IFELSE( + [AC_LANG_SOURCE( + [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], + [C++], [[int foo (void) { return 0; }]], + [Fortran 77], [[ + subroutine foo + end]], + [Fortran], [[ + subroutine foo + end]])])], + [lt_cv_irix_exported_symbol=yes], + [lt_cv_irix_exported_symbol=no]) + LDFLAGS="$save_LDFLAGS"]) + if test "$lt_cv_irix_exported_symbol" = yes; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' + fi + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + newsos6) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *nto* | *qnx*) + ;; + + openbsd*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + else + case $host_os in + openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + ;; + esac + fi + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + solaris*) + _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' + if test "$GCC" = yes; then + wlarc='${wl}' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + _LT_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='${wl}' + _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. GCC discards it without `$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test "$GCC" = yes; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + fi + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4) + case $host_vendor in + sni) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' + _LT_TAGVAR(hardcode_direct, $1)=no + ;; + motorola) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4.3*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + _LT_TAGVAR(ld_shlibs, $1)=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + if test x$host_vendor = xsni; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Blargedynsym' + ;; + esac + fi + fi +]) +AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) +test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + +_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld + +_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl +_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl +_LT_DECL([], [extract_expsyms_cmds], [2], + [The commands to extract the exported symbol list from a shared archive]) + +# +# Do we need to explicitly link libc? +# +case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in +x|xyes) + # Assume -lc should be added + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $_LT_TAGVAR(archive_cmds, $1) in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + AC_CACHE_CHECK([whether -lc should be explicitly linked in], + [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), + [$RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if AC_TRY_EVAL(ac_compile) 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) + pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) + _LT_TAGVAR(allow_undefined_flag, $1)= + if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) + then + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no + else + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes + fi + _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + ]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) + ;; + esac + fi + ;; +esac + +_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], + [Whether or not to add -lc for building shared libraries]) +_LT_TAGDECL([allow_libtool_libs_with_static_runtimes], + [enable_shared_with_static_runtimes], [0], + [Whether or not to disallow shared libs when runtime libs are static]) +_LT_TAGDECL([], [export_dynamic_flag_spec], [1], + [Compiler flag to allow reflexive dlopens]) +_LT_TAGDECL([], [whole_archive_flag_spec], [1], + [Compiler flag to generate shared objects directly from archives]) +_LT_TAGDECL([], [compiler_needs_object], [1], + [Whether the compiler copes with passing no objects directly]) +_LT_TAGDECL([], [old_archive_from_new_cmds], [2], + [Create an old-style archive from a shared archive]) +_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], + [Create a temporary old-style archive to link instead of a shared archive]) +_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) +_LT_TAGDECL([], [archive_expsym_cmds], [2]) +_LT_TAGDECL([], [module_cmds], [2], + [Commands used to build a loadable module if different from building + a shared archive.]) +_LT_TAGDECL([], [module_expsym_cmds], [2]) +_LT_TAGDECL([], [with_gnu_ld], [1], + [Whether we are building with GNU ld or not]) +_LT_TAGDECL([], [allow_undefined_flag], [1], + [Flag that allows shared libraries with undefined symbols to be built]) +_LT_TAGDECL([], [no_undefined_flag], [1], + [Flag that enforces no undefined symbols]) +_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], + [Flag to hardcode $libdir into a binary during linking. + This must work even if $libdir does not exist]) +_LT_TAGDECL([], [hardcode_libdir_flag_spec_ld], [1], + [[If ld is used when linking, flag to hardcode $libdir into a binary + during linking. This must work even if $libdir does not exist]]) +_LT_TAGDECL([], [hardcode_libdir_separator], [1], + [Whether we need a single "-rpath" flag with a separated argument]) +_LT_TAGDECL([], [hardcode_direct], [0], + [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes + DIR into the resulting binary]) +_LT_TAGDECL([], [hardcode_direct_absolute], [0], + [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes + DIR into the resulting binary and the resulting library dependency is + "absolute", i.e impossible to change by setting ${shlibpath_var} if the + library is relocated]) +_LT_TAGDECL([], [hardcode_minus_L], [0], + [Set to "yes" if using the -LDIR flag during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_shlibpath_var], [0], + [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_automatic], [0], + [Set to "yes" if building a shared library automatically hardcodes DIR + into the library and all subsequent libraries and executables linked + against it]) +_LT_TAGDECL([], [inherit_rpath], [0], + [Set to yes if linker adds runtime paths of dependent libraries + to runtime path list]) +_LT_TAGDECL([], [link_all_deplibs], [0], + [Whether libtool must link a program against all its dependency libraries]) +_LT_TAGDECL([], [always_export_symbols], [0], + [Set to "yes" if exported symbols are required]) +_LT_TAGDECL([], [export_symbols_cmds], [2], + [The commands to list exported symbols]) +_LT_TAGDECL([], [exclude_expsyms], [1], + [Symbols that should not be listed in the preloaded symbols]) +_LT_TAGDECL([], [include_expsyms], [1], + [Symbols that must always be exported]) +_LT_TAGDECL([], [prelink_cmds], [2], + [Commands necessary for linking programs (against libraries) with templates]) +_LT_TAGDECL([], [postlink_cmds], [2], + [Commands necessary for finishing linking programs]) +_LT_TAGDECL([], [file_list_spec], [1], + [Specify filename containing input files]) +dnl FIXME: Not yet implemented +dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], +dnl [Compiler flag to generate thread safe objects]) +])# _LT_LINKER_SHLIBS + + +# _LT_LANG_C_CONFIG([TAG]) +# ------------------------ +# Ensure that the configuration variables for a C compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to `libtool'. +m4_defun([_LT_LANG_C_CONFIG], +[m4_require([_LT_DECL_EGREP])dnl +lt_save_CC="$CC" +AC_LANG_PUSH(C) + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + +_LT_TAG_COMPILER +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + LT_SYS_DLOPEN_SELF + _LT_CMD_STRIPLIB + + # Report which library types will actually be built + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test "$can_build_shared" = "no" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[[4-9]]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test "$enable_shared" = yes || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_CONFIG($1) +fi +AC_LANG_POP +CC="$lt_save_CC" +])# _LT_LANG_C_CONFIG + + +# _LT_LANG_CXX_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a C++ compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to `libtool'. +m4_defun([_LT_LANG_CXX_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + AC_PROG_CXXCPP +else + _lt_caught_CXX_error=yes +fi + +AC_LANG_PUSH(C++) +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(compiler_needs_object, $1)=no +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the CXX compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test "$_lt_caught_CXX_error" != yes; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="int some_variable = 0;" + + # Code to be used in simple link tests + lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_CFLAGS=$CFLAGS + lt_save_LD=$LD + lt_save_GCC=$GCC + GCC=$GXX + lt_save_with_gnu_ld=$with_gnu_ld + lt_save_path_LD=$lt_cv_path_LD + if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx + else + $as_unset lt_cv_prog_gnu_ld + fi + if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX + else + $as_unset lt_cv_path_LD + fi + test -z "${LDCXX+set}" || LD=$LDCXX + CC=${CXX-"c++"} + CFLAGS=$CXXFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + # We don't want -fno-exception when compiling C++ code, so set the + # no_builtin_flag separately + if test "$GXX" = yes; then + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' + else + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + fi + + if test "$GXX" = yes; then + # Set up default GNU C++ configuration + + LT_PATH_LD + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test "$with_gnu_ld" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='${wl}' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | + $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + GXX=no + with_gnu_ld=no + wlarc= + fi + + # PORTME: fill in a description of your system's C++ link characteristics + AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) + _LT_TAGVAR(ld_shlibs, $1)=yes + case $host_os in + aix3*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aix[[4-9]]*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' + + if test "$GXX" = yes; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to + # export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an empty + # executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + if test "$with_gnu_ld" = yes; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds its shared + # libraries. + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + cygwin* | mingw* | pw32* | cegcc*) + case $GXX,$cc_basename in + ,cl* | no,cl*) + # Native MSVC + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + $SED -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; + else + $SED -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile="$lt_outputfile.exe" + lt_tool_outputfile="$lt_tool_outputfile.exe" + ;; + esac~ + func_to_tool_file "$lt_outputfile"~ + if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # g++ + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + freebsd[[12]]*) + # C++ shared libraries reported to be fairly broken before + # switch to ELF + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + freebsd-elf*) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + + freebsd* | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + gnu*) + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + hpux9*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test "$GXX" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + hpux10*|hpux11*) + if test $with_gnu_ld = no; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test "$GXX" = yes; then + if test $with_gnu_ld = no; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test "$GXX" = yes; then + if test "$with_gnu_ld" = no; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib' + fi + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + esac + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc* | ecpc* ) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + case `$CC -V` in + *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) + _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ + compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' + _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ + $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ + $RANLIB $oldlib' + _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + ;; + *) # Version 6 and above use weak symbols + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + ;; + cxx*) + # Compaq C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' + ;; + xl* | mpixl* | bgxl*) + # IBM XL 8.0 on PPC, with GNU ld + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + if test "x$supports_anon_versioning" = xyes; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + + # Not sure whether something based on + # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 + # would be better. + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + esac + ;; + esac + ;; + + lynxos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + m88k*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + + *nto* | *qnx*) + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + openbsd2*) + # C++ shared libraries are fairly broken + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + openbsd*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + fi + output_verbose_link_cmd=func_echo_all + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + case $host in + osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; + *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; + esac + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + case $host in + osf3*) + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + ;; + *) + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~ + $RM $lib.exp' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + case $host in + osf3*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + psos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(archive_cmds_need_lc,$1)=yes + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. + # Supported since Solaris 2.6 (maybe 2.5.1?) + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' + if $CC --version | $GREP -v '^2\.7' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + else + # g++ 2.7 appears to require `-G' NOT `-shared' on this + # platform. + _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + fi + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + ;; + esac + fi + ;; + esac + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ + '"$_LT_TAGVAR(old_archive_cmds, $1)" + _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ + '"$_LT_TAGVAR(reload_cmds, $1)" + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + vxworks*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) + test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + + _LT_TAGVAR(GCC, $1)="$GXX" + _LT_TAGVAR(LD, $1)="$LD" + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS + LDCXX=$LD + LD=$lt_save_LD + GCC=$lt_save_GCC + with_gnu_ld=$lt_save_with_gnu_ld + lt_cv_path_LDCXX=$lt_cv_path_LD + lt_cv_path_LD=$lt_save_path_LD + lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld + lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +fi # test "$_lt_caught_CXX_error" != yes + +AC_LANG_POP +])# _LT_LANG_CXX_CONFIG + + +# _LT_FUNC_STRIPNAME_CNF +# ---------------------- +# func_stripname_cnf prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +# +# This function is identical to the (non-XSI) version of func_stripname, +# except this one can be used by m4 code that may be executed by configure, +# rather than the libtool script. +m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl +AC_REQUIRE([_LT_DECL_SED]) +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) +func_stripname_cnf () +{ + case ${2} in + .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; + *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; + esac +} # func_stripname_cnf +])# _LT_FUNC_STRIPNAME_CNF + +# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) +# --------------------------------- +# Figure out "hidden" library dependencies from verbose +# compiler output when linking a shared library. +# Parse the compiler output and extract the necessary +# objects, libraries and library flags. +m4_defun([_LT_SYS_HIDDEN_LIBDEPS], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl +# Dependencies to place before and after the object being linked: +_LT_TAGVAR(predep_objects, $1)= +_LT_TAGVAR(postdep_objects, $1)= +_LT_TAGVAR(predeps, $1)= +_LT_TAGVAR(postdeps, $1)= +_LT_TAGVAR(compiler_lib_search_path, $1)= + +dnl we can't use the lt_simple_compile_test_code here, +dnl because it contains code intended for an executable, +dnl not a library. It's possible we should let each +dnl tag define a new lt_????_link_test_code variable, +dnl but it's only used here... +m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF +int a; +void foo (void) { a = 0; } +_LT_EOF +], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF +class Foo +{ +public: + Foo (void) { a = 0; } +private: + int a; +}; +_LT_EOF +], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer*4 a + a=0 + return + end +_LT_EOF +], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer a + a=0 + return + end +_LT_EOF +], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF +public class foo { + private int a; + public void bar (void) { + a = 0; + } +}; +_LT_EOF +]) + +_lt_libdeps_save_CFLAGS=$CFLAGS +case "$CC $CFLAGS " in #( +*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; +*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; +esac + +dnl Parse the compiler output and extract the necessary +dnl objects, libraries and library flags. +if AC_TRY_EVAL(ac_compile); then + # Parse the compiler output and extract the necessary + # objects, libraries and library flags. + + # Sentinel used to keep track of whether or not we are before + # the conftest object file. + pre_test_object_deps_done=no + + for p in `eval "$output_verbose_link_cmd"`; do + case ${prev}${p} in + + -L* | -R* | -l*) + # Some compilers place space between "-{L,R}" and the path. + # Remove the space. + if test $p = "-L" || + test $p = "-R"; then + prev=$p + continue + fi + + # Expand the sysroot to ease extracting the directories later. + if test -z "$prev"; then + case $p in + -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; + -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; + -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; + esac + fi + case $p in + =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; + esac + if test "$pre_test_object_deps_done" = no; then + case ${prev} in + -L | -R) + # Internal compiler library paths should come after those + # provided the user. The postdeps already come after the + # user supplied libs so there is no need to process them. + if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then + _LT_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}" + else + _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}" + fi + ;; + # The "-l" case would never come before the object being + # linked, so don't bother handling this case. + esac + else + if test -z "$_LT_TAGVAR(postdeps, $1)"; then + _LT_TAGVAR(postdeps, $1)="${prev}${p}" + else + _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}" + fi + fi + prev= + ;; + + *.lto.$objext) ;; # Ignore GCC LTO objects + *.$objext) + # This assumes that the test object file only shows up + # once in the compiler output. + if test "$p" = "conftest.$objext"; then + pre_test_object_deps_done=yes + continue + fi + + if test "$pre_test_object_deps_done" = no; then + if test -z "$_LT_TAGVAR(predep_objects, $1)"; then + _LT_TAGVAR(predep_objects, $1)="$p" + else + _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" + fi + else + if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then + _LT_TAGVAR(postdep_objects, $1)="$p" + else + _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" + fi + fi + ;; + + *) ;; # Ignore the rest. + + esac + done + + # Clean up. + rm -f a.out a.exe +else + echo "libtool.m4: error: problem compiling $1 test program" +fi + +$RM -f confest.$objext +CFLAGS=$_lt_libdeps_save_CFLAGS + +# PORTME: override above test on systems where it is broken +m4_if([$1], [CXX], +[case $host_os in +interix[[3-9]]*) + # Interix 3.5 installs completely hosed .la files for C++, so rather than + # hack all around it, let's just trust "g++" to DTRT. + _LT_TAGVAR(predep_objects,$1)= + _LT_TAGVAR(postdep_objects,$1)= + _LT_TAGVAR(postdeps,$1)= + ;; + +linux*) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + + # The more standards-conforming stlport4 library is + # incompatible with the Cstd library. Avoid specifying + # it if it's in CXXFLAGS. Ignore libCrun as + # -library=stlport4 depends on it. + case " $CXX $CXXFLAGS " in + *" -library=stlport4 "*) + solaris_use_stlport4=yes + ;; + esac + + if test "$solaris_use_stlport4" != yes; then + _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' + fi + ;; + esac + ;; + +solaris*) + case $cc_basename in + CC* | sunCC*) + # The more standards-conforming stlport4 library is + # incompatible with the Cstd library. Avoid specifying + # it if it's in CXXFLAGS. Ignore libCrun as + # -library=stlport4 depends on it. + case " $CXX $CXXFLAGS " in + *" -library=stlport4 "*) + solaris_use_stlport4=yes + ;; + esac + + # Adding this requires a known-good setup of shared libraries for + # Sun compiler versions before 5.6, else PIC objects from an old + # archive will be linked into the output, leading to subtle bugs. + if test "$solaris_use_stlport4" != yes; then + _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' + fi + ;; + esac + ;; +esac +]) + +case " $_LT_TAGVAR(postdeps, $1) " in +*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; +esac + _LT_TAGVAR(compiler_lib_search_dirs, $1)= +if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then + _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'` +fi +_LT_TAGDECL([], [compiler_lib_search_dirs], [1], + [The directories searched by this compiler when creating a shared library]) +_LT_TAGDECL([], [predep_objects], [1], + [Dependencies to place before and after the objects being linked to + create a shared library]) +_LT_TAGDECL([], [postdep_objects], [1]) +_LT_TAGDECL([], [predeps], [1]) +_LT_TAGDECL([], [postdeps], [1]) +_LT_TAGDECL([], [compiler_lib_search_path], [1], + [The library search path used internally by the compiler when linking + a shared library]) +])# _LT_SYS_HIDDEN_LIBDEPS + + +# _LT_LANG_F77_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a Fortran 77 compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_F77_CONFIG], +[AC_LANG_PUSH(Fortran 77) +if test -z "$F77" || test "X$F77" = "Xno"; then + _lt_disable_F77=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for f77 test sources. +ac_ext=f + +# Object file extension for compiled f77 test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the F77 compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test "$_lt_disable_F77" != yes; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC="$CC" + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${F77-"f77"} + CFLAGS=$FFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + GCC=$G77 + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test "$can_build_shared" = "no" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test "$enable_shared" = yes || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)="$G77" + _LT_TAGVAR(LD, $1)="$LD" + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC="$lt_save_CC" + CFLAGS="$lt_save_CFLAGS" +fi # test "$_lt_disable_F77" != yes + +AC_LANG_POP +])# _LT_LANG_F77_CONFIG + + +# _LT_LANG_FC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for a Fortran compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_FC_CONFIG], +[AC_LANG_PUSH(Fortran) + +if test -z "$FC" || test "X$FC" = "Xno"; then + _lt_disable_FC=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for fc test sources. +ac_ext=${ac_fc_srcext-f} + +# Object file extension for compiled fc test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the FC compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test "$_lt_disable_FC" != yes; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC="$CC" + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${FC-"f95"} + CFLAGS=$FCFLAGS + compiler=$CC + GCC=$ac_cv_fc_compiler_gnu + + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test "$can_build_shared" = "no" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test "$enable_shared" = yes || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)="$ac_cv_fc_compiler_gnu" + _LT_TAGVAR(LD, $1)="$LD" + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS +fi # test "$_lt_disable_FC" != yes + +AC_LANG_POP +])# _LT_LANG_FC_CONFIG + + +# _LT_LANG_GCJ_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for the GNU Java Compiler compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_GCJ_CONFIG], +[AC_REQUIRE([LT_PROG_GCJ])dnl +AC_LANG_SAVE + +# Source file extension for Java test sources. +ac_ext=java + +# Object file extension for compiled Java test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="class foo {}" + +# Code to be used in simple link tests +lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC=yes +CC=${GCJ-"gcj"} +CFLAGS=$GCJFLAGS +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_TAGVAR(LD, $1)="$LD" +_LT_CC_BASENAME([$compiler]) + +# GCJ did not exist at the time GCC didn't implicitly link libc in. +_LT_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds + +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) +fi + +AC_LANG_RESTORE + +GCC=$lt_save_GCC +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_GCJ_CONFIG + + +# _LT_LANG_RC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for the Windows resource compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_RC_CONFIG], +[AC_REQUIRE([LT_PROG_RC])dnl +AC_LANG_SAVE + +# Source file extension for RC test sources. +ac_ext=rc + +# Object file extension for compiled RC test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' + +# Code to be used in simple link tests +lt_simple_link_test_code="$lt_simple_compile_test_code" + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC= +CC=${RC-"windres"} +CFLAGS= +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) +_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + +if test -n "$compiler"; then + : + _LT_CONFIG($1) +fi + +GCC=$lt_save_GCC +AC_LANG_RESTORE +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_RC_CONFIG + + +# LT_PROG_GCJ +# ----------- +AC_DEFUN([LT_PROG_GCJ], +[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], + [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], + [AC_CHECK_TOOL(GCJ, gcj,) + test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" + AC_SUBST(GCJFLAGS)])])[]dnl +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_GCJ], []) + + +# LT_PROG_RC +# ---------- +AC_DEFUN([LT_PROG_RC], +[AC_CHECK_TOOL(RC, windres,) +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_RC], []) + + +# _LT_DECL_EGREP +# -------------- +# If we don't have a new enough Autoconf to choose the best grep +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_EGREP], +[AC_REQUIRE([AC_PROG_EGREP])dnl +AC_REQUIRE([AC_PROG_FGREP])dnl +test -z "$GREP" && GREP=grep +_LT_DECL([], [GREP], [1], [A grep program that handles long lines]) +_LT_DECL([], [EGREP], [1], [An ERE matcher]) +_LT_DECL([], [FGREP], [1], [A literal string matcher]) +dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too +AC_SUBST([GREP]) +]) + + +# _LT_DECL_OBJDUMP +# -------------- +# If we don't have a new enough Autoconf to choose the best objdump +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_OBJDUMP], +[AC_CHECK_TOOL(OBJDUMP, objdump, false) +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) +AC_SUBST([OBJDUMP]) +]) + +# _LT_DECL_DLLTOOL +# ---------------- +# Ensure DLLTOOL variable is set. +m4_defun([_LT_DECL_DLLTOOL], +[AC_CHECK_TOOL(DLLTOOL, dlltool, false) +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program]) +AC_SUBST([DLLTOOL]) +]) + +# _LT_DECL_SED +# ------------ +# Check for a fully-functional sed program, that truncates +# as few characters as possible. Prefer GNU sed if found. +m4_defun([_LT_DECL_SED], +[AC_PROG_SED +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" +_LT_DECL([], [SED], [1], [A sed program that does not truncate output]) +_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], + [Sed that helps us avoid accidentally triggering echo(1) options like -n]) +])# _LT_DECL_SED + +m4_ifndef([AC_PROG_SED], [ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_SED. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # + +m4_defun([AC_PROG_SED], +[AC_MSG_CHECKING([for a sed that does not truncate output]) +AC_CACHE_VAL(lt_cv_path_SED, +[# Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done +done +IFS=$as_save_IFS +lt_ac_max=0 +lt_ac_count=0 +# Add /usr/xpg4/bin/sed as it is typically found on Solaris +# along with /bin/sed that truncates output. +for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f $lt_ac_sed && continue + cat /dev/null > conftest.in + lt_ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >conftest.in + # Check for GNU sed and select it if it is found. + if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then + lt_cv_path_SED=$lt_ac_sed + break + fi + while true; do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo >>conftest.nl + $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break + cmp -s conftest.out conftest.nl || break + # 10000 chars as input seems more than enough + test $lt_ac_count -gt 10 && break + lt_ac_count=`expr $lt_ac_count + 1` + if test $lt_ac_count -gt $lt_ac_max; then + lt_ac_max=$lt_ac_count + lt_cv_path_SED=$lt_ac_sed + fi + done +done +]) +SED=$lt_cv_path_SED +AC_SUBST([SED]) +AC_MSG_RESULT([$SED]) +])#AC_PROG_SED +])#m4_ifndef + +# Old name: +AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_SED], []) + + +# _LT_CHECK_SHELL_FEATURES +# ------------------------ +# Find out whether the shell is Bourne or XSI compatible, +# or has some other useful features. +m4_defun([_LT_CHECK_SHELL_FEATURES], +[AC_MSG_CHECKING([whether the shell understands some XSI constructs]) +# Try some XSI features +xsi_shell=no +( _lt_dummy="a/b/c" + test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ + = c,a/b,b/c, \ + && eval 'test $(( 1 + 1 )) -eq 2 \ + && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ + && xsi_shell=yes +AC_MSG_RESULT([$xsi_shell]) +_LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell']) + +AC_MSG_CHECKING([whether the shell understands "+="]) +lt_shell_append=no +( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \ + >/dev/null 2>&1 \ + && lt_shell_append=yes +AC_MSG_RESULT([$lt_shell_append]) +_LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append']) + +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi +_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac +_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl +_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl +])# _LT_CHECK_SHELL_FEATURES + + +# _LT_PROG_FUNCTION_REPLACE (FUNCNAME, REPLACEMENT-BODY) +# ------------------------------------------------------ +# In `$cfgfile', look for function FUNCNAME delimited by `^FUNCNAME ()$' and +# '^} FUNCNAME ', and replace its body with REPLACEMENT-BODY. +m4_defun([_LT_PROG_FUNCTION_REPLACE], +[dnl { +sed -e '/^$1 ()$/,/^} # $1 /c\ +$1 ()\ +{\ +m4_bpatsubsts([$2], [$], [\\], [^\([ ]\)], [\\\1]) +} # Extended-shell $1 implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: +]) + + +# _LT_PROG_REPLACE_SHELLFNS +# ------------------------- +# Replace existing portable implementations of several shell functions with +# equivalent extended shell implementations where those features are available.. +m4_defun([_LT_PROG_REPLACE_SHELLFNS], +[if test x"$xsi_shell" = xyes; then + _LT_PROG_FUNCTION_REPLACE([func_dirname], [dnl + case ${1} in + */*) func_dirname_result="${1%/*}${2}" ;; + * ) func_dirname_result="${3}" ;; + esac]) + + _LT_PROG_FUNCTION_REPLACE([func_basename], [dnl + func_basename_result="${1##*/}"]) + + _LT_PROG_FUNCTION_REPLACE([func_dirname_and_basename], [dnl + case ${1} in + */*) func_dirname_result="${1%/*}${2}" ;; + * ) func_dirname_result="${3}" ;; + esac + func_basename_result="${1##*/}"]) + + _LT_PROG_FUNCTION_REPLACE([func_stripname], [dnl + # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are + # positional parameters, so assign one to ordinary parameter first. + func_stripname_result=${3} + func_stripname_result=${func_stripname_result#"${1}"} + func_stripname_result=${func_stripname_result%"${2}"}]) + + _LT_PROG_FUNCTION_REPLACE([func_split_long_opt], [dnl + func_split_long_opt_name=${1%%=*} + func_split_long_opt_arg=${1#*=}]) + + _LT_PROG_FUNCTION_REPLACE([func_split_short_opt], [dnl + func_split_short_opt_arg=${1#??} + func_split_short_opt_name=${1%"$func_split_short_opt_arg"}]) + + _LT_PROG_FUNCTION_REPLACE([func_lo2o], [dnl + case ${1} in + *.lo) func_lo2o_result=${1%.lo}.${objext} ;; + *) func_lo2o_result=${1} ;; + esac]) + + _LT_PROG_FUNCTION_REPLACE([func_xform], [ func_xform_result=${1%.*}.lo]) + + _LT_PROG_FUNCTION_REPLACE([func_arith], [ func_arith_result=$(( $[*] ))]) + + _LT_PROG_FUNCTION_REPLACE([func_len], [ func_len_result=${#1}]) +fi + +if test x"$lt_shell_append" = xyes; then + _LT_PROG_FUNCTION_REPLACE([func_append], [ eval "${1}+=\\${2}"]) + + _LT_PROG_FUNCTION_REPLACE([func_append_quoted], [dnl + func_quote_for_eval "${2}" +dnl m4 expansion turns \\\\ into \\, and then the shell eval turns that into \ + eval "${1}+=\\\\ \\$func_quote_for_eval_result"]) + + # Save a `func_append' function call where possible by direct use of '+=' + sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") + test 0 -eq $? || _lt_function_replace_fail=: +else + # Save a `func_append' function call even when '+=' is not available + sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") + test 0 -eq $? || _lt_function_replace_fail=: +fi + +if test x"$_lt_function_replace_fail" = x":"; then + AC_MSG_WARN([Unable to substitute extended shell functions in $ofile]) +fi +]) + +# _LT_PATH_CONVERSION_FUNCTIONS +# ----------------------------- +# Determine which file name conversion functions should be used by +# func_to_host_file (and, implicitly, by func_to_host_path). These are needed +# for certain cross-compile configurations and native mingw. +m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_MSG_CHECKING([how to convert $build file names to $host format]) +AC_CACHE_VAL(lt_cv_to_host_file_cmd, +[case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac +]) +to_host_file_cmd=$lt_cv_to_host_file_cmd +AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) +_LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], + [0], [convert $build file names to $host format])dnl + +AC_MSG_CHECKING([how to convert $build file names to toolchain format]) +AC_CACHE_VAL(lt_cv_to_tool_file_cmd, +[#assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac +]) +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) +_LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], + [0], [convert $build files to toolchain format])dnl +])# _LT_PATH_CONVERSION_FUNCTIONS + +# Helper functions for option handling. -*- Autoconf -*- +# +# Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 7 ltoptions.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) + + +# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) +# ------------------------------------------ +m4_define([_LT_MANGLE_OPTION], +[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) + + +# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) +# --------------------------------------- +# Set option OPTION-NAME for macro MACRO-NAME, and if there is a +# matching handler defined, dispatch to it. Other OPTION-NAMEs are +# saved as a flag. +m4_define([_LT_SET_OPTION], +[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl +m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), + _LT_MANGLE_DEFUN([$1], [$2]), + [m4_warning([Unknown $1 option `$2'])])[]dnl +]) + + +# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) +# ------------------------------------------------------------ +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +m4_define([_LT_IF_OPTION], +[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) + + +# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) +# ------------------------------------------------------- +# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME +# are set. +m4_define([_LT_UNLESS_OPTIONS], +[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), + [m4_define([$0_found])])])[]dnl +m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 +])[]dnl +]) + + +# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) +# ---------------------------------------- +# OPTION-LIST is a space-separated list of Libtool options associated +# with MACRO-NAME. If any OPTION has a matching handler declared with +# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about +# the unknown option and exit. +m4_defun([_LT_SET_OPTIONS], +[# Set options +m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [_LT_SET_OPTION([$1], _LT_Option)]) + +m4_if([$1],[LT_INIT],[ + dnl + dnl Simply set some default values (i.e off) if boolean options were not + dnl specified: + _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no + ]) + _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no + ]) + dnl + dnl If no reference was made to various pairs of opposing options, then + dnl we run the default mode handler for the pair. For example, if neither + dnl `shared' nor `disable-shared' was passed, we enable building of shared + dnl archives by default: + _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) + _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], + [_LT_ENABLE_FAST_INSTALL]) + ]) +])# _LT_SET_OPTIONS + + + +# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) +# ----------------------------------------- +m4_define([_LT_MANGLE_DEFUN], +[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) + + +# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) +# ----------------------------------------------- +m4_define([LT_OPTION_DEFINE], +[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl +])# LT_OPTION_DEFINE + + +# dlopen +# ------ +LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes +]) + +AU_DEFUN([AC_LIBTOOL_DLOPEN], +[_LT_SET_OPTION([LT_INIT], [dlopen]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the `dlopen' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) + + +# win32-dll +# --------- +# Declare package support for building win32 dll's. +LT_OPTION_DEFINE([LT_INIT], [win32-dll], +[enable_win32_dll=yes + +case $host in +*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) + AC_CHECK_TOOL(AS, as, false) + AC_CHECK_TOOL(DLLTOOL, dlltool, false) + AC_CHECK_TOOL(OBJDUMP, objdump, false) + ;; +esac + +test -z "$AS" && AS=as +_LT_DECL([], [AS], [1], [Assembler program])dnl + +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl + +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl +])# win32-dll + +AU_DEFUN([AC_LIBTOOL_WIN32_DLL], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +_LT_SET_OPTION([LT_INIT], [win32-dll]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the `win32-dll' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) + + +# _LT_ENABLE_SHARED([DEFAULT]) +# ---------------------------- +# implement the --enable-shared flag, and supports the `shared' and +# `disable-shared' LT_INIT options. +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +m4_define([_LT_ENABLE_SHARED], +[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([shared], + [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], + [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) + + _LT_DECL([build_libtool_libs], [enable_shared], [0], + [Whether or not to build shared libraries]) +])# _LT_ENABLE_SHARED + +LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) +]) + +AC_DEFUN([AC_DISABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], [disable-shared]) +]) + +AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) +AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_SHARED], []) +dnl AC_DEFUN([AM_DISABLE_SHARED], []) + + + +# _LT_ENABLE_STATIC([DEFAULT]) +# ---------------------------- +# implement the --enable-static flag, and support the `static' and +# `disable-static' LT_INIT options. +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +m4_define([_LT_ENABLE_STATIC], +[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([static], + [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], + [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_static=]_LT_ENABLE_STATIC_DEFAULT) + + _LT_DECL([build_old_libs], [enable_static], [0], + [Whether or not to build static libraries]) +])# _LT_ENABLE_STATIC + +LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) +]) + +AC_DEFUN([AC_DISABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], [disable-static]) +]) + +AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) +AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_STATIC], []) +dnl AC_DEFUN([AM_DISABLE_STATIC], []) + + + +# _LT_ENABLE_FAST_INSTALL([DEFAULT]) +# ---------------------------------- +# implement the --enable-fast-install flag, and support the `fast-install' +# and `disable-fast-install' LT_INIT options. +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +m4_define([_LT_ENABLE_FAST_INSTALL], +[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([fast-install], + [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], + [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) + +_LT_DECL([fast_install], [enable_fast_install], [0], + [Whether or not to optimize for fast installation])dnl +])# _LT_ENABLE_FAST_INSTALL + +LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) + +# Old names: +AU_DEFUN([AC_ENABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the `fast-install' option into LT_INIT's first parameter.]) +]) + +AU_DEFUN([AC_DISABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], [disable-fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the `disable-fast-install' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) +dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) + + +# _LT_WITH_PIC([MODE]) +# -------------------- +# implement the --with-pic flag, and support the `pic-only' and `no-pic' +# LT_INIT options. +# MODE is either `yes' or `no'. If omitted, it defaults to `both'. +m4_define([_LT_WITH_PIC], +[AC_ARG_WITH([pic], + [AS_HELP_STRING([--with-pic], + [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], + [pic_mode="$withval"], + [pic_mode=default]) + +test -z "$pic_mode" && pic_mode=m4_default([$1], [default]) + +_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl +])# _LT_WITH_PIC + +LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) + +# Old name: +AU_DEFUN([AC_LIBTOOL_PICMODE], +[_LT_SET_OPTION([LT_INIT], [pic-only]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the `pic-only' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) + + +m4_define([_LTDL_MODE], []) +LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], + [m4_define([_LTDL_MODE], [nonrecursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [recursive], + [m4_define([_LTDL_MODE], [recursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [subproject], + [m4_define([_LTDL_MODE], [subproject])]) + +m4_define([_LTDL_TYPE], []) +LT_OPTION_DEFINE([LTDL_INIT], [installable], + [m4_define([_LTDL_TYPE], [installable])]) +LT_OPTION_DEFINE([LTDL_INIT], [convenience], + [m4_define([_LTDL_TYPE], [convenience])]) + +# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- +# +# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 6 ltsugar.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) + + +# lt_join(SEP, ARG1, [ARG2...]) +# ----------------------------- +# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their +# associated separator. +# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier +# versions in m4sugar had bugs. +m4_define([lt_join], +[m4_if([$#], [1], [], + [$#], [2], [[$2]], + [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) +m4_define([_lt_join], +[m4_if([$#$2], [2], [], + [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) + + +# lt_car(LIST) +# lt_cdr(LIST) +# ------------ +# Manipulate m4 lists. +# These macros are necessary as long as will still need to support +# Autoconf-2.59 which quotes differently. +m4_define([lt_car], [[$1]]) +m4_define([lt_cdr], +[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], + [$#], 1, [], + [m4_dquote(m4_shift($@))])]) +m4_define([lt_unquote], $1) + + +# lt_append(MACRO-NAME, STRING, [SEPARATOR]) +# ------------------------------------------ +# Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'. +# Note that neither SEPARATOR nor STRING are expanded; they are appended +# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). +# No SEPARATOR is output if MACRO-NAME was previously undefined (different +# than defined and empty). +# +# This macro is needed until we can rely on Autoconf 2.62, since earlier +# versions of m4sugar mistakenly expanded SEPARATOR but not STRING. +m4_define([lt_append], +[m4_define([$1], + m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) + + + +# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) +# ---------------------------------------------------------- +# Produce a SEP delimited list of all paired combinations of elements of +# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list +# has the form PREFIXmINFIXSUFFIXn. +# Needed until we can rely on m4_combine added in Autoconf 2.62. +m4_define([lt_combine], +[m4_if(m4_eval([$# > 3]), [1], + [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl +[[m4_foreach([_Lt_prefix], [$2], + [m4_foreach([_Lt_suffix], + ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, + [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) + + +# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) +# ----------------------------------------------------------------------- +# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited +# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. +m4_define([lt_if_append_uniq], +[m4_ifdef([$1], + [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], + [lt_append([$1], [$2], [$3])$4], + [$5])], + [lt_append([$1], [$2], [$3])$4])]) + + +# lt_dict_add(DICT, KEY, VALUE) +# ----------------------------- +m4_define([lt_dict_add], +[m4_define([$1($2)], [$3])]) + + +# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) +# -------------------------------------------- +m4_define([lt_dict_add_subkey], +[m4_define([$1($2:$3)], [$4])]) + + +# lt_dict_fetch(DICT, KEY, [SUBKEY]) +# ---------------------------------- +m4_define([lt_dict_fetch], +[m4_ifval([$3], + m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), + m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) + + +# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) +# ----------------------------------------------------------------- +m4_define([lt_if_dict_fetch], +[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], + [$5], + [$6])]) + + +# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) +# -------------------------------------------------------------- +m4_define([lt_dict_filter], +[m4_if([$5], [], [], + [lt_join(m4_quote(m4_default([$4], [[, ]])), + lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), + [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl +]) + +# ltversion.m4 -- version numbers -*- Autoconf -*- +# +# Copyright (C) 2004 Free Software Foundation, Inc. +# Written by Scott James Remnant, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# @configure_input@ + +# serial 3294 ltversion.m4 +# This file is part of GNU Libtool + +m4_define([LT_PACKAGE_VERSION], [2.4]) +m4_define([LT_PACKAGE_REVISION], [1.3294]) + +AC_DEFUN([LTVERSION_VERSION], +[macro_version='2.4' +macro_revision='1.3294' +_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) +_LT_DECL(, macro_revision, 0) +]) + +# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- +# +# Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc. +# Written by Scott James Remnant, 2004. +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 5 lt~obsolete.m4 + +# These exist entirely to fool aclocal when bootstrapping libtool. +# +# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN) +# which have later been changed to m4_define as they aren't part of the +# exported API, or moved to Autoconf or Automake where they belong. +# +# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN +# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us +# using a macro with the same name in our local m4/libtool.m4 it'll +# pull the old libtool.m4 in (it doesn't see our shiny new m4_define +# and doesn't know about Autoconf macros at all.) +# +# So we provide this file, which has a silly filename so it's always +# included after everything else. This provides aclocal with the +# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything +# because those macros already exist, or will be overwritten later. +# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. +# +# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. +# Yes, that means every name once taken will need to remain here until +# we give up compatibility with versions before 1.7, at which point +# we need to keep only those names which we still refer to. + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) + +m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) +m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) +m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) +m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) +m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) +m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) +m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) +m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) +m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) +m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) +m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) +m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) +m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) +m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) +m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) +m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) +m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) +m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) +m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) +m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) +m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) +m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) +m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) +m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) +m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) +m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) +m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) +m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) +m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) +m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) +m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) +m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) +m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) +m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) +m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) +m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) +m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) +m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) +m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) +m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) +m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) +m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) +m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) +m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) +m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) +m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) +m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) +m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) +m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) +m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) +m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) + +# Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008, 2011 Free Software +# Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 1 + +# AM_AUTOMAKE_VERSION(VERSION) +# ---------------------------- +# Automake X.Y traces this macro to ensure aclocal.m4 has been +# generated from the m4 files accompanying Automake X.Y. +# (This private macro should not be called outside this file.) +AC_DEFUN([AM_AUTOMAKE_VERSION], +[am__api_version='1.11' +dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to +dnl require some minimum version. Point them to the right macro. +m4_if([$1], [1.11.6], [], + [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl +]) + +# _AM_AUTOCONF_VERSION(VERSION) +# ----------------------------- +# aclocal traces this macro to find the Autoconf version. +# This is a private macro too. Using m4_define simplifies +# the logic in aclocal, which can simply ignore this definition. +m4_define([_AM_AUTOCONF_VERSION], []) + +# AM_SET_CURRENT_AUTOMAKE_VERSION +# ------------------------------- +# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. +# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. +AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], +[AM_AUTOMAKE_VERSION([1.11.6])dnl +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) + +# AM_AUX_DIR_EXPAND -*- Autoconf -*- + +# Copyright (C) 2001, 2003, 2005, 2011 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 1 + +# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets +# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to +# `$srcdir', `$srcdir/..', or `$srcdir/../..'. +# +# Of course, Automake must honor this variable whenever it calls a +# tool from the auxiliary directory. The problem is that $srcdir (and +# therefore $ac_aux_dir as well) can be either absolute or relative, +# depending on how configure is run. This is pretty annoying, since +# it makes $ac_aux_dir quite unusable in subdirectories: in the top +# source directory, any form will work fine, but in subdirectories a +# relative path needs to be adjusted first. +# +# $ac_aux_dir/missing +# fails when called from a subdirectory if $ac_aux_dir is relative +# $top_srcdir/$ac_aux_dir/missing +# fails if $ac_aux_dir is absolute, +# fails when called from a subdirectory in a VPATH build with +# a relative $ac_aux_dir +# +# The reason of the latter failure is that $top_srcdir and $ac_aux_dir +# are both prefixed by $srcdir. In an in-source build this is usually +# harmless because $srcdir is `.', but things will broke when you +# start a VPATH build or use an absolute $srcdir. +# +# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, +# iff we strip the leading $srcdir from $ac_aux_dir. That would be: +# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` +# and then we would define $MISSING as +# MISSING="\${SHELL} $am_aux_dir/missing" +# This will work as long as MISSING is not called from configure, because +# unfortunately $(top_srcdir) has no meaning in configure. +# However there are other variables, like CC, which are often used in +# configure, and could therefore not use this "fixed" $ac_aux_dir. +# +# Another solution, used here, is to always expand $ac_aux_dir to an +# absolute PATH. The drawback is that using absolute paths prevent a +# configured tree to be moved without reconfiguration. + +AC_DEFUN([AM_AUX_DIR_EXPAND], +[dnl Rely on autoconf to set up CDPATH properly. +AC_PREREQ([2.50])dnl +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` +]) + +# AM_CONDITIONAL -*- Autoconf -*- + +# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006, 2008 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 9 + +# AM_CONDITIONAL(NAME, SHELL-CONDITION) +# ------------------------------------- +# Define a conditional. +AC_DEFUN([AM_CONDITIONAL], +[AC_PREREQ(2.52)dnl + ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], + [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl +AC_SUBST([$1_TRUE])dnl +AC_SUBST([$1_FALSE])dnl +_AM_SUBST_NOTMAKE([$1_TRUE])dnl +_AM_SUBST_NOTMAKE([$1_FALSE])dnl +m4_define([_AM_COND_VALUE_$1], [$2])dnl +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi +AC_CONFIG_COMMANDS_PRE( +[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then + AC_MSG_ERROR([[conditional "$1" was never defined. +Usually this means the macro was only invoked conditionally.]]) +fi])]) + +# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009, +# 2010, 2011 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 12 + +# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be +# written in clear, in which case automake, when reading aclocal.m4, +# will think it sees a *use*, and therefore will trigger all it's +# C support machinery. Also note that it means that autoscan, seeing +# CC etc. in the Makefile, will ask for an AC_PROG_CC use... + + +# _AM_DEPENDENCIES(NAME) +# ---------------------- +# See how the compiler implements dependency checking. +# NAME is "CC", "CXX", "GCJ", or "OBJC". +# We try a few techniques and use that to set a single cache variable. +# +# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was +# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular +# dependency, and given that the user is not expected to run this macro, +# just rely on AC_PROG_CC. +AC_DEFUN([_AM_DEPENDENCIES], +[AC_REQUIRE([AM_SET_DEPDIR])dnl +AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl +AC_REQUIRE([AM_MAKE_INCLUDE])dnl +AC_REQUIRE([AM_DEP_TRACK])dnl + +ifelse([$1], CC, [depcc="$CC" am_compiler_list=], + [$1], CXX, [depcc="$CXX" am_compiler_list=], + [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'], + [$1], UPC, [depcc="$UPC" am_compiler_list=], + [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], + [depcc="$$1" am_compiler_list=]) + +AC_CACHE_CHECK([dependency style of $depcc], + [am_cv_$1_dependencies_compiler_type], +[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_$1_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` + fi + am__universal=false + m4_case([$1], [CC], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac], + [CXX], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac]) + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with + # Solaris 8's {/usr,}/bin/sh. + touch sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok `-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_$1_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_$1_dependencies_compiler_type=none +fi +]) +AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) +AM_CONDITIONAL([am__fastdep$1], [ + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) +]) + + +# AM_SET_DEPDIR +# ------------- +# Choose a directory name for dependency files. +# This macro is AC_REQUIREd in _AM_DEPENDENCIES +AC_DEFUN([AM_SET_DEPDIR], +[AC_REQUIRE([AM_SET_LEADING_DOT])dnl +AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl +]) + + +# AM_DEP_TRACK +# ------------ +AC_DEFUN([AM_DEP_TRACK], +[AC_ARG_ENABLE(dependency-tracking, +[ --disable-dependency-tracking speeds up one-time build + --enable-dependency-tracking do not reject slow dependency extractors]) +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' + am__nodep='_no' +fi +AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) +AC_SUBST([AMDEPBACKSLASH])dnl +_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl +AC_SUBST([am__nodep])dnl +_AM_SUBST_NOTMAKE([am__nodep])dnl +]) + +# Generate code to set up dependency tracking. -*- Autoconf -*- + +# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +#serial 5 + +# _AM_OUTPUT_DEPENDENCY_COMMANDS +# ------------------------------ +AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], +[{ + # Autoconf 2.62 quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named `Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`AS_DIRNAME("$mf")` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running `make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n 's/^U = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`AS_DIRNAME(["$file"])` + AS_MKDIR_P([$dirpart/$fdir]) + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} +])# _AM_OUTPUT_DEPENDENCY_COMMANDS + + +# AM_OUTPUT_DEPENDENCY_COMMANDS +# ----------------------------- +# This macro should only be invoked once -- use via AC_REQUIRE. +# +# This code is only required when automatic dependency tracking +# is enabled. FIXME. This creates each `.P' file that we will +# need in order to bootstrap the dependency handling code. +AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], +[AC_CONFIG_COMMANDS([depfiles], + [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], + [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) +]) + +# Do all the work for Automake. -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, +# 2005, 2006, 2008, 2009 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 16 + +# This macro actually does too much. Some checks are only needed if +# your package does certain things. But this isn't really a big deal. + +# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) +# AM_INIT_AUTOMAKE([OPTIONS]) +# ----------------------------------------------- +# The call with PACKAGE and VERSION arguments is the old style +# call (pre autoconf-2.50), which is being phased out. PACKAGE +# and VERSION should now be passed to AC_INIT and removed from +# the call to AM_INIT_AUTOMAKE. +# We support both call styles for the transition. After +# the next Automake release, Autoconf can make the AC_INIT +# arguments mandatory, and then we can depend on a new Autoconf +# release and drop the old call support. +AC_DEFUN([AM_INIT_AUTOMAKE], +[AC_PREREQ([2.62])dnl +dnl Autoconf wants to disallow AM_ names. We explicitly allow +dnl the ones we care about. +m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl +AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl +AC_REQUIRE([AC_PROG_INSTALL])dnl +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi +AC_SUBST([CYGPATH_W]) + +# Define the identity of the package. +dnl Distinguish between old-style and new-style calls. +m4_ifval([$2], +[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl + AC_SUBST([PACKAGE], [$1])dnl + AC_SUBST([VERSION], [$2])], +[_AM_SET_OPTIONS([$1])dnl +dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. +m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,, + [m4_fatal([AC_INIT should be called with package and version arguments])])dnl + AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl + AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl + +_AM_IF_OPTION([no-define],, +[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) + AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl + +# Some tools Automake needs. +AC_REQUIRE([AM_SANITY_CHECK])dnl +AC_REQUIRE([AC_ARG_PROGRAM])dnl +AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}) +AM_MISSING_PROG(AUTOCONF, autoconf) +AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}) +AM_MISSING_PROG(AUTOHEADER, autoheader) +AM_MISSING_PROG(MAKEINFO, makeinfo) +AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl +AC_REQUIRE([AM_PROG_MKDIR_P])dnl +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([AC_PROG_MAKE_SET])dnl +AC_REQUIRE([AM_SET_LEADING_DOT])dnl +_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], + [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], + [_AM_PROG_TAR([v7])])]) +_AM_IF_OPTION([no-dependencies],, +[AC_PROVIDE_IFELSE([AC_PROG_CC], + [_AM_DEPENDENCIES(CC)], + [define([AC_PROG_CC], + defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl +AC_PROVIDE_IFELSE([AC_PROG_CXX], + [_AM_DEPENDENCIES(CXX)], + [define([AC_PROG_CXX], + defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJC], + [_AM_DEPENDENCIES(OBJC)], + [define([AC_PROG_OBJC], + defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl +]) +_AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl +dnl The `parallel-tests' driver may need to know about EXEEXT, so add the +dnl `am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro +dnl is hooked onto _AC_COMPILER_EXEEXT early, see below. +AC_CONFIG_COMMANDS_PRE(dnl +[m4_provide_if([_AM_COMPILER_EXEEXT], + [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl +]) + +dnl Hook into `_AC_COMPILER_EXEEXT' early to learn its expansion. Do not +dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further +dnl mangled by Autoconf and run in a shell conditional statement. +m4_define([_AC_COMPILER_EXEEXT], +m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) + + +# When config.status generates a header, we must update the stamp-h file. +# This file resides in the same directory as the config header +# that is generated. The stamp files are numbered to have different names. + +# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the +# loop where config.status creates the headers, so we can generate +# our stamp files there. +AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], +[# Compute $1's index in $config_headers. +_am_arg=$1 +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) + +# Copyright (C) 2001, 2003, 2005, 2008, 2011 Free Software Foundation, +# Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 1 + +# AM_PROG_INSTALL_SH +# ------------------ +# Define $install_sh. +AC_DEFUN([AM_PROG_INSTALL_SH], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +if test x"${install_sh}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi +AC_SUBST(install_sh)]) + +# Copyright (C) 2003, 2005 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 2 + +# Check whether the underlying file-system supports filenames +# with a leading dot. For instance MS-DOS doesn't. +AC_DEFUN([AM_SET_LEADING_DOT], +[rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null +AC_SUBST([am__leading_dot])]) + +# Add --enable-maintainer-mode option to configure. -*- Autoconf -*- +# From Jim Meyering + +# Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2008, +# 2011 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 5 + +# AM_MAINTAINER_MODE([DEFAULT-MODE]) +# ---------------------------------- +# Control maintainer-specific portions of Makefiles. +# Default is to disable them, unless `enable' is passed literally. +# For symmetry, `disable' may be passed as well. Anyway, the user +# can override the default with the --enable/--disable switch. +AC_DEFUN([AM_MAINTAINER_MODE], +[m4_case(m4_default([$1], [disable]), + [enable], [m4_define([am_maintainer_other], [disable])], + [disable], [m4_define([am_maintainer_other], [enable])], + [m4_define([am_maintainer_other], [enable]) + m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])]) +AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) + dnl maintainer-mode's default is 'disable' unless 'enable' is passed + AC_ARG_ENABLE([maintainer-mode], +[ --][am_maintainer_other][-maintainer-mode am_maintainer_other make rules and dependencies not useful + (and sometimes confusing) to the casual installer], + [USE_MAINTAINER_MODE=$enableval], + [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes])) + AC_MSG_RESULT([$USE_MAINTAINER_MODE]) + AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes]) + MAINT=$MAINTAINER_MODE_TRUE + AC_SUBST([MAINT])dnl +] +) + +AU_DEFUN([jm_MAINTAINER_MODE], [AM_MAINTAINER_MODE]) + +# Check to see how 'make' treats includes. -*- Autoconf -*- + +# Copyright (C) 2001, 2002, 2003, 2005, 2009 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 4 + +# AM_MAKE_INCLUDE() +# ----------------- +# Check to see how make treats includes. +AC_DEFUN([AM_MAKE_INCLUDE], +[am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +AC_MSG_CHECKING([for style of include used by $am_make]) +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from `make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi +AC_SUBST([am__include]) +AC_SUBST([am__quote]) +AC_MSG_RESULT([$_am_result]) +rm -f confinc confmf +]) + +# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- + +# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005, 2008 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 6 + +# AM_MISSING_PROG(NAME, PROGRAM) +# ------------------------------ +AC_DEFUN([AM_MISSING_PROG], +[AC_REQUIRE([AM_MISSING_HAS_RUN]) +$1=${$1-"${am_missing_run}$2"} +AC_SUBST($1)]) + + +# AM_MISSING_HAS_RUN +# ------------------ +# Define MISSING if not defined so far and test if it supports --run. +# If it does, set am_missing_run to use it, otherwise, to nothing. +AC_DEFUN([AM_MISSING_HAS_RUN], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([missing])dnl +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + AC_MSG_WARN([`missing' script is too old or missing]) +fi +]) + +# Copyright (C) 2003, 2004, 2005, 2006, 2011 Free Software Foundation, +# Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 1 + +# AM_PROG_MKDIR_P +# --------------- +# Check for `mkdir -p'. +AC_DEFUN([AM_PROG_MKDIR_P], +[AC_PREREQ([2.60])dnl +AC_REQUIRE([AC_PROG_MKDIR_P])dnl +dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P, +dnl while keeping a definition of mkdir_p for backward compatibility. +dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile. +dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of +dnl Makefile.ins that do not define MKDIR_P, so we do our own +dnl adjustment using top_builddir (which is defined more often than +dnl MKDIR_P). +AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl +case $mkdir_p in + [[\\/$]]* | ?:[[\\/]]*) ;; + */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; +esac +]) + +# Helper functions for option handling. -*- Autoconf -*- + +# Copyright (C) 2001, 2002, 2003, 2005, 2008, 2010 Free Software +# Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 5 + +# _AM_MANGLE_OPTION(NAME) +# ----------------------- +AC_DEFUN([_AM_MANGLE_OPTION], +[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) + +# _AM_SET_OPTION(NAME) +# -------------------- +# Set option NAME. Presently that only means defining a flag for this option. +AC_DEFUN([_AM_SET_OPTION], +[m4_define(_AM_MANGLE_OPTION([$1]), 1)]) + +# _AM_SET_OPTIONS(OPTIONS) +# ------------------------ +# OPTIONS is a space-separated list of Automake options. +AC_DEFUN([_AM_SET_OPTIONS], +[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) + +# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) +# ------------------------------------------- +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +AC_DEFUN([_AM_IF_OPTION], +[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) + +# Check to make sure that the build environment is sane. -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005, 2008 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 5 + +# AM_SANITY_CHECK +# --------------- +AC_DEFUN([AM_SANITY_CHECK], +[AC_MSG_CHECKING([whether build environment is sane]) +# Just in case +sleep 1 +echo timestamp > conftest.file +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[[\\\"\#\$\&\'\`$am_lf]]*) + AC_MSG_ERROR([unsafe absolute working directory name]);; +esac +case $srcdir in + *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) + AC_MSG_ERROR([unsafe srcdir value: `$srcdir']);; +esac + +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$[*]" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + rm -f conftest.file + if test "$[*]" != "X $srcdir/configure conftest.file" \ + && test "$[*]" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken +alias in your environment]) + fi + + test "$[2]" = conftest.file + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +AC_MSG_RESULT(yes)]) + +# Copyright (C) 2001, 2003, 2005, 2011 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 1 + +# AM_PROG_INSTALL_STRIP +# --------------------- +# One issue with vendor `install' (even GNU) is that you can't +# specify the program used to strip binaries. This is especially +# annoying in cross-compiling environments, where the build's strip +# is unlikely to handle the host's binaries. +# Fortunately install-sh will honor a STRIPPROG variable, so we +# always use install-sh in `make install-strip', and initialize +# STRIPPROG with the value of the STRIP variable (set by the user). +AC_DEFUN([AM_PROG_INSTALL_STRIP], +[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +# Installed binaries are usually stripped using `strip' when the user +# run `make install-strip'. However `strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the `STRIP' environment variable to overrule this program. +dnl Don't test for $cross_compiling = yes, because it might be `maybe'. +if test "$cross_compiling" != no; then + AC_CHECK_TOOL([STRIP], [strip], :) +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" +AC_SUBST([INSTALL_STRIP_PROGRAM])]) + +# Copyright (C) 2006, 2008, 2010 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 3 + +# _AM_SUBST_NOTMAKE(VARIABLE) +# --------------------------- +# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. +# This macro is traced by Automake. +AC_DEFUN([_AM_SUBST_NOTMAKE]) + +# AM_SUBST_NOTMAKE(VARIABLE) +# -------------------------- +# Public sister of _AM_SUBST_NOTMAKE. +AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) + +# Check how to create a tarball. -*- Autoconf -*- + +# Copyright (C) 2004, 2005, 2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 2 + +# _AM_PROG_TAR(FORMAT) +# -------------------- +# Check how to create a tarball in format FORMAT. +# FORMAT should be one of `v7', `ustar', or `pax'. +# +# Substitute a variable $(am__tar) that is a command +# writing to stdout a FORMAT-tarball containing the directory +# $tardir. +# tardir=directory && $(am__tar) > result.tar +# +# Substitute a variable $(am__untar) that extract such +# a tarball read from stdin. +# $(am__untar) < result.tar +AC_DEFUN([_AM_PROG_TAR], +[# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AC_SUBST([AMTAR], ['$${TAR-tar}']) +m4_if([$1], [v7], + [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], + [m4_case([$1], [ustar],, [pax],, + [m4_fatal([Unknown tar format])]) +AC_MSG_CHECKING([how to create a $1 tar archive]) +# Loop over all known methods to create a tar archive until one works. +_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' +_am_tools=${am_cv_prog_tar_$1-$_am_tools} +# Do not fold the above two line into one, because Tru64 sh and +# Solaris sh will not grok spaces in the rhs of `-'. +for _am_tool in $_am_tools +do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; + do + AM_RUN_LOG([$_am_tar --version]) && break + done + am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x $1 -w "$$tardir"' + am__tar_='pax -L -x $1 -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H $1 -L' + am__tar_='find "$tardir" -print | cpio -o -H $1 -L' + am__untar='cpio -i -H $1 -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_$1}" && break + + # tar/untar a dummy directory, and stop if the command works + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) + rm -rf conftest.dir + if test -s conftest.tar; then + AM_RUN_LOG([$am__untar /dev/null 2>&1 && break + fi +done +rm -rf conftest.dir + +AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) +AC_MSG_RESULT([$am_cv_prog_tar_$1])]) +AC_SUBST([am__tar]) +AC_SUBST([am__untar]) +]) # _AM_PROG_TAR + diff --git a/jni/lcms2-2.5/autogen.sh b/jni/lcms2-2.5/autogen.sh new file mode 100755 index 00000000..5c62310e --- /dev/null +++ b/jni/lcms2-2.5/autogen.sh @@ -0,0 +1,92 @@ +#!/bin/sh +# Run this to generate all the initial makefiles, etc. + +srcdir=`dirname $0` +test -z "$srcdir" && srcdir=. + +DIE=0 + +(test -f $srcdir/configure.ac) || { + echo -n "**Error**: Directory $srcdir does not look like the" + echo " top-level package directory" + exit 1 +} + +(autoconf --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "**Error**: You must have autoconf installed." + echo "Download the appropriate package for your distribution," + echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/" + DIE=1 +} + +(grep "^LT_INIT" $srcdir/configure.ac >/dev/null) && { + (libtool --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "**Error**: You must have libtool installed." + echo "You can get it from: ftp://ftp.gnu.org/pub/gnu/" + DIE=1 + } +} + +(automake --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "**Error**: You must have automake installed." + echo "You can get it from: ftp://ftp.gnu.org/pub/gnu/" + DIE=1 + NO_AUTOMAKE=yes +} + +# if no automake, don't bother testing for aclocal +test -n "$NO_AUTOMAKE" || (aclocal --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "**Error**: Missing aclocal. The version of automake" + echo "installed doesn't appear recent enough." + echo "You can get automake from ftp://ftp.gnu.org/pub/gnu/" + DIE=1 +} + +if test "$DIE" -eq 1; then + exit 1 +fi + +if test -z "$*"; then + echo "**Warning**: I am going to run configure with no arguments." + echo "If you wish to pass any to it, please specify them on the" + echo $0 " command line." + echo +fi + +case $CC in +xlc ) + am_opt=--include-deps;; +esac + + aclocalinclude="$ACLOCAL_FLAGS" + + if grep "^LT_INIT" configure.ac >/dev/null; then + if test -z "$NO_LIBTOOLIZE" ; then + echo "Running libtoolize..." + libtoolize --force --copy + fi + fi + echo "Running aclocal $aclocalinclude ..." + aclocal $aclocalinclude + if grep "^AC_CONFIG_HEADERS" configure.ac >/dev/null; then + echo "Running autoheader..." + autoheader + fi + echo "Running automake --add-missing --gnu -Wno-portability $am_opt ..." + automake --add-missing --gnu -Wno-portability $am_opt + echo "Running autoconf ..." + autoconf + +conf_flags="--enable-maintainer-mode" + +if test x$NOCONFIGURE = x; then + echo "Running $srcdir/configure $conf_flags $@ ..." + $srcdir/configure $conf_flags "$@" \ + && echo "Now type make to compile." || exit 1 +else + echo "Skipping configure process." +fi diff --git a/jni/lcms2-2.5/config.guess b/jni/lcms2-2.5/config.guess new file mode 100755 index 00000000..dc84c68e --- /dev/null +++ b/jni/lcms2-2.5/config.guess @@ -0,0 +1,1501 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 +# Free Software Foundation, Inc. + +timestamp='2009-11-20' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Originally written by Per Bothner. Please send patches (context +# diff format) to and include a ChangeLog +# entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[456]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + case ${UNAME_MACHINE} in + pc98) + echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-gnu + else + echo ${UNAME_MACHINE}-unknown-linux-gnueabi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo cris-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo crisv32-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo frv-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + LIBC=gnu + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo or32-unknown-linux-gnu + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-gnu + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-gnu + exit ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + i386) + eval $set_cc_for_build + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + UNAME_PROCESSOR="x86_64" + fi + fi ;; + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix\n"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/jni/lcms2-2.5/config.sub b/jni/lcms2-2.5/config.sub new file mode 100755 index 00000000..2a55a507 --- /dev/null +++ b/jni/lcms2-2.5/config.sub @@ -0,0 +1,1705 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 +# Free Software Foundation, Inc. + +timestamp='2009-11-20' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Please send patches to . Submit a context +# diff and a properly formatted GNU ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \ + uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \ + kopensolaris*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray | -microblaze) + os= + basic_machine=$1 + ;; + -bluegene*) + os=-cnk + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | fido | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nios | nios2 \ + | ns16k | ns32k \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu | strongarm \ + | tahoe | thumb | tic4x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e \ + | we32k \ + | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12 | picochip) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nios-* | nios2-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* | tile-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + microblaze) + basic_machine=microblaze-xilinx + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tic55x | c55x*) + basic_machine=tic55x-unknown + os=-coff + ;; + tic6x | c6x*) + basic_machine=tic6x-unknown + os=-coff + ;; + tile*) + basic_machine=tile-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* | -cegcc* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -cnk*|-aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/jni/lcms2-2.5/configure.ac b/jni/lcms2-2.5/configure.ac new file mode 100644 index 00000000..7041865f --- /dev/null +++ b/jni/lcms2-2.5/configure.ac @@ -0,0 +1,285 @@ +# +# LittleCMS 2 configure script +# + +AC_PREREQ(2.60) + +# +# Set the package name and version +# +AC_INIT(lcms2,2.5) + +# +# Libtool library revision control info +# See the libtool documentation under the heading "Libtool's versioning +# system" in order to understand the meaning of these fields +# +# Here are a set of rules to help you update your library version +# information: +# +# 1. Start with version information of `0:0:0' for each libtool library. +# 2. Update the version information only immediately before a public +# release of your software. More frequent updates are unnecessary, and +# only guarantee that the current interface number gets larger faster. +# 3. If the library source code has changed at all since the last update, +# then increment revision (`c:r:a' becomes `c:r+1:a'). +# 4. If any interfaces have been added, removed, or changed since the last +# update, increment current, and set revision to 0. +# 5. If any interfaces have been added since the last public release, then +# increment age. +# 6. If any interfaces have been removed since the last public release, +# then set age to 0. +# +LIBRARY_CURRENT=2 +LIBRARY_REVISION=5 +LIBRARY_AGE=0 + +AC_SUBST(LIBRARY_CURRENT)dnl +AC_SUBST(LIBRARY_REVISION)dnl +AC_SUBST(LIBRARY_AGE)dnl + +# Obtain system type by running config.guess +AC_CANONICAL_HOST + +AM_INIT_AUTOMAKE([foreign 1.7.2 no-define dist-zip]) + +# Disable JPEG. +AC_ARG_WITH(jpeg, + [ --without-jpeg disable JPEG support], + [with_jpeg=$withval], + [with_jpeg='yes']) + +# Disable TIFF. +AC_ARG_WITH(tiff, + [ --without-tiff disable TIFF support], + [with_tiff=$withval], + [with_tiff='yes']) + +# Disable ZLIB +AC_ARG_WITH(zlib, + [ --without-zlib disable ZLIB support], + [with_zlib=$withval], + [with_zlib='yes']) + +# Check for programs +AC_PROG_CC_STDC +AC_PROG_CPP +AC_PROG_CXX + +#AM_PROG_LD +#AC_SUBST(LD) +#AC_PROG_INSTALL +#AC_PROG_MAKE_SET +#AC_PROG_LN_S + +# +# Tests for Windows +# +AC_EXEEXT +AC_OBJEXT + +# Configure libtool +AC_ENABLE_SHARED +AC_ENABLE_STATIC +AC_LIBTOOL_WIN32_DLL +AC_LIBTOOL_SETUP +AC_PROG_LIBTOOL +AC_SUBST(LIBTOOL_DEPS) + +# Add configure option --enable-maintainer-mode which enables dependency +# checking and generation useful to package maintainers. This is made an +# option to avoid confusing end users. +AM_MAINTAINER_MODE + +# If the C compiler supports the keyword inline, do nothing. Otherwise +# define inline to __inline__ or __inline if it accepts one of those, +# otherwise define inline to be empty. +AC_C_INLINE +AC_SUBST(inline) + +# If words are stored with the most significant byte first (like +# Motorola and SPARC CPUs), define `WORDS_BIGENDIAN'. +AC_C_BIGENDIAN + +# +# Find math library +# +LIB_MATH='' +AC_CHECK_LIB(m,sqrt,LIB_MATH="-lm",,) +LIBS="$LIB_MATH $LIBS" +AC_SUBST(LIB_MATH) + +# +# Check for JPEG +# +have_jpeg='no' +LIB_JPEG='' +if test ! "$with_jpeg" = 'no' +then + AC_MSG_CHECKING(for JPEG support ) + AC_MSG_RESULT() + failed=0; + passed=0; + AC_CHECK_HEADER(jconfig.h,passed=`expr $passed + 1`,failed=`expr $failed + 1`) + AC_CHECK_HEADER(jerror.h,passed=`expr $passed + 1`,failed=`expr $failed + 1`) + AC_CHECK_HEADER(jmorecfg.h,passed=`expr $passed + 1`,failed=`expr $failed + 1`) + AC_CHECK_HEADER(jpeglib.h,passed=`expr $passed + 1`,failed=`expr $failed + 1`) + AC_CHECK_LIB(jpeg,jpeg_read_header,passed=`expr $passed + 1`,failed=`expr $failed + 1`,) + +# Test for compatible JPEG library +if test ! "$ac_cv_jpeg_version_ok" = 'yes' ; then +AC_CACHE_CHECK(for JPEG library is version 6b or later, ac_cv_jpeg_version_ok, +[AC_TRY_COMPILE( +#include +#include +#include +, +changequote(<<, >>)dnl +<< +#if JPEG_LIB_VERSION < 62 +#error IJG JPEG library must be version 6b or newer! +#endif +return 0; +>>, +changequote([, ])dnl +ac_cv_jpeg_version_ok='yes', +ac_cv_jpeg_version_ok='no')]) +if test "$ac_cv_jpeg_version_ok" = 'yes' ; then + AC_MSG_RESULT(yes) + passed=`expr $passed + 1` +else + AC_MSG_RESULT(no) + failed=`expr $failed + 1` +fi +fi + AC_MSG_CHECKING(if JPEG package is complete) + if test $passed -gt 0 + then + if test $failed -gt 0 + then + AC_MSG_RESULT(no -- some components failed test) + have_jpeg='no (failed tests)' + else + LIB_JPEG='-ljpeg' + LIBS="$LIB_JPEG $LIBS" + AC_DEFINE(HasJPEG,1,Define if you have JPEG library) + AC_MSG_RESULT(yes) + have_jpeg='yes' + fi + else + AC_MSG_RESULT(no) + fi +fi +AM_CONDITIONAL(HasJPEG, test "$have_jpeg" = 'yes') +AC_SUBST(LIB_JPEG) + +# +# Check for ZLIB +# +have_zlib='no' +dnl PNG requires zlib so enable zlib check if PNG is requested +if test ! "$with_zlib" = 'no' || test ! "$with_png" = 'no' +then + LIB_ZLIB='' + AC_MSG_CHECKING(for ZLIB support ) + AC_MSG_RESULT() + failed=0; + passed=0; + AC_CHECK_HEADER(zconf.h,passed=`expr $passed + 1`,failed=`expr $failed + 1`) + AC_CHECK_HEADER(zlib.h,passed=`expr $passed + 1`,failed=`expr $failed + 1`) + AC_CHECK_LIB(z,compress,passed=`expr $passed + 1`,failed=`expr $failed + 1`,) + AC_CHECK_LIB(z,uncompress,passed=`expr $passed + 1`,failed=`expr $failed + 1`,) + AC_CHECK_LIB(z,deflate,passed=`expr $passed + 1`,failed=`expr $failed + 1`,) + AC_CHECK_LIB(z,inflate,passed=`expr $passed + 1`,failed=`expr $failed + 1`,) + AC_CHECK_LIB(z,gzseek,passed=`expr $passed + 1`,failed=`expr $failed + 1`,) + AC_CHECK_LIB(z,gztell,passed=`expr $passed + 1`,failed=`expr $failed + 1`,) + AC_MSG_CHECKING(if ZLIB package is complete) + if test $passed -gt 0 + then + if test $failed -gt 0 + then + AC_MSG_RESULT(no -- some components failed test) + have_zlib='no (failed tests)' + else + LIB_ZLIB='-lz' + LIBS="$LIB_ZLIB $LIBS" + AC_DEFINE(HasZLIB,1,Define if you have zlib compression library) + AC_MSG_RESULT(yes) + have_zlib='yes' + fi + else + AC_MSG_RESULT(no) + fi +fi +AM_CONDITIONAL(HasZLIB, test "$have_zlib" = 'yes') +AC_SUBST(LIB_ZLIB) + +# +# Check for TIFF +# +have_tiff='no' +LIB_TIFF='' +if test ! "$with_tiff" = 'no' +then + AC_MSG_CHECKING(for TIFF support ) + AC_MSG_RESULT() + failed=0; + passed=0; + AC_CHECK_HEADER(tiff.h,passed=`expr $passed + 1`,failed=`expr $failed + 1`) + AC_CHECK_HEADER(tiffio.h,passed=`expr $passed + 1`,failed=`expr $failed + 1`) + AC_CHECK_LIB(tiff,TIFFOpen,passed=`expr $passed + 1`,failed=`expr $failed + 1`,) + AC_CHECK_LIB(tiff,TIFFClientOpen,passed=`expr $passed + 1`,failed=`expr $failed + 1`,) + AC_CHECK_LIB(tiff,TIFFIsByteSwapped,passed=`expr $passed + 1`,failed=`expr $failed + 1`,) + AC_MSG_CHECKING(if TIFF package is complete) + if test $passed -gt 0 + then + if test $failed -gt 0 + then + AC_MSG_RESULT(no -- some components failed test) + have_tiff='no (failed tests)' + else + LIB_TIFF='-ltiff' + LIBS="$LIB_TIFF $LIBS" + AC_DEFINE(HasTIFF,1,Define if you have TIFF library) + AC_MSG_RESULT(yes) + have_tiff='yes' + AC_CHECK_HEADERS(tiffconf.h) + fi + else + AC_MSG_RESULT(no) + fi +fi +AM_CONDITIONAL(HasTIFF, test "$have_tiff" = 'yes') +AC_SUBST(LIB_TIFF) + +# Libraries that the LCMS library depends on +LCMS_LIB_DEPLIBS="$LIB_MATH" +LCMS_LIB_DEPLIBS=`echo $LCMS_LIB_DEPLIBS | sed -e 's/ */ /g'` +AC_SUBST(LCMS_LIB_DEPLIBS) + +# Libraries that the jpegicc program depends on +JPEGICC_DEPLIBS="$LIB_JPEG $LIB_MATH" +JPEGICC_DEPLIBS=`echo $JPEGICC_DEPLIBS | sed -e 's/ */ /g'` +AC_SUBST(JPEGICC_DEPLIBS) + +# Libraries that the tifficc program depends on +TIFFICC_DEPLIBS="$LIB_TIFF $LIB_JPEG $LIB_ZLIB $LIB_MATH" +TIFFICC_DEPLIBS=`echo $TIFFICC_DEPLIBS | sed -e 's/ */ /g'` +AC_SUBST(TIFFICC_DEPLIBS) + +LIBS='' + +# +# Perform substitutions +# +AC_CONFIG_FILES([Makefile]) +AC_CONFIG_FILES([lcms2.pc]) +AC_CONFIG_FILES([include/Makefile]) +AC_CONFIG_FILES([src/Makefile]) +AC_CONFIG_FILES([utils/tificc/Makefile]) +AC_CONFIG_FILES([utils/transicc/Makefile]) +AC_CONFIG_FILES([utils/linkicc/Makefile]) +AC_CONFIG_FILES([utils/jpgicc/Makefile]) +AC_CONFIG_FILES([utils/psicc/Makefile]) +AC_CONFIG_FILES([testbed/Makefile]) +AC_OUTPUT diff --git a/jni/lcms2-2.5/depcomp b/jni/lcms2-2.5/depcomp new file mode 100644 index 00000000..11e2d3bf --- /dev/null +++ b/jni/lcms2-2.5/depcomp @@ -0,0 +1,522 @@ +#! /bin/sh +# depcomp - compile a program generating dependencies as side-effects + +scriptversion=2004-05-31.23 + +# Copyright (C) 1999, 2000, 2003, 2004 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Alexandre Oliva . + +case $1 in + '') + echo "$0: No command. Try \`$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: depcomp [--help] [--version] PROGRAM [ARGS] + +Run PROGRAMS ARGS to compile a file, generating dependencies +as side-effects. + +Environment variables: + depmode Dependency tracking mode. + source Source file read by `PROGRAMS ARGS'. + object Object file output by `PROGRAMS ARGS'. + DEPDIR directory where to store dependencies. + depfile Dependency file to output. + tmpdepfile Temporary file to use when outputing dependencies. + libtool Whether libtool is used (yes/no). + +Report bugs to . +EOF + exit 0 + ;; + -v | --v*) + echo "depcomp $scriptversion" + exit 0 + ;; +esac + +if test -z "$depmode" || test -z "$source" || test -z "$object"; then + echo "depcomp: Variables source, object and depmode must be set" 1>&2 + exit 1 +fi + +# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. +depfile=${depfile-`echo "$object" | + sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} +tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} + +rm -f "$tmpdepfile" + +# Some modes work just like other modes, but use different flags. We +# parameterize here, but still list the modes in the big case below, +# to make depend.m4 easier to write. Note that we *cannot* use a case +# here, because this file can only contain one case statement. +if test "$depmode" = hp; then + # HP compiler uses -M and no extra arg. + gccflag=-M + depmode=gcc +fi + +if test "$depmode" = dashXmstdout; then + # This is just like dashmstdout with a different argument. + dashmflag=-xM + depmode=dashmstdout +fi + +case "$depmode" in +gcc3) +## gcc 3 implements dependency tracking that does exactly what +## we want. Yay! Note: for some reason libtool 1.4 doesn't like +## it if -MD -MP comes after the -MF stuff. Hmm. + "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + +gcc) +## There are various ways to get dependency output from gcc. Here's +## why we pick this rather obscure method: +## - Don't want to use -MD because we'd like the dependencies to end +## up in a subdir. Having to rename by hand is ugly. +## (We might end up doing this anyway to support other compilers.) +## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like +## -MM, not -M (despite what the docs say). +## - Using -M directly means running the compiler twice (even worse +## than renaming). + if test -z "$gccflag"; then + gccflag=-MD, + fi + "$@" -Wp,"$gccflag$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz +## The second -e expression handles DOS-style file names with drive letters. + sed -e 's/^[^:]*: / /' \ + -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" +## This next piece of magic avoids the `deleted header file' problem. +## The problem is that when a header file which appears in a .P file +## is deleted, the dependency causes make to die (because there is +## typically no way to rebuild the header). We avoid this by adding +## dummy dependencies for each header file. Too bad gcc doesn't do +## this for us directly. + tr ' ' ' +' < "$tmpdepfile" | +## Some versions of gcc put a space before the `:'. On the theory +## that the space means something, we add a space to the output as +## well. +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +sgi) + if test "$libtool" = yes; then + "$@" "-Wp,-MDupdate,$tmpdepfile" + else + "$@" -MDupdate "$tmpdepfile" + fi + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + + if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files + echo "$object : \\" > "$depfile" + + # Clip off the initial element (the dependent). Don't try to be + # clever and replace this with sed code, as IRIX sed won't handle + # lines with more than a fixed number of characters (4096 in + # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; + # the IRIX cc adds comments like `#:fec' to the end of the + # dependency line. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ + tr ' +' ' ' >> $depfile + echo >> $depfile + + # The second pass generates a dummy entry for each header file. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> $depfile + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +aix) + # The C for AIX Compiler uses -M and outputs the dependencies + # in a .u file. In older versions, this file always lives in the + # current directory. Also, the AIX compiler puts `$object:' at the + # start of each line; $object doesn't have directory information. + # Version 6 uses the directory in both cases. + stripped=`echo "$object" | sed 's/\(.*\)\..*$/\1/'` + tmpdepfile="$stripped.u" + if test "$libtool" = yes; then + "$@" -Wc,-M + else + "$@" -M + fi + stat=$? + + if test -f "$tmpdepfile"; then : + else + stripped=`echo "$stripped" | sed 's,^.*/,,'` + tmpdepfile="$stripped.u" + fi + + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + + if test -f "$tmpdepfile"; then + outname="$stripped.o" + # Each line is of the form `foo.o: dependent.h'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile" + sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile" + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +icc) + # Intel's C compiler understands `-MD -MF file'. However on + # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c + # ICC 7.0 will fill foo.d with something like + # foo.o: sub/foo.c + # foo.o: sub/foo.h + # which is wrong. We want: + # sub/foo.o: sub/foo.c + # sub/foo.o: sub/foo.h + # sub/foo.c: + # sub/foo.h: + # ICC 7.1 will output + # foo.o: sub/foo.c sub/foo.h + # and will wrap long lines using \ : + # foo.o: sub/foo.c ... \ + # sub/foo.h ... \ + # ... + + "$@" -MD -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each line is of the form `foo.o: dependent.h', + # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | + sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +tru64) + # The Tru64 compiler uses -MD to generate dependencies as a side + # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # dependencies in `foo.d' instead, so we check for that too. + # Subdirectories are respected. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + + if test "$libtool" = yes; then + # Dependencies are output in .lo.d with libtool 1.4. + # With libtool 1.5 they are output both in $dir.libs/$base.o.d + # and in $dir.libs/$base.o.d and $dir$base.o.d. We process the + # latter, because the former will be cleaned when $dir.libs is + # erased. + tmpdepfile1="$dir.libs/$base.lo.d" + tmpdepfile2="$dir$base.o.d" + tmpdepfile3="$dir.libs/$base.d" + "$@" -Wc,-MD + else + tmpdepfile1="$dir$base.o.d" + tmpdepfile2="$dir$base.d" + tmpdepfile3="$dir$base.d" + "$@" -MD + fi + + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + if test -f "$tmpdepfile1"; then + tmpdepfile="$tmpdepfile1" + elif test -f "$tmpdepfile2"; then + tmpdepfile="$tmpdepfile2" + else + tmpdepfile="$tmpdepfile3" + fi + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" + # That's a tab and a space in the []. + sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +#nosideeffect) + # This comment above is used by automake to tell side-effect + # dependency tracking mechanisms from slower ones. + +dashmstdout) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + test -z "$dashmflag" && dashmflag=-M + # Require at least two characters before searching for `:' + # in the target name. This is to cope with DOS-style filenames: + # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. + "$@" $dashmflag | + sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + tr ' ' ' +' < "$tmpdepfile" | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +dashXmstdout) + # This case only exists to satisfy depend.m4. It is never actually + # run, as this mode is specially recognized in the preamble. + exit 1 + ;; + +makedepend) + "$@" || exit $? + # Remove any Libtool call + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + # X makedepend + shift + cleared=no + for arg in "$@"; do + case $cleared in + no) + set ""; shift + cleared=yes ;; + esac + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift ;; + # Strip any option that makedepend may not understand. Remove + # the object too, otherwise makedepend will parse it as a source file. + -*|$object) + ;; + *) + set fnord "$@" "$arg"; shift ;; + esac + done + obj_suffix="`echo $object | sed 's/^.*\././'`" + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + sed '1,2d' "$tmpdepfile" | tr ' ' ' +' | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" "$tmpdepfile".bak + ;; + +cpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + "$@" -E | + sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | + sed '$ s: \\$::' > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + cat < "$tmpdepfile" >> "$depfile" + sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvisualcpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o, + # because we must use -o when running libtool. + "$@" || exit $? + IFS=" " + for arg + do + case "$arg" in + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + set fnord "$@" + shift + shift + ;; + *) + set fnord "$@" "$arg" + shift + shift + ;; + esac + done + "$@" -E | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" + echo " " >> "$depfile" + . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +none) + exec "$@" + ;; + +*) + echo "Unknown depmode $depmode" 1>&2 + exit 1 + ;; +esac + +exit 0 + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/jni/lcms2-2.5/include/Makefile.am b/jni/lcms2-2.5/include/Makefile.am new file mode 100644 index 00000000..7dbe0e43 --- /dev/null +++ b/jni/lcms2-2.5/include/Makefile.am @@ -0,0 +1,7 @@ +# +# Makefile for include directory +# Based on a work by Bob Friesenhahn + +include_HEADERS = lcms2.h lcms2_plugin.h + +EXTRA_DIST = lcms2.h lcms2_plugin.h diff --git a/jni/lcms2-2.5/include/Makefile.in b/jni/lcms2-2.5/include/Makefile.in new file mode 100644 index 00000000..741f30c6 --- /dev/null +++ b/jni/lcms2-2.5/include/Makefile.in @@ -0,0 +1,505 @@ +# Makefile.in generated by automake 1.11.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# +# Makefile for include directory +# Based on a work by Bob Friesenhahn + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = include +DIST_COMMON = $(include_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(includedir)" +HEADERS = $(include_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +JPEGICC_DEPLIBS = @JPEGICC_DEPLIBS@ +LCMS_LIB_DEPLIBS = @LCMS_LIB_DEPLIBS@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBRARY_AGE = @LIBRARY_AGE@ +LIBRARY_CURRENT = @LIBRARY_CURRENT@ +LIBRARY_REVISION = @LIBRARY_REVISION@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBTOOL_DEPS = @LIBTOOL_DEPS@ +LIB_JPEG = @LIB_JPEG@ +LIB_MATH = @LIB_MATH@ +LIB_TIFF = @LIB_TIFF@ +LIB_ZLIB = @LIB_ZLIB@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +TIFFICC_DEPLIBS = @TIFFICC_DEPLIBS@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +inline = @inline@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +include_HEADERS = lcms2.h lcms2_plugin.h +EXTRA_DIST = lcms2.h lcms2_plugin.h +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign include/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign include/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-includeHEADERS: $(include_HEADERS) + @$(NORMAL_INSTALL) + @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(includedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(includedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(includedir)" || exit $$?; \ + done + +uninstall-includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir) + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(includedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-includeHEADERS + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-includeHEADERS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool ctags distclean distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am \ + install-includeHEADERS install-info install-info-am \ + install-man install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags uninstall uninstall-am uninstall-includeHEADERS + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/jni/lcms2-2.5/include/lcms2.h b/jni/lcms2-2.5/include/lcms2.h new file mode 100644 index 00000000..89cd37a2 --- /dev/null +++ b/jni/lcms2-2.5/include/lcms2.h @@ -0,0 +1,1829 @@ +//--------------------------------------------------------------------------------- +// +// Little Color Management System +// Copyright (c) 1998-2013 Marti Maria Saguer +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//--------------------------------------------------------------------------------- +// +// Version 2.5 +// + +#ifndef _lcms2_H + +// ********** Configuration toggles **************************************** + +// Uncomment this one if you are using big endian machines +// #define CMS_USE_BIG_ENDIAN 1 + +// Uncomment this one if your compiler/machine does NOT support the +// "long long" type. +// #define CMS_DONT_USE_INT64 1 + +// Uncomment this if your compiler doesn't work with fast floor function +// #define CMS_DONT_USE_FAST_FLOOR 1 + +// Uncomment this line if you want lcms to use the black point tag in profile, +// if commented, lcms will compute the black point by its own. +// It is safer to leave it commented out +// #define CMS_USE_PROFILE_BLACK_POINT_TAG 1 + +// Uncomment this line if you are compiling as C++ and want a C++ API +// #define CMS_USE_CPP_API + +// Uncomment this line if you need strict CGATS syntax. Makes CGATS files to +// require "KEYWORD" on undefined identifiers, keep it comented out unless needed +// #define CMS_STRICT_CGATS 1 + +// Uncomment to get rid of the tables for "half" float support +// #define CMS_NO_HALF_SUPPORT 1 + +// ********** End of configuration toggles ****************************** + +// Needed for streams +#include + +// Needed for portability (C99 per 7.1.2) +#include +#include +#include + +#ifndef CMS_USE_CPP_API +# ifdef __cplusplus +extern "C" { +# endif +#endif + +// Version/release +#define LCMS_VERSION 2050 + +// I will give the chance of redefining basic types for compilers that are not fully C99 compliant +#ifndef CMS_BASIC_TYPES_ALREADY_DEFINED + +// Base types +typedef unsigned char cmsUInt8Number; // That is guaranteed by the C99 spec +typedef signed char cmsInt8Number; // That is guaranteed by the C99 spec + +#if CHAR_BIT != 8 +# error "Unable to find 8 bit type, unsupported compiler" +#endif + +// IEEE float storage numbers +typedef float cmsFloat32Number; +typedef double cmsFloat64Number; + +// 16-bit base types +#if (USHRT_MAX == 65535U) + typedef unsigned short cmsUInt16Number; +#elif (UINT_MAX == 65535U) + typedef unsigned int cmsUInt16Number; +#else +# error "Unable to find 16 bits unsigned type, unsupported compiler" +#endif + +#if (SHRT_MAX == 32767) + typedef short cmsInt16Number; +#elif (INT_MAX == 32767) + typedef int cmsInt16Number; +#else +# error "Unable to find 16 bits signed type, unsupported compiler" +#endif + +// 32-bit base type +#if (UINT_MAX == 4294967295U) + typedef unsigned int cmsUInt32Number; +#elif (ULONG_MAX == 4294967295U) + typedef unsigned long cmsUInt32Number; +#else +# error "Unable to find 32 bit unsigned type, unsupported compiler" +#endif + +#if (INT_MAX == +2147483647) + typedef int cmsInt32Number; +#elif (LONG_MAX == +2147483647) + typedef long cmsInt32Number; +#else +# error "Unable to find 32 bit signed type, unsupported compiler" +#endif + +// 64-bit base types +#ifndef CMS_DONT_USE_INT64 +# if (ULONG_MAX == 18446744073709551615U) + typedef unsigned long cmsUInt64Number; +# elif (ULLONG_MAX == 18446744073709551615U) + typedef unsigned long long cmsUInt64Number; +# else +# define CMS_DONT_USE_INT64 1 +# endif +# if (LONG_MAX == +9223372036854775807) + typedef long cmsInt64Number; +# elif (LLONG_MAX == +9223372036854775807) + typedef long long cmsInt64Number; +# else +# define CMS_DONT_USE_INT64 1 +# endif +#endif +#endif + +// In the case 64 bit numbers are not supported by the compiler +#ifdef CMS_DONT_USE_INT64 + typedef cmsUInt32Number cmsUInt64Number[2]; + typedef cmsInt32Number cmsInt64Number[2]; +#endif + +// Derivative types +typedef cmsUInt32Number cmsSignature; +typedef cmsUInt16Number cmsU8Fixed8Number; +typedef cmsInt32Number cmsS15Fixed16Number; +typedef cmsUInt32Number cmsU16Fixed16Number; + +// Boolean type, which will be using the native integer +typedef int cmsBool; + +// Try to detect windows +#if defined (_WIN32) || defined(_WIN64) || defined(WIN32) || defined(_WIN32_) +# define CMS_IS_WINDOWS_ 1 +#endif + +#ifdef _MSC_VER +# define CMS_IS_WINDOWS_ 1 +#endif + +#ifdef __BORLANDC__ +# define CMS_IS_WINDOWS_ 1 +#endif + +// Try to detect big endian platforms. This list can be endless, so only some checks are performed over here. +// you can pass this toggle to the compiler by using -DCMS_USE_BIG_ENDIAN or something similar + +#if defined(_HOST_BIG_ENDIAN) || defined(__BIG_ENDIAN__) || defined(WORDS_BIGENDIAN) +# define CMS_USE_BIG_ENDIAN 1 +#endif + +#if defined(__sgi__) || defined(__sgi) || defined(__powerpc__) || defined(sparc) +# define CMS_USE_BIG_ENDIAN 1 +#endif + +#if defined(__ppc__) || defined(__s390__) || defined(__s390x__) +# define CMS_USE_BIG_ENDIAN 1 +#endif + +#ifdef TARGET_CPU_PPC +# if TARGET_CPU_PPC +# define CMS_USE_BIG_ENDIAN 1 +# endif +#endif + +#ifdef macintosh +# ifdef __BIG_ENDIAN__ +# define CMS_USE_BIG_ENDIAN 1 +# endif +#endif + +// Calling convention -- this is hardly platform and compiler dependent +#ifdef CMS_IS_WINDOWS_ +# if defined(CMS_DLL) || defined(CMS_DLL_BUILD) +# ifdef __BORLANDC__ +# define CMSEXPORT __stdcall _export +# define CMSAPI +# else +# define CMSEXPORT _stdcall +# ifdef CMS_DLL_BUILD +# define CMSAPI __declspec(dllexport) +# else +# define CMSAPI __declspec(dllimport) +# endif +# endif +# else +# define CMSEXPORT +# define CMSAPI +# endif +#else +# define CMSEXPORT +# define CMSAPI +#endif + +// Some common definitions +#define cmsMAX_PATH 256 + +#ifndef FALSE +# define FALSE 0 +#endif +#ifndef TRUE +# define TRUE 1 +#endif + +// D50 XYZ normalized to Y=1.0 +#define cmsD50X 0.9642 +#define cmsD50Y 1.0 +#define cmsD50Z 0.8249 + +// V4 perceptual black +#define cmsPERCEPTUAL_BLACK_X 0.00336 +#define cmsPERCEPTUAL_BLACK_Y 0.0034731 +#define cmsPERCEPTUAL_BLACK_Z 0.00287 + +// Definitions in ICC spec +#define cmsMagicNumber 0x61637370 // 'acsp' +#define lcmsSignature 0x6c636d73 // 'lcms' + + +// Base ICC type definitions +typedef enum { + cmsSigChromaticityType = 0x6368726D, // 'chrm' + cmsSigColorantOrderType = 0x636C726F, // 'clro' + cmsSigColorantTableType = 0x636C7274, // 'clrt' + cmsSigCrdInfoType = 0x63726469, // 'crdi' + cmsSigCurveType = 0x63757276, // 'curv' + cmsSigDataType = 0x64617461, // 'data' + cmsSigDictType = 0x64696374, // 'dict' + cmsSigDateTimeType = 0x6474696D, // 'dtim' + cmsSigDeviceSettingsType = 0x64657673, // 'devs' + cmsSigLut16Type = 0x6d667432, // 'mft2' + cmsSigLut8Type = 0x6d667431, // 'mft1' + cmsSigLutAtoBType = 0x6d414220, // 'mAB ' + cmsSigLutBtoAType = 0x6d424120, // 'mBA ' + cmsSigMeasurementType = 0x6D656173, // 'meas' + cmsSigMultiLocalizedUnicodeType = 0x6D6C7563, // 'mluc' + cmsSigMultiProcessElementType = 0x6D706574, // 'mpet' + cmsSigNamedColorType = 0x6E636f6C, // 'ncol' -- DEPRECATED! + cmsSigNamedColor2Type = 0x6E636C32, // 'ncl2' + cmsSigParametricCurveType = 0x70617261, // 'para' + cmsSigProfileSequenceDescType = 0x70736571, // 'pseq' + cmsSigProfileSequenceIdType = 0x70736964, // 'psid' + cmsSigResponseCurveSet16Type = 0x72637332, // 'rcs2' + cmsSigS15Fixed16ArrayType = 0x73663332, // 'sf32' + cmsSigScreeningType = 0x7363726E, // 'scrn' + cmsSigSignatureType = 0x73696720, // 'sig ' + cmsSigTextType = 0x74657874, // 'text' + cmsSigTextDescriptionType = 0x64657363, // 'desc' + cmsSigU16Fixed16ArrayType = 0x75663332, // 'uf32' + cmsSigUcrBgType = 0x62666420, // 'bfd ' + cmsSigUInt16ArrayType = 0x75693136, // 'ui16' + cmsSigUInt32ArrayType = 0x75693332, // 'ui32' + cmsSigUInt64ArrayType = 0x75693634, // 'ui64' + cmsSigUInt8ArrayType = 0x75693038, // 'ui08' + cmsSigVcgtType = 0x76636774, // 'vcgt' + cmsSigViewingConditionsType = 0x76696577, // 'view' + cmsSigXYZType = 0x58595A20 // 'XYZ ' + + +} cmsTagTypeSignature; + +// Base ICC tag definitions +typedef enum { + cmsSigAToB0Tag = 0x41324230, // 'A2B0' + cmsSigAToB1Tag = 0x41324231, // 'A2B1' + cmsSigAToB2Tag = 0x41324232, // 'A2B2' + cmsSigBlueColorantTag = 0x6258595A, // 'bXYZ' + cmsSigBlueMatrixColumnTag = 0x6258595A, // 'bXYZ' + cmsSigBlueTRCTag = 0x62545243, // 'bTRC' + cmsSigBToA0Tag = 0x42324130, // 'B2A0' + cmsSigBToA1Tag = 0x42324131, // 'B2A1' + cmsSigBToA2Tag = 0x42324132, // 'B2A2' + cmsSigCalibrationDateTimeTag = 0x63616C74, // 'calt' + cmsSigCharTargetTag = 0x74617267, // 'targ' + cmsSigChromaticAdaptationTag = 0x63686164, // 'chad' + cmsSigChromaticityTag = 0x6368726D, // 'chrm' + cmsSigColorantOrderTag = 0x636C726F, // 'clro' + cmsSigColorantTableTag = 0x636C7274, // 'clrt' + cmsSigColorantTableOutTag = 0x636C6F74, // 'clot' + cmsSigColorimetricIntentImageStateTag = 0x63696973, // 'ciis' + cmsSigCopyrightTag = 0x63707274, // 'cprt' + cmsSigCrdInfoTag = 0x63726469, // 'crdi' + cmsSigDataTag = 0x64617461, // 'data' + cmsSigDateTimeTag = 0x6474696D, // 'dtim' + cmsSigDeviceMfgDescTag = 0x646D6E64, // 'dmnd' + cmsSigDeviceModelDescTag = 0x646D6464, // 'dmdd' + cmsSigDeviceSettingsTag = 0x64657673, // 'devs' + cmsSigDToB0Tag = 0x44324230, // 'D2B0' + cmsSigDToB1Tag = 0x44324231, // 'D2B1' + cmsSigDToB2Tag = 0x44324232, // 'D2B2' + cmsSigDToB3Tag = 0x44324233, // 'D2B3' + cmsSigBToD0Tag = 0x42324430, // 'B2D0' + cmsSigBToD1Tag = 0x42324431, // 'B2D1' + cmsSigBToD2Tag = 0x42324432, // 'B2D2' + cmsSigBToD3Tag = 0x42324433, // 'B2D3' + cmsSigGamutTag = 0x67616D74, // 'gamt' + cmsSigGrayTRCTag = 0x6b545243, // 'kTRC' + cmsSigGreenColorantTag = 0x6758595A, // 'gXYZ' + cmsSigGreenMatrixColumnTag = 0x6758595A, // 'gXYZ' + cmsSigGreenTRCTag = 0x67545243, // 'gTRC' + cmsSigLuminanceTag = 0x6C756d69, // 'lumi' + cmsSigMeasurementTag = 0x6D656173, // 'meas' + cmsSigMediaBlackPointTag = 0x626B7074, // 'bkpt' + cmsSigMediaWhitePointTag = 0x77747074, // 'wtpt' + cmsSigNamedColorTag = 0x6E636f6C, // 'ncol' // Deprecated by the ICC + cmsSigNamedColor2Tag = 0x6E636C32, // 'ncl2' + cmsSigOutputResponseTag = 0x72657370, // 'resp' + cmsSigPerceptualRenderingIntentGamutTag = 0x72696730, // 'rig0' + cmsSigPreview0Tag = 0x70726530, // 'pre0' + cmsSigPreview1Tag = 0x70726531, // 'pre1' + cmsSigPreview2Tag = 0x70726532, // 'pre2' + cmsSigProfileDescriptionTag = 0x64657363, // 'desc' + cmsSigProfileDescriptionMLTag = 0x6473636d, // 'dscm' + cmsSigProfileSequenceDescTag = 0x70736571, // 'pseq' + cmsSigProfileSequenceIdTag = 0x70736964, // 'psid' + cmsSigPs2CRD0Tag = 0x70736430, // 'psd0' + cmsSigPs2CRD1Tag = 0x70736431, // 'psd1' + cmsSigPs2CRD2Tag = 0x70736432, // 'psd2' + cmsSigPs2CRD3Tag = 0x70736433, // 'psd3' + cmsSigPs2CSATag = 0x70733273, // 'ps2s' + cmsSigPs2RenderingIntentTag = 0x70733269, // 'ps2i' + cmsSigRedColorantTag = 0x7258595A, // 'rXYZ' + cmsSigRedMatrixColumnTag = 0x7258595A, // 'rXYZ' + cmsSigRedTRCTag = 0x72545243, // 'rTRC' + cmsSigSaturationRenderingIntentGamutTag = 0x72696732, // 'rig2' + cmsSigScreeningDescTag = 0x73637264, // 'scrd' + cmsSigScreeningTag = 0x7363726E, // 'scrn' + cmsSigTechnologyTag = 0x74656368, // 'tech' + cmsSigUcrBgTag = 0x62666420, // 'bfd ' + cmsSigViewingCondDescTag = 0x76756564, // 'vued' + cmsSigViewingConditionsTag = 0x76696577, // 'view' + cmsSigVcgtTag = 0x76636774, // 'vcgt' + cmsSigMetaTag = 0x6D657461 // 'meta' + +} cmsTagSignature; + + +// ICC Technology tag +typedef enum { + cmsSigDigitalCamera = 0x6463616D, // 'dcam' + cmsSigFilmScanner = 0x6673636E, // 'fscn' + cmsSigReflectiveScanner = 0x7273636E, // 'rscn' + cmsSigInkJetPrinter = 0x696A6574, // 'ijet' + cmsSigThermalWaxPrinter = 0x74776178, // 'twax' + cmsSigElectrophotographicPrinter = 0x6570686F, // 'epho' + cmsSigElectrostaticPrinter = 0x65737461, // 'esta' + cmsSigDyeSublimationPrinter = 0x64737562, // 'dsub' + cmsSigPhotographicPaperPrinter = 0x7270686F, // 'rpho' + cmsSigFilmWriter = 0x6670726E, // 'fprn' + cmsSigVideoMonitor = 0x7669646D, // 'vidm' + cmsSigVideoCamera = 0x76696463, // 'vidc' + cmsSigProjectionTelevision = 0x706A7476, // 'pjtv' + cmsSigCRTDisplay = 0x43525420, // 'CRT ' + cmsSigPMDisplay = 0x504D4420, // 'PMD ' + cmsSigAMDisplay = 0x414D4420, // 'AMD ' + cmsSigPhotoCD = 0x4B504344, // 'KPCD' + cmsSigPhotoImageSetter = 0x696D6773, // 'imgs' + cmsSigGravure = 0x67726176, // 'grav' + cmsSigOffsetLithography = 0x6F666673, // 'offs' + cmsSigSilkscreen = 0x73696C6B, // 'silk' + cmsSigFlexography = 0x666C6578, // 'flex' + cmsSigMotionPictureFilmScanner = 0x6D706673, // 'mpfs' + cmsSigMotionPictureFilmRecorder = 0x6D706672, // 'mpfr' + cmsSigDigitalMotionPictureCamera = 0x646D7063, // 'dmpc' + cmsSigDigitalCinemaProjector = 0x64636A70 // 'dcpj' + +} cmsTechnologySignature; + + +// ICC Color spaces +typedef enum { + cmsSigXYZData = 0x58595A20, // 'XYZ ' + cmsSigLabData = 0x4C616220, // 'Lab ' + cmsSigLuvData = 0x4C757620, // 'Luv ' + cmsSigYCbCrData = 0x59436272, // 'YCbr' + cmsSigYxyData = 0x59787920, // 'Yxy ' + cmsSigRgbData = 0x52474220, // 'RGB ' + cmsSigGrayData = 0x47524159, // 'GRAY' + cmsSigHsvData = 0x48535620, // 'HSV ' + cmsSigHlsData = 0x484C5320, // 'HLS ' + cmsSigCmykData = 0x434D594B, // 'CMYK' + cmsSigCmyData = 0x434D5920, // 'CMY ' + cmsSigMCH1Data = 0x4D434831, // 'MCH1' + cmsSigMCH2Data = 0x4D434832, // 'MCH2' + cmsSigMCH3Data = 0x4D434833, // 'MCH3' + cmsSigMCH4Data = 0x4D434834, // 'MCH4' + cmsSigMCH5Data = 0x4D434835, // 'MCH5' + cmsSigMCH6Data = 0x4D434836, // 'MCH6' + cmsSigMCH7Data = 0x4D434837, // 'MCH7' + cmsSigMCH8Data = 0x4D434838, // 'MCH8' + cmsSigMCH9Data = 0x4D434839, // 'MCH9' + cmsSigMCHAData = 0x4D434841, // 'MCHA' + cmsSigMCHBData = 0x4D434842, // 'MCHB' + cmsSigMCHCData = 0x4D434843, // 'MCHC' + cmsSigMCHDData = 0x4D434844, // 'MCHD' + cmsSigMCHEData = 0x4D434845, // 'MCHE' + cmsSigMCHFData = 0x4D434846, // 'MCHF' + cmsSigNamedData = 0x6e6d636c, // 'nmcl' + cmsSig1colorData = 0x31434C52, // '1CLR' + cmsSig2colorData = 0x32434C52, // '2CLR' + cmsSig3colorData = 0x33434C52, // '3CLR' + cmsSig4colorData = 0x34434C52, // '4CLR' + cmsSig5colorData = 0x35434C52, // '5CLR' + cmsSig6colorData = 0x36434C52, // '6CLR' + cmsSig7colorData = 0x37434C52, // '7CLR' + cmsSig8colorData = 0x38434C52, // '8CLR' + cmsSig9colorData = 0x39434C52, // '9CLR' + cmsSig10colorData = 0x41434C52, // 'ACLR' + cmsSig11colorData = 0x42434C52, // 'BCLR' + cmsSig12colorData = 0x43434C52, // 'CCLR' + cmsSig13colorData = 0x44434C52, // 'DCLR' + cmsSig14colorData = 0x45434C52, // 'ECLR' + cmsSig15colorData = 0x46434C52, // 'FCLR' + cmsSigLuvKData = 0x4C75764B // 'LuvK' + +} cmsColorSpaceSignature; + +// ICC Profile Class +typedef enum { + cmsSigInputClass = 0x73636E72, // 'scnr' + cmsSigDisplayClass = 0x6D6E7472, // 'mntr' + cmsSigOutputClass = 0x70727472, // 'prtr' + cmsSigLinkClass = 0x6C696E6B, // 'link' + cmsSigAbstractClass = 0x61627374, // 'abst' + cmsSigColorSpaceClass = 0x73706163, // 'spac' + cmsSigNamedColorClass = 0x6e6d636c // 'nmcl' + +} cmsProfileClassSignature; + +// ICC Platforms +typedef enum { + cmsSigMacintosh = 0x4150504C, // 'APPL' + cmsSigMicrosoft = 0x4D534654, // 'MSFT' + cmsSigSolaris = 0x53554E57, // 'SUNW' + cmsSigSGI = 0x53474920, // 'SGI ' + cmsSigTaligent = 0x54474E54, // 'TGNT' + cmsSigUnices = 0x2A6E6978 // '*nix' // From argyll -- Not official + +} cmsPlatformSignature; + +// Reference gamut +#define cmsSigPerceptualReferenceMediumGamut 0x70726d67 //'prmg' + +// For cmsSigColorimetricIntentImageStateTag +#define cmsSigSceneColorimetryEstimates 0x73636F65 //'scoe' +#define cmsSigSceneAppearanceEstimates 0x73617065 //'sape' +#define cmsSigFocalPlaneColorimetryEstimates 0x66706365 //'fpce' +#define cmsSigReflectionHardcopyOriginalColorimetry 0x72686F63 //'rhoc' +#define cmsSigReflectionPrintOutputColorimetry 0x72706F63 //'rpoc' + +// Multi process elements types +typedef enum { + cmsSigCurveSetElemType = 0x63767374, //'cvst' + cmsSigMatrixElemType = 0x6D617466, //'matf' + cmsSigCLutElemType = 0x636C7574, //'clut' + + cmsSigBAcsElemType = 0x62414353, // 'bACS' + cmsSigEAcsElemType = 0x65414353, // 'eACS' + + // Custom from here, not in the ICC Spec + cmsSigXYZ2LabElemType = 0x6C327820, // 'l2x ' + cmsSigLab2XYZElemType = 0x78326C20, // 'x2l ' + cmsSigNamedColorElemType = 0x6E636C20, // 'ncl ' + cmsSigLabV2toV4 = 0x32203420, // '2 4 ' + cmsSigLabV4toV2 = 0x34203220, // '4 2 ' + + // Identities + cmsSigIdentityElemType = 0x69646E20, // 'idn ' + + // Float to floatPCS + cmsSigLab2FloatPCS = 0x64326C20, // 'd2l ' + cmsSigFloatPCS2Lab = 0x6C326420, // 'l2d ' + cmsSigXYZ2FloatPCS = 0x64327820, // 'd2x ' + cmsSigFloatPCS2XYZ = 0x78326420 // 'x2d ' + +} cmsStageSignature; + +// Types of CurveElements +typedef enum { + + cmsSigFormulaCurveSeg = 0x70617266, // 'parf' + cmsSigSampledCurveSeg = 0x73616D66, // 'samf' + cmsSigSegmentedCurve = 0x63757266 // 'curf' + +} cmsCurveSegSignature; + +// Used in ResponseCurveType +#define cmsSigStatusA 0x53746141 //'StaA' +#define cmsSigStatusE 0x53746145 //'StaE' +#define cmsSigStatusI 0x53746149 //'StaI' +#define cmsSigStatusT 0x53746154 //'StaT' +#define cmsSigStatusM 0x5374614D //'StaM' +#define cmsSigDN 0x444E2020 //'DN ' +#define cmsSigDNP 0x444E2050 //'DN P' +#define cmsSigDNN 0x444E4E20 //'DNN ' +#define cmsSigDNNP 0x444E4E50 //'DNNP' + +// Device attributes, currently defined values correspond to the low 4 bytes +// of the 8 byte attribute quantity +#define cmsReflective 0 +#define cmsTransparency 1 +#define cmsGlossy 0 +#define cmsMatte 2 + +// Common structures in ICC tags +typedef struct { + cmsUInt32Number len; + cmsUInt32Number flag; + cmsUInt8Number data[1]; + +} cmsICCData; + +// ICC date time +typedef struct { + cmsUInt16Number year; + cmsUInt16Number month; + cmsUInt16Number day; + cmsUInt16Number hours; + cmsUInt16Number minutes; + cmsUInt16Number seconds; + +} cmsDateTimeNumber; + +// ICC XYZ +typedef struct { + cmsS15Fixed16Number X; + cmsS15Fixed16Number Y; + cmsS15Fixed16Number Z; + +} cmsEncodedXYZNumber; + + +// Profile ID as computed by MD5 algorithm +typedef union { + cmsUInt8Number ID8[16]; + cmsUInt16Number ID16[8]; + cmsUInt32Number ID32[4]; + +} cmsProfileID; + + +// ---------------------------------------------------------------------------------------------- +// ICC profile internal base types. Strictly, shouldn't be declared in this header, but maybe +// somebody want to use this info for accessing profile header directly, so here it is. + +// Profile header -- it is 32-bit aligned, so no issues are expected on alignment +typedef struct { + cmsUInt32Number size; // Profile size in bytes + cmsSignature cmmId; // CMM for this profile + cmsUInt32Number version; // Format version number + cmsProfileClassSignature deviceClass; // Type of profile + cmsColorSpaceSignature colorSpace; // Color space of data + cmsColorSpaceSignature pcs; // PCS, XYZ or Lab only + cmsDateTimeNumber date; // Date profile was created + cmsSignature magic; // Magic Number to identify an ICC profile + cmsPlatformSignature platform; // Primary Platform + cmsUInt32Number flags; // Various bit settings + cmsSignature manufacturer; // Device manufacturer + cmsUInt32Number model; // Device model number + cmsUInt64Number attributes; // Device attributes + cmsUInt32Number renderingIntent;// Rendering intent + cmsEncodedXYZNumber illuminant; // Profile illuminant + cmsSignature creator; // Profile creator + cmsProfileID profileID; // Profile ID using MD5 + cmsInt8Number reserved[28]; // Reserved for future use + +} cmsICCHeader; + +// ICC base tag +typedef struct { + cmsTagTypeSignature sig; + cmsInt8Number reserved[4]; + +} cmsTagBase; + +// A tag entry in directory +typedef struct { + cmsTagSignature sig; // The tag signature + cmsUInt32Number offset; // Start of tag + cmsUInt32Number size; // Size in bytes + +} cmsTagEntry; + +// ---------------------------------------------------------------------------------------------- + +// Little CMS specific typedefs + +typedef void* cmsContext; // Context identifier for multithreaded environments +typedef void* cmsHANDLE ; // Generic handle +typedef void* cmsHPROFILE; // Opaque typedefs to hide internals +typedef void* cmsHTRANSFORM; + +#define cmsMAXCHANNELS 16 // Maximum number of channels in ICC profiles + +// Format of pixel is defined by one cmsUInt32Number, using bit fields as follows +// +// 2 1 0 +// 3 2 10987 6 5 4 3 2 1 098 7654 321 +// A O TTTTT U Y F P X S EEE CCCC BBB +// +// A: Floating point -- With this flag we can differentiate 16 bits as float and as int +// O: Optimized -- previous optimization already returns the final 8-bit value +// T: Pixeltype +// F: Flavor 0=MinIsBlack(Chocolate) 1=MinIsWhite(Vanilla) +// P: Planar? 0=Chunky, 1=Planar +// X: swap 16 bps endianess? +// S: Do swap? ie, BGR, KYMC +// E: Extra samples +// C: Channels (Samples per pixel) +// B: bytes per sample +// Y: Swap first - changes ABGR to BGRA and KCMY to CMYK + +#define FLOAT_SH(a) ((a) << 22) +#define OPTIMIZED_SH(s) ((s) << 21) +#define COLORSPACE_SH(s) ((s) << 16) +#define SWAPFIRST_SH(s) ((s) << 14) +#define FLAVOR_SH(s) ((s) << 13) +#define PLANAR_SH(p) ((p) << 12) +#define ENDIAN16_SH(e) ((e) << 11) +#define DOSWAP_SH(e) ((e) << 10) +#define EXTRA_SH(e) ((e) << 7) +#define CHANNELS_SH(c) ((c) << 3) +#define BYTES_SH(b) (b) + +// These macros unpack format specifiers into integers +#define T_FLOAT(a) (((a)>>22)&1) +#define T_OPTIMIZED(o) (((o)>>21)&1) +#define T_COLORSPACE(s) (((s)>>16)&31) +#define T_SWAPFIRST(s) (((s)>>14)&1) +#define T_FLAVOR(s) (((s)>>13)&1) +#define T_PLANAR(p) (((p)>>12)&1) +#define T_ENDIAN16(e) (((e)>>11)&1) +#define T_DOSWAP(e) (((e)>>10)&1) +#define T_EXTRA(e) (((e)>>7)&7) +#define T_CHANNELS(c) (((c)>>3)&15) +#define T_BYTES(b) ((b)&7) + + +// Pixel types +#define PT_ANY 0 // Don't check colorspace + // 1 & 2 are reserved +#define PT_GRAY 3 +#define PT_RGB 4 +#define PT_CMY 5 +#define PT_CMYK 6 +#define PT_YCbCr 7 +#define PT_YUV 8 // Lu'v' +#define PT_XYZ 9 +#define PT_Lab 10 +#define PT_YUVK 11 // Lu'v'K +#define PT_HSV 12 +#define PT_HLS 13 +#define PT_Yxy 14 + +#define PT_MCH1 15 +#define PT_MCH2 16 +#define PT_MCH3 17 +#define PT_MCH4 18 +#define PT_MCH5 19 +#define PT_MCH6 20 +#define PT_MCH7 21 +#define PT_MCH8 22 +#define PT_MCH9 23 +#define PT_MCH10 24 +#define PT_MCH11 25 +#define PT_MCH12 26 +#define PT_MCH13 27 +#define PT_MCH14 28 +#define PT_MCH15 29 + +#define PT_LabV2 30 // Identical to PT_Lab, but using the V2 old encoding + +// Some (not all!) representations + +#ifndef TYPE_RGB_8 // TYPE_RGB_8 is a very common identifier, so don't include ours + // if user has it already defined. + +#define TYPE_GRAY_8 (COLORSPACE_SH(PT_GRAY)|CHANNELS_SH(1)|BYTES_SH(1)) +#define TYPE_GRAY_8_REV (COLORSPACE_SH(PT_GRAY)|CHANNELS_SH(1)|BYTES_SH(1)|FLAVOR_SH(1)) +#define TYPE_GRAY_16 (COLORSPACE_SH(PT_GRAY)|CHANNELS_SH(1)|BYTES_SH(2)) +#define TYPE_GRAY_16_REV (COLORSPACE_SH(PT_GRAY)|CHANNELS_SH(1)|BYTES_SH(2)|FLAVOR_SH(1)) +#define TYPE_GRAY_16_SE (COLORSPACE_SH(PT_GRAY)|CHANNELS_SH(1)|BYTES_SH(2)|ENDIAN16_SH(1)) +#define TYPE_GRAYA_8 (COLORSPACE_SH(PT_GRAY)|EXTRA_SH(1)|CHANNELS_SH(1)|BYTES_SH(1)) +#define TYPE_GRAYA_16 (COLORSPACE_SH(PT_GRAY)|EXTRA_SH(1)|CHANNELS_SH(1)|BYTES_SH(2)) +#define TYPE_GRAYA_16_SE (COLORSPACE_SH(PT_GRAY)|EXTRA_SH(1)|CHANNELS_SH(1)|BYTES_SH(2)|ENDIAN16_SH(1)) +#define TYPE_GRAYA_8_PLANAR (COLORSPACE_SH(PT_GRAY)|EXTRA_SH(1)|CHANNELS_SH(1)|BYTES_SH(1)|PLANAR_SH(1)) +#define TYPE_GRAYA_16_PLANAR (COLORSPACE_SH(PT_GRAY)|EXTRA_SH(1)|CHANNELS_SH(1)|BYTES_SH(2)|PLANAR_SH(1)) + +#define TYPE_RGB_8 (COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(1)) +#define TYPE_RGB_8_PLANAR (COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(1)|PLANAR_SH(1)) +#define TYPE_BGR_8 (COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1)) +#define TYPE_BGR_8_PLANAR (COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1)|PLANAR_SH(1)) +#define TYPE_RGB_16 (COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(2)) +#define TYPE_RGB_16_PLANAR (COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(2)|PLANAR_SH(1)) +#define TYPE_RGB_16_SE (COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(2)|ENDIAN16_SH(1)) +#define TYPE_BGR_16 (COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1)) +#define TYPE_BGR_16_PLANAR (COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1)|PLANAR_SH(1)) +#define TYPE_BGR_16_SE (COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1)|ENDIAN16_SH(1)) + +#define TYPE_RGBA_8 (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(1)) +#define TYPE_RGBA_8_PLANAR (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(1)|PLANAR_SH(1)) +#define TYPE_RGBA_16 (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)) +#define TYPE_RGBA_16_PLANAR (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)|PLANAR_SH(1)) +#define TYPE_RGBA_16_SE (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)|ENDIAN16_SH(1)) + +#define TYPE_ARGB_8 (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(1)|SWAPFIRST_SH(1)) +#define TYPE_ARGB_8_PLANAR (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(1)|SWAPFIRST_SH(1)|PLANAR_SH(1)) +#define TYPE_ARGB_16 (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)|SWAPFIRST_SH(1)) + +#define TYPE_ABGR_8 (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1)) +#define TYPE_ABGR_8_PLANAR (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1)|PLANAR_SH(1)) +#define TYPE_ABGR_16 (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1)) +#define TYPE_ABGR_16_PLANAR (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1)|PLANAR_SH(1)) +#define TYPE_ABGR_16_SE (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1)|ENDIAN16_SH(1)) + +#define TYPE_BGRA_8 (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1)) +#define TYPE_BGRA_8_PLANAR (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1)|PLANAR_SH(1)) +#define TYPE_BGRA_16 (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1)|SWAPFIRST_SH(1)) +#define TYPE_BGRA_16_SE (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)|ENDIAN16_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1)) + +#define TYPE_CMY_8 (COLORSPACE_SH(PT_CMY)|CHANNELS_SH(3)|BYTES_SH(1)) +#define TYPE_CMY_8_PLANAR (COLORSPACE_SH(PT_CMY)|CHANNELS_SH(3)|BYTES_SH(1)|PLANAR_SH(1)) +#define TYPE_CMY_16 (COLORSPACE_SH(PT_CMY)|CHANNELS_SH(3)|BYTES_SH(2)) +#define TYPE_CMY_16_PLANAR (COLORSPACE_SH(PT_CMY)|CHANNELS_SH(3)|BYTES_SH(2)|PLANAR_SH(1)) +#define TYPE_CMY_16_SE (COLORSPACE_SH(PT_CMY)|CHANNELS_SH(3)|BYTES_SH(2)|ENDIAN16_SH(1)) + +#define TYPE_CMYK_8 (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(1)) +#define TYPE_CMYKA_8 (COLORSPACE_SH(PT_CMYK)|EXTRA_SH(1)|CHANNELS_SH(4)|BYTES_SH(1)) +#define TYPE_CMYK_8_REV (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(1)|FLAVOR_SH(1)) +#define TYPE_YUVK_8 TYPE_CMYK_8_REV +#define TYPE_CMYK_8_PLANAR (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(1)|PLANAR_SH(1)) +#define TYPE_CMYK_16 (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(2)) +#define TYPE_CMYK_16_REV (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(2)|FLAVOR_SH(1)) +#define TYPE_YUVK_16 TYPE_CMYK_16_REV +#define TYPE_CMYK_16_PLANAR (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(2)|PLANAR_SH(1)) +#define TYPE_CMYK_16_SE (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(2)|ENDIAN16_SH(1)) + +#define TYPE_KYMC_8 (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(1)|DOSWAP_SH(1)) +#define TYPE_KYMC_16 (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(2)|DOSWAP_SH(1)) +#define TYPE_KYMC_16_SE (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(2)|DOSWAP_SH(1)|ENDIAN16_SH(1)) + +#define TYPE_KCMY_8 (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(1)|SWAPFIRST_SH(1)) +#define TYPE_KCMY_8_REV (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(1)|FLAVOR_SH(1)|SWAPFIRST_SH(1)) +#define TYPE_KCMY_16 (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(2)|SWAPFIRST_SH(1)) +#define TYPE_KCMY_16_REV (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(2)|FLAVOR_SH(1)|SWAPFIRST_SH(1)) +#define TYPE_KCMY_16_SE (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(2)|ENDIAN16_SH(1)|SWAPFIRST_SH(1)) + +#define TYPE_CMYK5_8 (COLORSPACE_SH(PT_MCH5)|CHANNELS_SH(5)|BYTES_SH(1)) +#define TYPE_CMYK5_16 (COLORSPACE_SH(PT_MCH5)|CHANNELS_SH(5)|BYTES_SH(2)) +#define TYPE_CMYK5_16_SE (COLORSPACE_SH(PT_MCH5)|CHANNELS_SH(5)|BYTES_SH(2)|ENDIAN16_SH(1)) +#define TYPE_KYMC5_8 (COLORSPACE_SH(PT_MCH5)|CHANNELS_SH(5)|BYTES_SH(1)|DOSWAP_SH(1)) +#define TYPE_KYMC5_16 (COLORSPACE_SH(PT_MCH5)|CHANNELS_SH(5)|BYTES_SH(2)|DOSWAP_SH(1)) +#define TYPE_KYMC5_16_SE (COLORSPACE_SH(PT_MCH5)|CHANNELS_SH(5)|BYTES_SH(2)|DOSWAP_SH(1)|ENDIAN16_SH(1)) +#define TYPE_CMYK6_8 (COLORSPACE_SH(PT_MCH6)|CHANNELS_SH(6)|BYTES_SH(1)) +#define TYPE_CMYK6_8_PLANAR (COLORSPACE_SH(PT_MCH6)|CHANNELS_SH(6)|BYTES_SH(1)|PLANAR_SH(1)) +#define TYPE_CMYK6_16 (COLORSPACE_SH(PT_MCH6)|CHANNELS_SH(6)|BYTES_SH(2)) +#define TYPE_CMYK6_16_PLANAR (COLORSPACE_SH(PT_MCH6)|CHANNELS_SH(6)|BYTES_SH(2)|PLANAR_SH(1)) +#define TYPE_CMYK6_16_SE (COLORSPACE_SH(PT_MCH6)|CHANNELS_SH(6)|BYTES_SH(2)|ENDIAN16_SH(1)) +#define TYPE_CMYK7_8 (COLORSPACE_SH(PT_MCH7)|CHANNELS_SH(7)|BYTES_SH(1)) +#define TYPE_CMYK7_16 (COLORSPACE_SH(PT_MCH7)|CHANNELS_SH(7)|BYTES_SH(2)) +#define TYPE_CMYK7_16_SE (COLORSPACE_SH(PT_MCH7)|CHANNELS_SH(7)|BYTES_SH(2)|ENDIAN16_SH(1)) +#define TYPE_KYMC7_8 (COLORSPACE_SH(PT_MCH7)|CHANNELS_SH(7)|BYTES_SH(1)|DOSWAP_SH(1)) +#define TYPE_KYMC7_16 (COLORSPACE_SH(PT_MCH7)|CHANNELS_SH(7)|BYTES_SH(2)|DOSWAP_SH(1)) +#define TYPE_KYMC7_16_SE (COLORSPACE_SH(PT_MCH7)|CHANNELS_SH(7)|BYTES_SH(2)|DOSWAP_SH(1)|ENDIAN16_SH(1)) +#define TYPE_CMYK8_8 (COLORSPACE_SH(PT_MCH8)|CHANNELS_SH(8)|BYTES_SH(1)) +#define TYPE_CMYK8_16 (COLORSPACE_SH(PT_MCH8)|CHANNELS_SH(8)|BYTES_SH(2)) +#define TYPE_CMYK8_16_SE (COLORSPACE_SH(PT_MCH8)|CHANNELS_SH(8)|BYTES_SH(2)|ENDIAN16_SH(1)) +#define TYPE_KYMC8_8 (COLORSPACE_SH(PT_MCH8)|CHANNELS_SH(8)|BYTES_SH(1)|DOSWAP_SH(1)) +#define TYPE_KYMC8_16 (COLORSPACE_SH(PT_MCH8)|CHANNELS_SH(8)|BYTES_SH(2)|DOSWAP_SH(1)) +#define TYPE_KYMC8_16_SE (COLORSPACE_SH(PT_MCH8)|CHANNELS_SH(8)|BYTES_SH(2)|DOSWAP_SH(1)|ENDIAN16_SH(1)) +#define TYPE_CMYK9_8 (COLORSPACE_SH(PT_MCH9)|CHANNELS_SH(9)|BYTES_SH(1)) +#define TYPE_CMYK9_16 (COLORSPACE_SH(PT_MCH9)|CHANNELS_SH(9)|BYTES_SH(2)) +#define TYPE_CMYK9_16_SE (COLORSPACE_SH(PT_MCH9)|CHANNELS_SH(9)|BYTES_SH(2)|ENDIAN16_SH(1)) +#define TYPE_KYMC9_8 (COLORSPACE_SH(PT_MCH9)|CHANNELS_SH(9)|BYTES_SH(1)|DOSWAP_SH(1)) +#define TYPE_KYMC9_16 (COLORSPACE_SH(PT_MCH9)|CHANNELS_SH(9)|BYTES_SH(2)|DOSWAP_SH(1)) +#define TYPE_KYMC9_16_SE (COLORSPACE_SH(PT_MCH9)|CHANNELS_SH(9)|BYTES_SH(2)|DOSWAP_SH(1)|ENDIAN16_SH(1)) +#define TYPE_CMYK10_8 (COLORSPACE_SH(PT_MCH10)|CHANNELS_SH(10)|BYTES_SH(1)) +#define TYPE_CMYK10_16 (COLORSPACE_SH(PT_MCH10)|CHANNELS_SH(10)|BYTES_SH(2)) +#define TYPE_CMYK10_16_SE (COLORSPACE_SH(PT_MCH10)|CHANNELS_SH(10)|BYTES_SH(2)|ENDIAN16_SH(1)) +#define TYPE_KYMC10_8 (COLORSPACE_SH(PT_MCH10)|CHANNELS_SH(10)|BYTES_SH(1)|DOSWAP_SH(1)) +#define TYPE_KYMC10_16 (COLORSPACE_SH(PT_MCH10)|CHANNELS_SH(10)|BYTES_SH(2)|DOSWAP_SH(1)) +#define TYPE_KYMC10_16_SE (COLORSPACE_SH(PT_MCH10)|CHANNELS_SH(10)|BYTES_SH(2)|DOSWAP_SH(1)|ENDIAN16_SH(1)) +#define TYPE_CMYK11_8 (COLORSPACE_SH(PT_MCH11)|CHANNELS_SH(11)|BYTES_SH(1)) +#define TYPE_CMYK11_16 (COLORSPACE_SH(PT_MCH11)|CHANNELS_SH(11)|BYTES_SH(2)) +#define TYPE_CMYK11_16_SE (COLORSPACE_SH(PT_MCH11)|CHANNELS_SH(11)|BYTES_SH(2)|ENDIAN16_SH(1)) +#define TYPE_KYMC11_8 (COLORSPACE_SH(PT_MCH11)|CHANNELS_SH(11)|BYTES_SH(1)|DOSWAP_SH(1)) +#define TYPE_KYMC11_16 (COLORSPACE_SH(PT_MCH11)|CHANNELS_SH(11)|BYTES_SH(2)|DOSWAP_SH(1)) +#define TYPE_KYMC11_16_SE (COLORSPACE_SH(PT_MCH11)|CHANNELS_SH(11)|BYTES_SH(2)|DOSWAP_SH(1)|ENDIAN16_SH(1)) +#define TYPE_CMYK12_8 (COLORSPACE_SH(PT_MCH12)|CHANNELS_SH(12)|BYTES_SH(1)) +#define TYPE_CMYK12_16 (COLORSPACE_SH(PT_MCH12)|CHANNELS_SH(12)|BYTES_SH(2)) +#define TYPE_CMYK12_16_SE (COLORSPACE_SH(PT_MCH12)|CHANNELS_SH(12)|BYTES_SH(2)|ENDIAN16_SH(1)) +#define TYPE_KYMC12_8 (COLORSPACE_SH(PT_MCH12)|CHANNELS_SH(12)|BYTES_SH(1)|DOSWAP_SH(1)) +#define TYPE_KYMC12_16 (COLORSPACE_SH(PT_MCH12)|CHANNELS_SH(12)|BYTES_SH(2)|DOSWAP_SH(1)) +#define TYPE_KYMC12_16_SE (COLORSPACE_SH(PT_MCH12)|CHANNELS_SH(12)|BYTES_SH(2)|DOSWAP_SH(1)|ENDIAN16_SH(1)) + +// Colorimetric +#define TYPE_XYZ_16 (COLORSPACE_SH(PT_XYZ)|CHANNELS_SH(3)|BYTES_SH(2)) +#define TYPE_Lab_8 (COLORSPACE_SH(PT_Lab)|CHANNELS_SH(3)|BYTES_SH(1)) +#define TYPE_LabV2_8 (COLORSPACE_SH(PT_LabV2)|CHANNELS_SH(3)|BYTES_SH(1)) + +#define TYPE_ALab_8 (COLORSPACE_SH(PT_Lab)|CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1)|SWAPFIRST_SH(1)) +#define TYPE_ALabV2_8 (COLORSPACE_SH(PT_LabV2)|CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1)|SWAPFIRST_SH(1)) +#define TYPE_Lab_16 (COLORSPACE_SH(PT_Lab)|CHANNELS_SH(3)|BYTES_SH(2)) +#define TYPE_LabV2_16 (COLORSPACE_SH(PT_LabV2)|CHANNELS_SH(3)|BYTES_SH(2)) +#define TYPE_Yxy_16 (COLORSPACE_SH(PT_Yxy)|CHANNELS_SH(3)|BYTES_SH(2)) + +// YCbCr +#define TYPE_YCbCr_8 (COLORSPACE_SH(PT_YCbCr)|CHANNELS_SH(3)|BYTES_SH(1)) +#define TYPE_YCbCr_8_PLANAR (COLORSPACE_SH(PT_YCbCr)|CHANNELS_SH(3)|BYTES_SH(1)|PLANAR_SH(1)) +#define TYPE_YCbCr_16 (COLORSPACE_SH(PT_YCbCr)|CHANNELS_SH(3)|BYTES_SH(2)) +#define TYPE_YCbCr_16_PLANAR (COLORSPACE_SH(PT_YCbCr)|CHANNELS_SH(3)|BYTES_SH(2)|PLANAR_SH(1)) +#define TYPE_YCbCr_16_SE (COLORSPACE_SH(PT_YCbCr)|CHANNELS_SH(3)|BYTES_SH(2)|ENDIAN16_SH(1)) + +// YUV +#define TYPE_YUV_8 (COLORSPACE_SH(PT_YUV)|CHANNELS_SH(3)|BYTES_SH(1)) +#define TYPE_YUV_8_PLANAR (COLORSPACE_SH(PT_YUV)|CHANNELS_SH(3)|BYTES_SH(1)|PLANAR_SH(1)) +#define TYPE_YUV_16 (COLORSPACE_SH(PT_YUV)|CHANNELS_SH(3)|BYTES_SH(2)) +#define TYPE_YUV_16_PLANAR (COLORSPACE_SH(PT_YUV)|CHANNELS_SH(3)|BYTES_SH(2)|PLANAR_SH(1)) +#define TYPE_YUV_16_SE (COLORSPACE_SH(PT_YUV)|CHANNELS_SH(3)|BYTES_SH(2)|ENDIAN16_SH(1)) + +// HLS +#define TYPE_HLS_8 (COLORSPACE_SH(PT_HLS)|CHANNELS_SH(3)|BYTES_SH(1)) +#define TYPE_HLS_8_PLANAR (COLORSPACE_SH(PT_HLS)|CHANNELS_SH(3)|BYTES_SH(1)|PLANAR_SH(1)) +#define TYPE_HLS_16 (COLORSPACE_SH(PT_HLS)|CHANNELS_SH(3)|BYTES_SH(2)) +#define TYPE_HLS_16_PLANAR (COLORSPACE_SH(PT_HLS)|CHANNELS_SH(3)|BYTES_SH(2)|PLANAR_SH(1)) +#define TYPE_HLS_16_SE (COLORSPACE_SH(PT_HLS)|CHANNELS_SH(3)|BYTES_SH(2)|ENDIAN16_SH(1)) + +// HSV +#define TYPE_HSV_8 (COLORSPACE_SH(PT_HSV)|CHANNELS_SH(3)|BYTES_SH(1)) +#define TYPE_HSV_8_PLANAR (COLORSPACE_SH(PT_HSV)|CHANNELS_SH(3)|BYTES_SH(1)|PLANAR_SH(1)) +#define TYPE_HSV_16 (COLORSPACE_SH(PT_HSV)|CHANNELS_SH(3)|BYTES_SH(2)) +#define TYPE_HSV_16_PLANAR (COLORSPACE_SH(PT_HSV)|CHANNELS_SH(3)|BYTES_SH(2)|PLANAR_SH(1)) +#define TYPE_HSV_16_SE (COLORSPACE_SH(PT_HSV)|CHANNELS_SH(3)|BYTES_SH(2)|ENDIAN16_SH(1)) + +// Named color index. Only 16 bits allowed (don't check colorspace) +#define TYPE_NAMED_COLOR_INDEX (CHANNELS_SH(1)|BYTES_SH(2)) + +// Float formatters. +#define TYPE_XYZ_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_XYZ)|CHANNELS_SH(3)|BYTES_SH(4)) +#define TYPE_Lab_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_Lab)|CHANNELS_SH(3)|BYTES_SH(4)) +#define TYPE_LabA_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_Lab)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(4)) +#define TYPE_GRAY_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_GRAY)|CHANNELS_SH(1)|BYTES_SH(4)) +#define TYPE_RGB_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(4)) + +#define TYPE_RGBA_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(4)) +#define TYPE_ARGB_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(4)|SWAPFIRST_SH(1)) +#define TYPE_BGR_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(4)|DOSWAP_SH(1)) +#define TYPE_BGRA_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(4)|DOSWAP_SH(1)|SWAPFIRST_SH(1)) +#define TYPE_ABGR_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(4)|DOSWAP_SH(1)) + +#define TYPE_CMYK_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(4)) + +// Floating point formatters. +// NOTE THAT 'BYTES' FIELD IS SET TO ZERO ON DLB because 8 bytes overflows the bitfield +#define TYPE_XYZ_DBL (FLOAT_SH(1)|COLORSPACE_SH(PT_XYZ)|CHANNELS_SH(3)|BYTES_SH(0)) +#define TYPE_Lab_DBL (FLOAT_SH(1)|COLORSPACE_SH(PT_Lab)|CHANNELS_SH(3)|BYTES_SH(0)) +#define TYPE_GRAY_DBL (FLOAT_SH(1)|COLORSPACE_SH(PT_GRAY)|CHANNELS_SH(1)|BYTES_SH(0)) +#define TYPE_RGB_DBL (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(0)) +#define TYPE_BGR_DBL (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(0)|DOSWAP_SH(1)) +#define TYPE_CMYK_DBL (FLOAT_SH(1)|COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(0)) + +// IEEE 754-2008 "half" +#define TYPE_GRAY_HALF_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_GRAY)|CHANNELS_SH(1)|BYTES_SH(2)) +#define TYPE_RGB_HALF_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(2)) +#define TYPE_RGBA_HALF_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)) +#define TYPE_CMYK_HALF_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(2)) + +#define TYPE_RGBA_HALF_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)) +#define TYPE_ARGB_HALF_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)|SWAPFIRST_SH(1)) +#define TYPE_BGR_HALF_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1)) +#define TYPE_BGRA_HALF_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1)|SWAPFIRST_SH(1)) +#define TYPE_ABGR_HALF_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1)) + +#endif + +// Colorspaces +typedef struct { + cmsFloat64Number X; + cmsFloat64Number Y; + cmsFloat64Number Z; + + } cmsCIEXYZ; + +typedef struct { + cmsFloat64Number x; + cmsFloat64Number y; + cmsFloat64Number Y; + + } cmsCIExyY; + +typedef struct { + cmsFloat64Number L; + cmsFloat64Number a; + cmsFloat64Number b; + + } cmsCIELab; + +typedef struct { + cmsFloat64Number L; + cmsFloat64Number C; + cmsFloat64Number h; + + } cmsCIELCh; + +typedef struct { + cmsFloat64Number J; + cmsFloat64Number C; + cmsFloat64Number h; + + } cmsJCh; + +typedef struct { + cmsCIEXYZ Red; + cmsCIEXYZ Green; + cmsCIEXYZ Blue; + + } cmsCIEXYZTRIPLE; + +typedef struct { + cmsCIExyY Red; + cmsCIExyY Green; + cmsCIExyY Blue; + + } cmsCIExyYTRIPLE; + +// Illuminant types for structs below +#define cmsILLUMINANT_TYPE_UNKNOWN 0x0000000 +#define cmsILLUMINANT_TYPE_D50 0x0000001 +#define cmsILLUMINANT_TYPE_D65 0x0000002 +#define cmsILLUMINANT_TYPE_D93 0x0000003 +#define cmsILLUMINANT_TYPE_F2 0x0000004 +#define cmsILLUMINANT_TYPE_D55 0x0000005 +#define cmsILLUMINANT_TYPE_A 0x0000006 +#define cmsILLUMINANT_TYPE_E 0x0000007 +#define cmsILLUMINANT_TYPE_F8 0x0000008 + +typedef struct { + cmsUInt32Number Observer; // 0 = unknown, 1=CIE 1931, 2=CIE 1964 + cmsCIEXYZ Backing; // Value of backing + cmsUInt32Number Geometry; // 0=unknown, 1=45/0, 0/45 2=0d, d/0 + cmsFloat64Number Flare; // 0..1.0 + cmsUInt32Number IlluminantType; + + } cmsICCMeasurementConditions; + +typedef struct { + cmsCIEXYZ IlluminantXYZ; // Not the same struct as CAM02, + cmsCIEXYZ SurroundXYZ; // This is for storing the tag + cmsUInt32Number IlluminantType; // viewing condition + + } cmsICCViewingConditions; + +// Support of non-standard functions -------------------------------------------------------------------------------------- + +CMSAPI int CMSEXPORT cmsstrcasecmp(const char* s1, const char* s2); +CMSAPI long int CMSEXPORT cmsfilelength(FILE* f); + +// Plug-In registering --------------------------------------------------------------------------------------------------- + +CMSAPI cmsBool CMSEXPORT cmsPlugin(void* Plugin); +CMSAPI cmsBool CMSEXPORT cmsPluginTHR(cmsContext ContextID, void* Plugin); +CMSAPI void CMSEXPORT cmsUnregisterPlugins(void); + +// Error logging ---------------------------------------------------------------------------------------------------------- + +// There is no error handling at all. When a function fails, it returns proper value. +// For example, all create functions does return NULL on failure. Other may return FALSE. +// It may be interesting, for the developer, to know why the function is failing. +// for that reason, lcms2 does offer a logging function. This function will get +// an ENGLISH string with some clues on what is going wrong. You can show this +// info to the end user if you wish, or just create some sort of log on disk. +// The logging function should NOT terminate the program, as this obviously can leave +// unfreed resources. It is the programmer's responsibility to check each function +// return code to make sure it didn't fail. + +#define cmsERROR_UNDEFINED 0 +#define cmsERROR_FILE 1 +#define cmsERROR_RANGE 2 +#define cmsERROR_INTERNAL 3 +#define cmsERROR_NULL 4 +#define cmsERROR_READ 5 +#define cmsERROR_SEEK 6 +#define cmsERROR_WRITE 7 +#define cmsERROR_UNKNOWN_EXTENSION 8 +#define cmsERROR_COLORSPACE_CHECK 9 +#define cmsERROR_ALREADY_DEFINED 10 +#define cmsERROR_BAD_SIGNATURE 11 +#define cmsERROR_CORRUPTION_DETECTED 12 +#define cmsERROR_NOT_SUITABLE 13 + +// Error logger is called with the ContextID when a message is raised. This gives the +// chance to know which thread is responsible of the warning and any environment associated +// with it. Non-multithreading applications may safely ignore this parameter. +// Note that under certain special circumstances, ContextID may be NULL. +typedef void (* cmsLogErrorHandlerFunction)(cmsContext ContextID, cmsUInt32Number ErrorCode, const char *Text); + +// Allows user to set any specific logger +CMSAPI void CMSEXPORT cmsSetLogErrorHandler(cmsLogErrorHandlerFunction Fn); + +// Conversions -------------------------------------------------------------------------------------------------------------- + +// Returns pointers to constant structs +CMSAPI const cmsCIEXYZ* CMSEXPORT cmsD50_XYZ(void); +CMSAPI const cmsCIExyY* CMSEXPORT cmsD50_xyY(void); + +// Colorimetric space conversions +CMSAPI void CMSEXPORT cmsXYZ2xyY(cmsCIExyY* Dest, const cmsCIEXYZ* Source); +CMSAPI void CMSEXPORT cmsxyY2XYZ(cmsCIEXYZ* Dest, const cmsCIExyY* Source); +CMSAPI void CMSEXPORT cmsXYZ2Lab(const cmsCIEXYZ* WhitePoint, cmsCIELab* Lab, const cmsCIEXYZ* xyz); +CMSAPI void CMSEXPORT cmsLab2XYZ(const cmsCIEXYZ* WhitePoint, cmsCIEXYZ* xyz, const cmsCIELab* Lab); +CMSAPI void CMSEXPORT cmsLab2LCh(cmsCIELCh*LCh, const cmsCIELab* Lab); +CMSAPI void CMSEXPORT cmsLCh2Lab(cmsCIELab* Lab, const cmsCIELCh* LCh); + +// Encoding /Decoding on PCS +CMSAPI void CMSEXPORT cmsLabEncoded2Float(cmsCIELab* Lab, const cmsUInt16Number wLab[3]); +CMSAPI void CMSEXPORT cmsLabEncoded2FloatV2(cmsCIELab* Lab, const cmsUInt16Number wLab[3]); +CMSAPI void CMSEXPORT cmsFloat2LabEncoded(cmsUInt16Number wLab[3], const cmsCIELab* Lab); +CMSAPI void CMSEXPORT cmsFloat2LabEncodedV2(cmsUInt16Number wLab[3], const cmsCIELab* Lab); +CMSAPI void CMSEXPORT cmsXYZEncoded2Float(cmsCIEXYZ* fxyz, const cmsUInt16Number XYZ[3]); +CMSAPI void CMSEXPORT cmsFloat2XYZEncoded(cmsUInt16Number XYZ[3], const cmsCIEXYZ* fXYZ); + +// DeltaE metrics +CMSAPI cmsFloat64Number CMSEXPORT cmsDeltaE(const cmsCIELab* Lab1, const cmsCIELab* Lab2); +CMSAPI cmsFloat64Number CMSEXPORT cmsCIE94DeltaE(const cmsCIELab* Lab1, const cmsCIELab* Lab2); +CMSAPI cmsFloat64Number CMSEXPORT cmsBFDdeltaE(const cmsCIELab* Lab1, const cmsCIELab* Lab2); +CMSAPI cmsFloat64Number CMSEXPORT cmsCMCdeltaE(const cmsCIELab* Lab1, const cmsCIELab* Lab2, cmsFloat64Number l, cmsFloat64Number c); +CMSAPI cmsFloat64Number CMSEXPORT cmsCIE2000DeltaE(const cmsCIELab* Lab1, const cmsCIELab* Lab2, cmsFloat64Number Kl, cmsFloat64Number Kc, cmsFloat64Number Kh); + +// Temperature <-> Chromaticity (Black body) +CMSAPI cmsBool CMSEXPORT cmsWhitePointFromTemp(cmsCIExyY* WhitePoint, cmsFloat64Number TempK); +CMSAPI cmsBool CMSEXPORT cmsTempFromWhitePoint(cmsFloat64Number* TempK, const cmsCIExyY* WhitePoint); + +// Chromatic adaptation +CMSAPI cmsBool CMSEXPORT cmsAdaptToIlluminant(cmsCIEXYZ* Result, const cmsCIEXYZ* SourceWhitePt, + const cmsCIEXYZ* Illuminant, + const cmsCIEXYZ* Value); + +// CIECAM02 --------------------------------------------------------------------------------------------------- + +// Viewing conditions. Please note those are CAM model viewing conditions, and not the ICC tag viewing +// conditions, which I'm naming cmsICCViewingConditions to make differences evident. Unfortunately, the tag +// cannot deal with surround La, Yb and D value so is basically useless to store CAM02 viewing conditions. + + +#define AVG_SURROUND 1 +#define DIM_SURROUND 2 +#define DARK_SURROUND 3 +#define CUTSHEET_SURROUND 4 + +#define D_CALCULATE (-1) + +typedef struct { + cmsCIEXYZ whitePoint; + cmsFloat64Number Yb; + cmsFloat64Number La; + int surround; + cmsFloat64Number D_value; + + } cmsViewingConditions; + +CMSAPI cmsHANDLE CMSEXPORT cmsCIECAM02Init(cmsContext ContextID, const cmsViewingConditions* pVC); +CMSAPI void CMSEXPORT cmsCIECAM02Done(cmsHANDLE hModel); +CMSAPI void CMSEXPORT cmsCIECAM02Forward(cmsHANDLE hModel, const cmsCIEXYZ* pIn, cmsJCh* pOut); +CMSAPI void CMSEXPORT cmsCIECAM02Reverse(cmsHANDLE hModel, const cmsJCh* pIn, cmsCIEXYZ* pOut); + + +// Tone curves ----------------------------------------------------------------------------------------- + +// This describes a curve segment. For a table of supported types, see the manual. User can increase the number of +// available types by using a proper plug-in. Parametric segments allow 10 parameters at most + +typedef struct { + cmsFloat32Number x0, x1; // Domain; for x0 < x <= x1 + cmsInt32Number Type; // Parametric type, Type == 0 means sampled segment. Negative values are reserved + cmsFloat64Number Params[10]; // Parameters if Type != 0 + cmsUInt32Number nGridPoints; // Number of grid points if Type == 0 + cmsFloat32Number* SampledPoints; // Points to an array of floats if Type == 0 + +} cmsCurveSegment; + +// The internal representation is none of your business. +typedef struct _cms_curve_struct cmsToneCurve; + +CMSAPI cmsToneCurve* CMSEXPORT cmsBuildSegmentedToneCurve(cmsContext ContextID, cmsInt32Number nSegments, const cmsCurveSegment Segments[]); +CMSAPI cmsToneCurve* CMSEXPORT cmsBuildParametricToneCurve(cmsContext ContextID, cmsInt32Number Type, const cmsFloat64Number Params[]); +CMSAPI cmsToneCurve* CMSEXPORT cmsBuildGamma(cmsContext ContextID, cmsFloat64Number Gamma); +CMSAPI cmsToneCurve* CMSEXPORT cmsBuildTabulatedToneCurve16(cmsContext ContextID, cmsInt32Number nEntries, const cmsUInt16Number values[]); +CMSAPI cmsToneCurve* CMSEXPORT cmsBuildTabulatedToneCurveFloat(cmsContext ContextID, cmsUInt32Number nEntries, const cmsFloat32Number values[]); +CMSAPI void CMSEXPORT cmsFreeToneCurve(cmsToneCurve* Curve); +CMSAPI void CMSEXPORT cmsFreeToneCurveTriple(cmsToneCurve* Curve[3]); +CMSAPI cmsToneCurve* CMSEXPORT cmsDupToneCurve(const cmsToneCurve* Src); +CMSAPI cmsToneCurve* CMSEXPORT cmsReverseToneCurve(const cmsToneCurve* InGamma); +CMSAPI cmsToneCurve* CMSEXPORT cmsReverseToneCurveEx(cmsInt32Number nResultSamples, const cmsToneCurve* InGamma); +CMSAPI cmsToneCurve* CMSEXPORT cmsJoinToneCurve(cmsContext ContextID, const cmsToneCurve* X, const cmsToneCurve* Y, cmsUInt32Number nPoints); +CMSAPI cmsBool CMSEXPORT cmsSmoothToneCurve(cmsToneCurve* Tab, cmsFloat64Number lambda); +CMSAPI cmsFloat32Number CMSEXPORT cmsEvalToneCurveFloat(const cmsToneCurve* Curve, cmsFloat32Number v); +CMSAPI cmsUInt16Number CMSEXPORT cmsEvalToneCurve16(const cmsToneCurve* Curve, cmsUInt16Number v); +CMSAPI cmsBool CMSEXPORT cmsIsToneCurveMultisegment(const cmsToneCurve* InGamma); +CMSAPI cmsBool CMSEXPORT cmsIsToneCurveLinear(const cmsToneCurve* Curve); +CMSAPI cmsBool CMSEXPORT cmsIsToneCurveMonotonic(const cmsToneCurve* t); +CMSAPI cmsBool CMSEXPORT cmsIsToneCurveDescending(const cmsToneCurve* t); +CMSAPI cmsInt32Number CMSEXPORT cmsGetToneCurveParametricType(const cmsToneCurve* t); +CMSAPI cmsFloat64Number CMSEXPORT cmsEstimateGamma(const cmsToneCurve* t, cmsFloat64Number Precision); + +// Tone curve tabular estimation +CMSAPI cmsUInt32Number CMSEXPORT cmsGetToneCurveEstimatedTableEntries(const cmsToneCurve* t); +CMSAPI const cmsUInt16Number* CMSEXPORT cmsGetToneCurveEstimatedTable(const cmsToneCurve* t); + + +// Implements pipelines of multi-processing elements ------------------------------------------------------------- + +// Nothing to see here, move along +typedef struct _cmsPipeline_struct cmsPipeline; +typedef struct _cmsStage_struct cmsStage; + +// Those are hi-level pipelines +CMSAPI cmsPipeline* CMSEXPORT cmsPipelineAlloc(cmsContext ContextID, cmsUInt32Number InputChannels, cmsUInt32Number OutputChannels); +CMSAPI void CMSEXPORT cmsPipelineFree(cmsPipeline* lut); +CMSAPI cmsPipeline* CMSEXPORT cmsPipelineDup(const cmsPipeline* Orig); + +CMSAPI cmsContext CMSEXPORT cmsGetPipelineContextID(const cmsPipeline* lut); +CMSAPI cmsUInt32Number CMSEXPORT cmsPipelineInputChannels(const cmsPipeline* lut); +CMSAPI cmsUInt32Number CMSEXPORT cmsPipelineOutputChannels(const cmsPipeline* lut); + +CMSAPI cmsUInt32Number CMSEXPORT cmsPipelineStageCount(const cmsPipeline* lut); +CMSAPI cmsStage* CMSEXPORT cmsPipelineGetPtrToFirstStage(const cmsPipeline* lut); +CMSAPI cmsStage* CMSEXPORT cmsPipelineGetPtrToLastStage(const cmsPipeline* lut); + +CMSAPI void CMSEXPORT cmsPipelineEval16(const cmsUInt16Number In[], cmsUInt16Number Out[], const cmsPipeline* lut); +CMSAPI void CMSEXPORT cmsPipelineEvalFloat(const cmsFloat32Number In[], cmsFloat32Number Out[], const cmsPipeline* lut); +CMSAPI cmsBool CMSEXPORT cmsPipelineEvalReverseFloat(cmsFloat32Number Target[], cmsFloat32Number Result[], cmsFloat32Number Hint[], const cmsPipeline* lut); +CMSAPI cmsBool CMSEXPORT cmsPipelineCat(cmsPipeline* l1, const cmsPipeline* l2); +CMSAPI cmsBool CMSEXPORT cmsPipelineSetSaveAs8bitsFlag(cmsPipeline* lut, cmsBool On); + +// Where to place/locate the stages in the pipeline chain +typedef enum { cmsAT_BEGIN, cmsAT_END } cmsStageLoc; + +CMSAPI int CMSEXPORT cmsPipelineInsertStage(cmsPipeline* lut, cmsStageLoc loc, cmsStage* mpe); +CMSAPI void CMSEXPORT cmsPipelineUnlinkStage(cmsPipeline* lut, cmsStageLoc loc, cmsStage** mpe); + +// This function is quite useful to analyze the structure of a Pipeline and retrieve the Stage elements +// that conform the Pipeline. It should be called with the Pipeline, the number of expected elements and +// then a list of expected types followed with a list of double pointers to Stage elements. If +// the function founds a match with current pipeline, it fills the pointers and returns TRUE +// if not, returns FALSE without touching anything. +CMSAPI cmsBool CMSEXPORT cmsPipelineCheckAndRetreiveStages(const cmsPipeline* Lut, cmsUInt32Number n, ...); + +// Matrix has double precision and CLUT has only float precision. That is because an ICC profile can encode +// matrices with far more precision that CLUTS +CMSAPI cmsStage* CMSEXPORT cmsStageAllocIdentity(cmsContext ContextID, cmsUInt32Number nChannels); +CMSAPI cmsStage* CMSEXPORT cmsStageAllocToneCurves(cmsContext ContextID, cmsUInt32Number nChannels, cmsToneCurve* const Curves[]); +CMSAPI cmsStage* CMSEXPORT cmsStageAllocMatrix(cmsContext ContextID, cmsUInt32Number Rows, cmsUInt32Number Cols, const cmsFloat64Number* Matrix, const cmsFloat64Number* Offset); + +CMSAPI cmsStage* CMSEXPORT cmsStageAllocCLut16bit(cmsContext ContextID, cmsUInt32Number nGridPoints, cmsUInt32Number inputChan, cmsUInt32Number outputChan, const cmsUInt16Number* Table); +CMSAPI cmsStage* CMSEXPORT cmsStageAllocCLutFloat(cmsContext ContextID, cmsUInt32Number nGridPoints, cmsUInt32Number inputChan, cmsUInt32Number outputChan, const cmsFloat32Number* Table); + +CMSAPI cmsStage* CMSEXPORT cmsStageAllocCLut16bitGranular(cmsContext ContextID, const cmsUInt32Number clutPoints[], cmsUInt32Number inputChan, cmsUInt32Number outputChan, const cmsUInt16Number* Table); +CMSAPI cmsStage* CMSEXPORT cmsStageAllocCLutFloatGranular(cmsContext ContextID, const cmsUInt32Number clutPoints[], cmsUInt32Number inputChan, cmsUInt32Number outputChan, const cmsFloat32Number* Table); + +CMSAPI cmsStage* CMSEXPORT cmsStageDup(cmsStage* mpe); +CMSAPI void CMSEXPORT cmsStageFree(cmsStage* mpe); +CMSAPI cmsStage* CMSEXPORT cmsStageNext(const cmsStage* mpe); + +CMSAPI cmsUInt32Number CMSEXPORT cmsStageInputChannels(const cmsStage* mpe); +CMSAPI cmsUInt32Number CMSEXPORT cmsStageOutputChannels(const cmsStage* mpe); +CMSAPI cmsStageSignature CMSEXPORT cmsStageType(const cmsStage* mpe); +CMSAPI void* CMSEXPORT cmsStageData(const cmsStage* mpe); + +// Sampling +typedef cmsInt32Number (* cmsSAMPLER16) (register const cmsUInt16Number In[], + register cmsUInt16Number Out[], + register void * Cargo); + +typedef cmsInt32Number (* cmsSAMPLERFLOAT)(register const cmsFloat32Number In[], + register cmsFloat32Number Out[], + register void * Cargo); + +// Use this flag to prevent changes being written to destination +#define SAMPLER_INSPECT 0x01000000 + +// For CLUT only +CMSAPI cmsBool CMSEXPORT cmsStageSampleCLut16bit(cmsStage* mpe, cmsSAMPLER16 Sampler, void* Cargo, cmsUInt32Number dwFlags); +CMSAPI cmsBool CMSEXPORT cmsStageSampleCLutFloat(cmsStage* mpe, cmsSAMPLERFLOAT Sampler, void* Cargo, cmsUInt32Number dwFlags); + +// Slicers +CMSAPI cmsBool CMSEXPORT cmsSliceSpace16(cmsUInt32Number nInputs, const cmsUInt32Number clutPoints[], + cmsSAMPLER16 Sampler, void * Cargo); + +CMSAPI cmsBool CMSEXPORT cmsSliceSpaceFloat(cmsUInt32Number nInputs, const cmsUInt32Number clutPoints[], + cmsSAMPLERFLOAT Sampler, void * Cargo); + +// Multilocalized Unicode management --------------------------------------------------------------------------------------- + +typedef struct _cms_MLU_struct cmsMLU; + +#define cmsNoLanguage "\0\0" +#define cmsNoCountry "\0\0" + +CMSAPI cmsMLU* CMSEXPORT cmsMLUalloc(cmsContext ContextID, cmsUInt32Number nItems); +CMSAPI void CMSEXPORT cmsMLUfree(cmsMLU* mlu); +CMSAPI cmsMLU* CMSEXPORT cmsMLUdup(const cmsMLU* mlu); + +CMSAPI cmsBool CMSEXPORT cmsMLUsetASCII(cmsMLU* mlu, + const char LanguageCode[3], const char CountryCode[3], + const char* ASCIIString); +CMSAPI cmsBool CMSEXPORT cmsMLUsetWide(cmsMLU* mlu, + const char LanguageCode[3], const char CountryCode[3], + const wchar_t* WideString); + +CMSAPI cmsUInt32Number CMSEXPORT cmsMLUgetASCII(const cmsMLU* mlu, + const char LanguageCode[3], const char CountryCode[3], + char* Buffer, cmsUInt32Number BufferSize); + +CMSAPI cmsUInt32Number CMSEXPORT cmsMLUgetWide(const cmsMLU* mlu, + const char LanguageCode[3], const char CountryCode[3], + wchar_t* Buffer, cmsUInt32Number BufferSize); + +CMSAPI cmsBool CMSEXPORT cmsMLUgetTranslation(const cmsMLU* mlu, + const char LanguageCode[3], const char CountryCode[3], + char ObtainedLanguage[3], char ObtainedCountry[3]); + +CMSAPI cmsUInt32Number CMSEXPORT cmsMLUtranslationsCount(const cmsMLU* mlu); + +CMSAPI cmsBool CMSEXPORT cmsMLUtranslationsCodes(const cmsMLU* mlu, + cmsUInt32Number idx, + char LanguageCode[3], + char CountryCode[3]); + +// Undercolorremoval & black generation ------------------------------------------------------------------------------------- + +typedef struct { + cmsToneCurve* Ucr; + cmsToneCurve* Bg; + cmsMLU* Desc; + +} cmsUcrBg; + +// Screening ---------------------------------------------------------------------------------------------------------------- + +#define cmsPRINTER_DEFAULT_SCREENS 0x0001 +#define cmsFREQUENCE_UNITS_LINES_CM 0x0000 +#define cmsFREQUENCE_UNITS_LINES_INCH 0x0002 + +#define cmsSPOT_UNKNOWN 0 +#define cmsSPOT_PRINTER_DEFAULT 1 +#define cmsSPOT_ROUND 2 +#define cmsSPOT_DIAMOND 3 +#define cmsSPOT_ELLIPSE 4 +#define cmsSPOT_LINE 5 +#define cmsSPOT_SQUARE 6 +#define cmsSPOT_CROSS 7 + +typedef struct { + cmsFloat64Number Frequency; + cmsFloat64Number ScreenAngle; + cmsUInt32Number SpotShape; + +} cmsScreeningChannel; + +typedef struct { + cmsUInt32Number Flag; + cmsUInt32Number nChannels; + cmsScreeningChannel Channels[cmsMAXCHANNELS]; + +} cmsScreening; + + +// Named color ----------------------------------------------------------------------------------------------------------------- + +typedef struct _cms_NAMEDCOLORLIST_struct cmsNAMEDCOLORLIST; + +CMSAPI cmsNAMEDCOLORLIST* CMSEXPORT cmsAllocNamedColorList(cmsContext ContextID, + cmsUInt32Number n, + cmsUInt32Number ColorantCount, + const char* Prefix, const char* Suffix); + +CMSAPI void CMSEXPORT cmsFreeNamedColorList(cmsNAMEDCOLORLIST* v); +CMSAPI cmsNAMEDCOLORLIST* CMSEXPORT cmsDupNamedColorList(const cmsNAMEDCOLORLIST* v); +CMSAPI cmsBool CMSEXPORT cmsAppendNamedColor(cmsNAMEDCOLORLIST* v, const char* Name, + cmsUInt16Number PCS[3], + cmsUInt16Number Colorant[cmsMAXCHANNELS]); + +CMSAPI cmsUInt32Number CMSEXPORT cmsNamedColorCount(const cmsNAMEDCOLORLIST* v); +CMSAPI cmsInt32Number CMSEXPORT cmsNamedColorIndex(const cmsNAMEDCOLORLIST* v, const char* Name); + +CMSAPI cmsBool CMSEXPORT cmsNamedColorInfo(const cmsNAMEDCOLORLIST* NamedColorList, cmsUInt32Number nColor, + char* Name, + char* Prefix, + char* Suffix, + cmsUInt16Number* PCS, + cmsUInt16Number* Colorant); + +// Retrieve named color list from transform +CMSAPI cmsNAMEDCOLORLIST* CMSEXPORT cmsGetNamedColorList(cmsHTRANSFORM xform); + +// Profile sequence ----------------------------------------------------------------------------------------------------- + +// Profile sequence descriptor. Some fields come from profile sequence descriptor tag, others +// come from Profile Sequence Identifier Tag +typedef struct { + + cmsSignature deviceMfg; + cmsSignature deviceModel; + cmsUInt64Number attributes; + cmsTechnologySignature technology; + cmsProfileID ProfileID; + cmsMLU* Manufacturer; + cmsMLU* Model; + cmsMLU* Description; + +} cmsPSEQDESC; + +typedef struct { + + cmsUInt32Number n; + cmsContext ContextID; + cmsPSEQDESC* seq; + +} cmsSEQ; + +CMSAPI cmsSEQ* CMSEXPORT cmsAllocProfileSequenceDescription(cmsContext ContextID, cmsUInt32Number n); +CMSAPI cmsSEQ* CMSEXPORT cmsDupProfileSequenceDescription(const cmsSEQ* pseq); +CMSAPI void CMSEXPORT cmsFreeProfileSequenceDescription(cmsSEQ* pseq); + +// Dictionaries -------------------------------------------------------------------------------------------------------- + +typedef struct _cmsDICTentry_struct { + + struct _cmsDICTentry_struct* Next; + + cmsMLU *DisplayName; + cmsMLU *DisplayValue; + wchar_t* Name; + wchar_t* Value; + +} cmsDICTentry; + +CMSAPI cmsHANDLE CMSEXPORT cmsDictAlloc(cmsContext ContextID); +CMSAPI void CMSEXPORT cmsDictFree(cmsHANDLE hDict); +CMSAPI cmsHANDLE CMSEXPORT cmsDictDup(cmsHANDLE hDict); + +CMSAPI cmsBool CMSEXPORT cmsDictAddEntry(cmsHANDLE hDict, const wchar_t* Name, const wchar_t* Value, const cmsMLU *DisplayName, const cmsMLU *DisplayValue); +CMSAPI const cmsDICTentry* CMSEXPORT cmsDictGetEntryList(cmsHANDLE hDict); +CMSAPI const cmsDICTentry* CMSEXPORT cmsDictNextEntry(const cmsDICTentry* e); + +// Access to Profile data ---------------------------------------------------------------------------------------------- +CMSAPI cmsHPROFILE CMSEXPORT cmsCreateProfilePlaceholder(cmsContext ContextID); + +CMSAPI cmsContext CMSEXPORT cmsGetProfileContextID(cmsHPROFILE hProfile); +CMSAPI cmsInt32Number CMSEXPORT cmsGetTagCount(cmsHPROFILE hProfile); +CMSAPI cmsTagSignature CMSEXPORT cmsGetTagSignature(cmsHPROFILE hProfile, cmsUInt32Number n); +CMSAPI cmsBool CMSEXPORT cmsIsTag(cmsHPROFILE hProfile, cmsTagSignature sig); + +// Read and write pre-formatted data +CMSAPI void* CMSEXPORT cmsReadTag(cmsHPROFILE hProfile, cmsTagSignature sig); +CMSAPI cmsBool CMSEXPORT cmsWriteTag(cmsHPROFILE hProfile, cmsTagSignature sig, const void* data); +CMSAPI cmsBool CMSEXPORT cmsLinkTag(cmsHPROFILE hProfile, cmsTagSignature sig, cmsTagSignature dest); +CMSAPI cmsTagSignature CMSEXPORT cmsTagLinkedTo(cmsHPROFILE hProfile, cmsTagSignature sig); + +// Read and write raw data +CMSAPI cmsInt32Number CMSEXPORT cmsReadRawTag(cmsHPROFILE hProfile, cmsTagSignature sig, void* Buffer, cmsUInt32Number BufferSize); +CMSAPI cmsBool CMSEXPORT cmsWriteRawTag(cmsHPROFILE hProfile, cmsTagSignature sig, const void* data, cmsUInt32Number Size); + +// Access header data +#define cmsEmbeddedProfileFalse 0x00000000 +#define cmsEmbeddedProfileTrue 0x00000001 +#define cmsUseAnywhere 0x00000000 +#define cmsUseWithEmbeddedDataOnly 0x00000002 + +CMSAPI cmsUInt32Number CMSEXPORT cmsGetHeaderFlags(cmsHPROFILE hProfile); +CMSAPI void CMSEXPORT cmsGetHeaderAttributes(cmsHPROFILE hProfile, cmsUInt64Number* Flags); +CMSAPI void CMSEXPORT cmsGetHeaderProfileID(cmsHPROFILE hProfile, cmsUInt8Number* ProfileID); +CMSAPI cmsBool CMSEXPORT cmsGetHeaderCreationDateTime(cmsHPROFILE hProfile, struct tm *Dest); +CMSAPI cmsUInt32Number CMSEXPORT cmsGetHeaderRenderingIntent(cmsHPROFILE hProfile); + +CMSAPI void CMSEXPORT cmsSetHeaderFlags(cmsHPROFILE hProfile, cmsUInt32Number Flags); +CMSAPI cmsUInt32Number CMSEXPORT cmsGetHeaderManufacturer(cmsHPROFILE hProfile); +CMSAPI void CMSEXPORT cmsSetHeaderManufacturer(cmsHPROFILE hProfile, cmsUInt32Number manufacturer); +CMSAPI cmsUInt32Number CMSEXPORT cmsGetHeaderCreator(cmsHPROFILE hProfile); +CMSAPI cmsUInt32Number CMSEXPORT cmsGetHeaderModel(cmsHPROFILE hProfile); +CMSAPI void CMSEXPORT cmsSetHeaderModel(cmsHPROFILE hProfile, cmsUInt32Number model); +CMSAPI void CMSEXPORT cmsSetHeaderAttributes(cmsHPROFILE hProfile, cmsUInt64Number Flags); +CMSAPI void CMSEXPORT cmsSetHeaderProfileID(cmsHPROFILE hProfile, cmsUInt8Number* ProfileID); +CMSAPI void CMSEXPORT cmsSetHeaderRenderingIntent(cmsHPROFILE hProfile, cmsUInt32Number RenderingIntent); + +CMSAPI cmsColorSpaceSignature + CMSEXPORT cmsGetPCS(cmsHPROFILE hProfile); +CMSAPI void CMSEXPORT cmsSetPCS(cmsHPROFILE hProfile, cmsColorSpaceSignature pcs); +CMSAPI cmsColorSpaceSignature + CMSEXPORT cmsGetColorSpace(cmsHPROFILE hProfile); +CMSAPI void CMSEXPORT cmsSetColorSpace(cmsHPROFILE hProfile, cmsColorSpaceSignature sig); +CMSAPI cmsProfileClassSignature + CMSEXPORT cmsGetDeviceClass(cmsHPROFILE hProfile); +CMSAPI void CMSEXPORT cmsSetDeviceClass(cmsHPROFILE hProfile, cmsProfileClassSignature sig); +CMSAPI void CMSEXPORT cmsSetProfileVersion(cmsHPROFILE hProfile, cmsFloat64Number Version); +CMSAPI cmsFloat64Number CMSEXPORT cmsGetProfileVersion(cmsHPROFILE hProfile); + +CMSAPI cmsUInt32Number CMSEXPORT cmsGetEncodedICCversion(cmsHPROFILE hProfile); +CMSAPI void CMSEXPORT cmsSetEncodedICCversion(cmsHPROFILE hProfile, cmsUInt32Number Version); + +// How profiles may be used +#define LCMS_USED_AS_INPUT 0 +#define LCMS_USED_AS_OUTPUT 1 +#define LCMS_USED_AS_PROOF 2 + +CMSAPI cmsBool CMSEXPORT cmsIsIntentSupported(cmsHPROFILE hProfile, cmsUInt32Number Intent, cmsUInt32Number UsedDirection); +CMSAPI cmsBool CMSEXPORT cmsIsMatrixShaper(cmsHPROFILE hProfile); +CMSAPI cmsBool CMSEXPORT cmsIsCLUT(cmsHPROFILE hProfile, cmsUInt32Number Intent, cmsUInt32Number UsedDirection); + +// Translate form/to our notation to ICC +CMSAPI cmsColorSpaceSignature CMSEXPORT _cmsICCcolorSpace(int OurNotation); +CMSAPI int CMSEXPORT _cmsLCMScolorSpace(cmsColorSpaceSignature ProfileSpace); + +CMSAPI cmsUInt32Number CMSEXPORT cmsChannelsOf(cmsColorSpaceSignature ColorSpace); + +// Build a suitable formatter for the colorspace of this profile +CMSAPI cmsUInt32Number CMSEXPORT cmsFormatterForColorspaceOfProfile(cmsHPROFILE hProfile, cmsUInt32Number nBytes, cmsBool lIsFloat); +CMSAPI cmsUInt32Number CMSEXPORT cmsFormatterForPCSOfProfile(cmsHPROFILE hProfile, cmsUInt32Number nBytes, cmsBool lIsFloat); + + +// Localized info +typedef enum { + cmsInfoDescription = 0, + cmsInfoManufacturer = 1, + cmsInfoModel = 2, + cmsInfoCopyright = 3 +} cmsInfoType; + +CMSAPI cmsUInt32Number CMSEXPORT cmsGetProfileInfo(cmsHPROFILE hProfile, cmsInfoType Info, + const char LanguageCode[3], const char CountryCode[3], + wchar_t* Buffer, cmsUInt32Number BufferSize); + +CMSAPI cmsUInt32Number CMSEXPORT cmsGetProfileInfoASCII(cmsHPROFILE hProfile, cmsInfoType Info, + const char LanguageCode[3], const char CountryCode[3], + char* Buffer, cmsUInt32Number BufferSize); + +// IO handlers ---------------------------------------------------------------------------------------------------------- + +typedef struct _cms_io_handler cmsIOHANDLER; + +CMSAPI cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromFile(cmsContext ContextID, const char* FileName, const char* AccessMode); +CMSAPI cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromStream(cmsContext ContextID, FILE* Stream); +CMSAPI cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromMem(cmsContext ContextID, void *Buffer, cmsUInt32Number size, const char* AccessMode); +CMSAPI cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromNULL(cmsContext ContextID); +CMSAPI cmsBool CMSEXPORT cmsCloseIOhandler(cmsIOHANDLER* io); + +// MD5 message digest -------------------------------------------------------------------------------------------------- + +CMSAPI cmsBool CMSEXPORT cmsMD5computeID(cmsHPROFILE hProfile); + +// Profile high level funtions ------------------------------------------------------------------------------------------ + +CMSAPI cmsHPROFILE CMSEXPORT cmsOpenProfileFromFile(const char *ICCProfile, const char *sAccess); +CMSAPI cmsHPROFILE CMSEXPORT cmsOpenProfileFromFileTHR(cmsContext ContextID, const char *ICCProfile, const char *sAccess); +CMSAPI cmsHPROFILE CMSEXPORT cmsOpenProfileFromStream(FILE* ICCProfile, const char* sAccess); +CMSAPI cmsHPROFILE CMSEXPORT cmsOpenProfileFromStreamTHR(cmsContext ContextID, FILE* ICCProfile, const char* sAccess); +CMSAPI cmsHPROFILE CMSEXPORT cmsOpenProfileFromMem(const void * MemPtr, cmsUInt32Number dwSize); +CMSAPI cmsHPROFILE CMSEXPORT cmsOpenProfileFromMemTHR(cmsContext ContextID, const void * MemPtr, cmsUInt32Number dwSize); +CMSAPI cmsHPROFILE CMSEXPORT cmsOpenProfileFromIOhandlerTHR(cmsContext ContextID, cmsIOHANDLER* io); +CMSAPI cmsBool CMSEXPORT cmsCloseProfile(cmsHPROFILE hProfile); + +CMSAPI cmsBool CMSEXPORT cmsSaveProfileToFile(cmsHPROFILE hProfile, const char* FileName); +CMSAPI cmsBool CMSEXPORT cmsSaveProfileToStream(cmsHPROFILE hProfile, FILE* Stream); +CMSAPI cmsBool CMSEXPORT cmsSaveProfileToMem(cmsHPROFILE hProfile, void *MemPtr, cmsUInt32Number* BytesNeeded); +CMSAPI cmsUInt32Number CMSEXPORT cmsSaveProfileToIOhandler(cmsHPROFILE hProfile, cmsIOHANDLER* io); + +// Predefined virtual profiles ------------------------------------------------------------------------------------------ + +CMSAPI cmsHPROFILE CMSEXPORT cmsCreateRGBProfileTHR(cmsContext ContextID, + const cmsCIExyY* WhitePoint, + const cmsCIExyYTRIPLE* Primaries, + cmsToneCurve* const TransferFunction[3]); + +CMSAPI cmsHPROFILE CMSEXPORT cmsCreateRGBProfile(const cmsCIExyY* WhitePoint, + const cmsCIExyYTRIPLE* Primaries, + cmsToneCurve* const TransferFunction[3]); + +CMSAPI cmsHPROFILE CMSEXPORT cmsCreateGrayProfileTHR(cmsContext ContextID, + const cmsCIExyY* WhitePoint, + const cmsToneCurve* TransferFunction); + +CMSAPI cmsHPROFILE CMSEXPORT cmsCreateGrayProfile(const cmsCIExyY* WhitePoint, + const cmsToneCurve* TransferFunction); + +CMSAPI cmsHPROFILE CMSEXPORT cmsCreateLinearizationDeviceLinkTHR(cmsContext ContextID, + cmsColorSpaceSignature ColorSpace, + cmsToneCurve* const TransferFunctions[]); + +CMSAPI cmsHPROFILE CMSEXPORT cmsCreateLinearizationDeviceLink(cmsColorSpaceSignature ColorSpace, + cmsToneCurve* const TransferFunctions[]); + +CMSAPI cmsHPROFILE CMSEXPORT cmsCreateInkLimitingDeviceLinkTHR(cmsContext ContextID, + cmsColorSpaceSignature ColorSpace, cmsFloat64Number Limit); + +CMSAPI cmsHPROFILE CMSEXPORT cmsCreateInkLimitingDeviceLink(cmsColorSpaceSignature ColorSpace, cmsFloat64Number Limit); + + +CMSAPI cmsHPROFILE CMSEXPORT cmsCreateLab2ProfileTHR(cmsContext ContextID, const cmsCIExyY* WhitePoint); +CMSAPI cmsHPROFILE CMSEXPORT cmsCreateLab2Profile(const cmsCIExyY* WhitePoint); +CMSAPI cmsHPROFILE CMSEXPORT cmsCreateLab4ProfileTHR(cmsContext ContextID, const cmsCIExyY* WhitePoint); +CMSAPI cmsHPROFILE CMSEXPORT cmsCreateLab4Profile(const cmsCIExyY* WhitePoint); + +CMSAPI cmsHPROFILE CMSEXPORT cmsCreateXYZProfileTHR(cmsContext ContextID); +CMSAPI cmsHPROFILE CMSEXPORT cmsCreateXYZProfile(void); + +CMSAPI cmsHPROFILE CMSEXPORT cmsCreate_sRGBProfileTHR(cmsContext ContextID); +CMSAPI cmsHPROFILE CMSEXPORT cmsCreate_sRGBProfile(void); + +CMSAPI cmsHPROFILE CMSEXPORT cmsCreateBCHSWabstractProfileTHR(cmsContext ContextID, + int nLUTPoints, + cmsFloat64Number Bright, + cmsFloat64Number Contrast, + cmsFloat64Number Hue, + cmsFloat64Number Saturation, + int TempSrc, + int TempDest); + +CMSAPI cmsHPROFILE CMSEXPORT cmsCreateBCHSWabstractProfile(int nLUTPoints, + cmsFloat64Number Bright, + cmsFloat64Number Contrast, + cmsFloat64Number Hue, + cmsFloat64Number Saturation, + int TempSrc, + int TempDest); + +CMSAPI cmsHPROFILE CMSEXPORT cmsCreateNULLProfileTHR(cmsContext ContextID); +CMSAPI cmsHPROFILE CMSEXPORT cmsCreateNULLProfile(void); + +// Converts a transform to a devicelink profile +CMSAPI cmsHPROFILE CMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, cmsFloat64Number Version, cmsUInt32Number dwFlags); + +// Intents ---------------------------------------------------------------------------------------------- + +// ICC Intents +#define INTENT_PERCEPTUAL 0 +#define INTENT_RELATIVE_COLORIMETRIC 1 +#define INTENT_SATURATION 2 +#define INTENT_ABSOLUTE_COLORIMETRIC 3 + +// Non-ICC intents +#define INTENT_PRESERVE_K_ONLY_PERCEPTUAL 10 +#define INTENT_PRESERVE_K_ONLY_RELATIVE_COLORIMETRIC 11 +#define INTENT_PRESERVE_K_ONLY_SATURATION 12 +#define INTENT_PRESERVE_K_PLANE_PERCEPTUAL 13 +#define INTENT_PRESERVE_K_PLANE_RELATIVE_COLORIMETRIC 14 +#define INTENT_PRESERVE_K_PLANE_SATURATION 15 + +// Call with NULL as parameters to get the intent count +CMSAPI cmsUInt32Number CMSEXPORT cmsGetSupportedIntents(cmsUInt32Number nMax, cmsUInt32Number* Codes, char** Descriptions); + +// Flags + +#define cmsFLAGS_NOCACHE 0x0040 // Inhibit 1-pixel cache +#define cmsFLAGS_NOOPTIMIZE 0x0100 // Inhibit optimizations +#define cmsFLAGS_NULLTRANSFORM 0x0200 // Don't transform anyway + +// Proofing flags +#define cmsFLAGS_GAMUTCHECK 0x1000 // Out of Gamut alarm +#define cmsFLAGS_SOFTPROOFING 0x4000 // Do softproofing + +// Misc +#define cmsFLAGS_BLACKPOINTCOMPENSATION 0x2000 +#define cmsFLAGS_NOWHITEONWHITEFIXUP 0x0004 // Don't fix scum dot +#define cmsFLAGS_HIGHRESPRECALC 0x0400 // Use more memory to give better accurancy +#define cmsFLAGS_LOWRESPRECALC 0x0800 // Use less memory to minimize resouces + +// For devicelink creation +#define cmsFLAGS_8BITS_DEVICELINK 0x0008 // Create 8 bits devicelinks +#define cmsFLAGS_GUESSDEVICECLASS 0x0020 // Guess device class (for transform2devicelink) +#define cmsFLAGS_KEEP_SEQUENCE 0x0080 // Keep profile sequence for devicelink creation + +// Specific to a particular optimizations +#define cmsFLAGS_FORCE_CLUT 0x0002 // Force CLUT optimization +#define cmsFLAGS_CLUT_POST_LINEARIZATION 0x0001 // create postlinearization tables if possible +#define cmsFLAGS_CLUT_PRE_LINEARIZATION 0x0010 // create prelinearization tables if possible + +// Fine-tune control over number of gridpoints +#define cmsFLAGS_GRIDPOINTS(n) (((n) & 0xFF) << 16) + +// CRD special +#define cmsFLAGS_NODEFAULTRESOURCEDEF 0x01000000 + +// Transforms --------------------------------------------------------------------------------------------------- + +CMSAPI cmsHTRANSFORM CMSEXPORT cmsCreateTransformTHR(cmsContext ContextID, + cmsHPROFILE Input, + cmsUInt32Number InputFormat, + cmsHPROFILE Output, + cmsUInt32Number OutputFormat, + cmsUInt32Number Intent, + cmsUInt32Number dwFlags); + +CMSAPI cmsHTRANSFORM CMSEXPORT cmsCreateTransform(cmsHPROFILE Input, + cmsUInt32Number InputFormat, + cmsHPROFILE Output, + cmsUInt32Number OutputFormat, + cmsUInt32Number Intent, + cmsUInt32Number dwFlags); + +CMSAPI cmsHTRANSFORM CMSEXPORT cmsCreateProofingTransformTHR(cmsContext ContextID, + cmsHPROFILE Input, + cmsUInt32Number InputFormat, + cmsHPROFILE Output, + cmsUInt32Number OutputFormat, + cmsHPROFILE Proofing, + cmsUInt32Number Intent, + cmsUInt32Number ProofingIntent, + cmsUInt32Number dwFlags); + +CMSAPI cmsHTRANSFORM CMSEXPORT cmsCreateProofingTransform(cmsHPROFILE Input, + cmsUInt32Number InputFormat, + cmsHPROFILE Output, + cmsUInt32Number OutputFormat, + cmsHPROFILE Proofing, + cmsUInt32Number Intent, + cmsUInt32Number ProofingIntent, + cmsUInt32Number dwFlags); + +CMSAPI cmsHTRANSFORM CMSEXPORT cmsCreateMultiprofileTransformTHR(cmsContext ContextID, + cmsHPROFILE hProfiles[], + cmsUInt32Number nProfiles, + cmsUInt32Number InputFormat, + cmsUInt32Number OutputFormat, + cmsUInt32Number Intent, + cmsUInt32Number dwFlags); + + +CMSAPI cmsHTRANSFORM CMSEXPORT cmsCreateMultiprofileTransform(cmsHPROFILE hProfiles[], + cmsUInt32Number nProfiles, + cmsUInt32Number InputFormat, + cmsUInt32Number OutputFormat, + cmsUInt32Number Intent, + cmsUInt32Number dwFlags); + + +CMSAPI cmsHTRANSFORM CMSEXPORT cmsCreateExtendedTransform(cmsContext ContextID, + cmsUInt32Number nProfiles, cmsHPROFILE hProfiles[], + cmsBool BPC[], + cmsUInt32Number Intents[], + cmsFloat64Number AdaptationStates[], + cmsHPROFILE hGamutProfile, + cmsUInt32Number nGamutPCSposition, + cmsUInt32Number InputFormat, + cmsUInt32Number OutputFormat, + cmsUInt32Number dwFlags); + +CMSAPI void CMSEXPORT cmsDeleteTransform(cmsHTRANSFORM hTransform); + +CMSAPI void CMSEXPORT cmsDoTransform(cmsHTRANSFORM Transform, + const void * InputBuffer, + void * OutputBuffer, + cmsUInt32Number Size); + +CMSAPI void CMSEXPORT cmsDoTransformStride(cmsHTRANSFORM Transform, + const void * InputBuffer, + void * OutputBuffer, + cmsUInt32Number Size, + cmsUInt32Number Stride); + + +CMSAPI void CMSEXPORT cmsSetAlarmCodes(cmsUInt16Number NewAlarm[cmsMAXCHANNELS]); +CMSAPI void CMSEXPORT cmsGetAlarmCodes(cmsUInt16Number NewAlarm[cmsMAXCHANNELS]); + +// Adaptation state for absolute colorimetric intent +CMSAPI cmsFloat64Number CMSEXPORT cmsSetAdaptationState(cmsFloat64Number d); + +// Grab the ContextID from an open transform. Returns NULL if a NULL transform is passed +CMSAPI cmsContext CMSEXPORT cmsGetTransformContextID(cmsHTRANSFORM hTransform); + +// Grab the input/output formats +CMSAPI cmsUInt32Number CMSEXPORT cmsGetTransformInputFormat(cmsHTRANSFORM hTransform); +CMSAPI cmsUInt32Number CMSEXPORT cmsGetTransformOutputFormat(cmsHTRANSFORM hTransform); + +// For backwards compatibility +CMSAPI cmsBool CMSEXPORT cmsChangeBuffersFormat(cmsHTRANSFORM hTransform, + cmsUInt32Number InputFormat, + cmsUInt32Number OutputFormat); + + + +// PostScript ColorRenderingDictionary and ColorSpaceArray ---------------------------------------------------- + +typedef enum { cmsPS_RESOURCE_CSA, cmsPS_RESOURCE_CRD } cmsPSResourceType; + +// lcms2 unified method to access postscript color resources +CMSAPI cmsUInt32Number CMSEXPORT cmsGetPostScriptColorResource(cmsContext ContextID, + cmsPSResourceType Type, + cmsHPROFILE hProfile, + cmsUInt32Number Intent, + cmsUInt32Number dwFlags, + cmsIOHANDLER* io); + +CMSAPI cmsUInt32Number CMSEXPORT cmsGetPostScriptCSA(cmsContext ContextID, cmsHPROFILE hProfile, cmsUInt32Number Intent, cmsUInt32Number dwFlags, void* Buffer, cmsUInt32Number dwBufferLen); +CMSAPI cmsUInt32Number CMSEXPORT cmsGetPostScriptCRD(cmsContext ContextID, cmsHPROFILE hProfile, cmsUInt32Number Intent, cmsUInt32Number dwFlags, void* Buffer, cmsUInt32Number dwBufferLen); + + +// IT8.7 / CGATS.17-200x handling ----------------------------------------------------------------------------- + +CMSAPI cmsHANDLE CMSEXPORT cmsIT8Alloc(cmsContext ContextID); +CMSAPI void CMSEXPORT cmsIT8Free(cmsHANDLE hIT8); + +// Tables +CMSAPI cmsUInt32Number CMSEXPORT cmsIT8TableCount(cmsHANDLE hIT8); +CMSAPI cmsInt32Number CMSEXPORT cmsIT8SetTable(cmsHANDLE hIT8, cmsUInt32Number nTable); + +// Persistence +CMSAPI cmsHANDLE CMSEXPORT cmsIT8LoadFromFile(cmsContext ContextID, const char* cFileName); +CMSAPI cmsHANDLE CMSEXPORT cmsIT8LoadFromMem(cmsContext ContextID, void *Ptr, cmsUInt32Number len); +// CMSAPI cmsHANDLE CMSEXPORT cmsIT8LoadFromIOhandler(cmsContext ContextID, cmsIOHANDLER* io); + +CMSAPI cmsBool CMSEXPORT cmsIT8SaveToFile(cmsHANDLE hIT8, const char* cFileName); +CMSAPI cmsBool CMSEXPORT cmsIT8SaveToMem(cmsHANDLE hIT8, void *MemPtr, cmsUInt32Number* BytesNeeded); + +// Properties +CMSAPI const char* CMSEXPORT cmsIT8GetSheetType(cmsHANDLE hIT8); +CMSAPI cmsBool CMSEXPORT cmsIT8SetSheetType(cmsHANDLE hIT8, const char* Type); + +CMSAPI cmsBool CMSEXPORT cmsIT8SetComment(cmsHANDLE hIT8, const char* cComment); + +CMSAPI cmsBool CMSEXPORT cmsIT8SetPropertyStr(cmsHANDLE hIT8, const char* cProp, const char *Str); +CMSAPI cmsBool CMSEXPORT cmsIT8SetPropertyDbl(cmsHANDLE hIT8, const char* cProp, cmsFloat64Number Val); +CMSAPI cmsBool CMSEXPORT cmsIT8SetPropertyHex(cmsHANDLE hIT8, const char* cProp, cmsUInt32Number Val); +CMSAPI cmsBool CMSEXPORT cmsIT8SetPropertyMulti(cmsHANDLE hIT8, const char* Key, const char* SubKey, const char *Buffer); +CMSAPI cmsBool CMSEXPORT cmsIT8SetPropertyUncooked(cmsHANDLE hIT8, const char* Key, const char* Buffer); + + +CMSAPI const char* CMSEXPORT cmsIT8GetProperty(cmsHANDLE hIT8, const char* cProp); +CMSAPI cmsFloat64Number CMSEXPORT cmsIT8GetPropertyDbl(cmsHANDLE hIT8, const char* cProp); +CMSAPI const char* CMSEXPORT cmsIT8GetPropertyMulti(cmsHANDLE hIT8, const char* Key, const char *SubKey); +CMSAPI cmsUInt32Number CMSEXPORT cmsIT8EnumProperties(cmsHANDLE hIT8, char ***PropertyNames); +CMSAPI cmsUInt32Number CMSEXPORT cmsIT8EnumPropertyMulti(cmsHANDLE hIT8, const char* cProp, const char ***SubpropertyNames); + +// Datasets +CMSAPI const char* CMSEXPORT cmsIT8GetDataRowCol(cmsHANDLE hIT8, int row, int col); +CMSAPI cmsFloat64Number CMSEXPORT cmsIT8GetDataRowColDbl(cmsHANDLE hIT8, int row, int col); + +CMSAPI cmsBool CMSEXPORT cmsIT8SetDataRowCol(cmsHANDLE hIT8, int row, int col, + const char* Val); + +CMSAPI cmsBool CMSEXPORT cmsIT8SetDataRowColDbl(cmsHANDLE hIT8, int row, int col, + cmsFloat64Number Val); + +CMSAPI const char* CMSEXPORT cmsIT8GetData(cmsHANDLE hIT8, const char* cPatch, const char* cSample); + + +CMSAPI cmsFloat64Number CMSEXPORT cmsIT8GetDataDbl(cmsHANDLE hIT8, const char* cPatch, const char* cSample); + +CMSAPI cmsBool CMSEXPORT cmsIT8SetData(cmsHANDLE hIT8, const char* cPatch, + const char* cSample, + const char *Val); + +CMSAPI cmsBool CMSEXPORT cmsIT8SetDataDbl(cmsHANDLE hIT8, const char* cPatch, + const char* cSample, + cmsFloat64Number Val); + +CMSAPI int CMSEXPORT cmsIT8FindDataFormat(cmsHANDLE hIT8, const char* cSample); +CMSAPI cmsBool CMSEXPORT cmsIT8SetDataFormat(cmsHANDLE hIT8, int n, const char *Sample); +CMSAPI int CMSEXPORT cmsIT8EnumDataFormat(cmsHANDLE hIT8, char ***SampleNames); + +CMSAPI const char* CMSEXPORT cmsIT8GetPatchName(cmsHANDLE hIT8, int nPatch, char* buffer); +CMSAPI int CMSEXPORT cmsIT8GetPatchByName(cmsHANDLE hIT8, const char *cPatch); + +// The LABEL extension +CMSAPI int CMSEXPORT cmsIT8SetTableByLabel(cmsHANDLE hIT8, const char* cSet, const char* cField, const char* ExpectedType); + +CMSAPI cmsBool CMSEXPORT cmsIT8SetIndexColumn(cmsHANDLE hIT8, const char* cSample); + +// Formatter for double +CMSAPI void CMSEXPORT cmsIT8DefineDblFormat(cmsHANDLE hIT8, const char* Formatter); + +// Gamut boundary description routines ------------------------------------------------------------------------------ + +CMSAPI cmsHANDLE CMSEXPORT cmsGBDAlloc(cmsContext ContextID); +CMSAPI void CMSEXPORT cmsGBDFree(cmsHANDLE hGBD); +CMSAPI cmsBool CMSEXPORT cmsGDBAddPoint(cmsHANDLE hGBD, const cmsCIELab* Lab); +CMSAPI cmsBool CMSEXPORT cmsGDBCompute(cmsHANDLE hGDB, cmsUInt32Number dwFlags); +CMSAPI cmsBool CMSEXPORT cmsGDBCheckPoint(cmsHANDLE hGBD, const cmsCIELab* Lab); + +// Feature detection ---------------------------------------------------------------------------------------------- + +// Estimate the black point +CMSAPI cmsBool CMSEXPORT cmsDetectBlackPoint(cmsCIEXYZ* BlackPoint, cmsHPROFILE hProfile, cmsUInt32Number Intent, cmsUInt32Number dwFlags); +CMSAPI cmsBool CMSEXPORT cmsDetectDestinationBlackPoint(cmsCIEXYZ* BlackPoint, cmsHPROFILE hProfile, cmsUInt32Number Intent, cmsUInt32Number dwFlags); + +// Estimate total area coverage +CMSAPI cmsFloat64Number CMSEXPORT cmsDetectTAC(cmsHPROFILE hProfile); + + +// Poor man's gamut mapping +CMSAPI cmsBool CMSEXPORT cmsDesaturateLab(cmsCIELab* Lab, + double amax, double amin, + double bmax, double bmin); + +#ifndef CMS_USE_CPP_API +# ifdef __cplusplus + } +# endif +#endif + +#define _lcms2_H +#endif diff --git a/jni/lcms2-2.5/include/lcms2_plugin.h b/jni/lcms2-2.5/include/lcms2_plugin.h new file mode 100644 index 00000000..10e61cbb --- /dev/null +++ b/jni/lcms2-2.5/include/lcms2_plugin.h @@ -0,0 +1,604 @@ +//--------------------------------------------------------------------------------- +// +// Little Color Management System +// Copyright (c) 1998-2011 Marti Maria Saguer +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//--------------------------------------------------------------------------------- +// +// This is the plug-in header file. Normal LittleCMS clients should not use it. +// It is provided for plug-in writters that may want to access the support +// functions to do low level operations. All plug-in related structures +// are defined here. Including this file forces to include the standard API too. + +#ifndef _lcms_plugin_H + +// Deal with Microsoft's attempt at deprecating C standard runtime functions +#ifdef _MSC_VER +# if (_MSC_VER >= 1400) +# ifndef _CRT_SECURE_NO_DEPRECATE +# define _CRT_SECURE_NO_DEPRECATE +# endif +# ifndef _CRT_SECURE_NO_WARNINGS +# define _CRT_SECURE_NO_WARNINGS +# endif +# endif +#endif + +#ifndef _lcms2_H +#include "lcms2.h" +#endif + +// We need some standard C functions. +#include +#include +#include +#include +#include + + +#ifndef CMS_USE_CPP_API +# ifdef __cplusplus +extern "C" { +# endif +#endif + +// Vector & Matrix operations ----------------------------------------------------------------------- + +// Axis of the matrix/array. No specific meaning at all. +#define VX 0 +#define VY 1 +#define VZ 2 + +// Vectors +typedef struct { + cmsFloat64Number n[3]; + + } cmsVEC3; + +// 3x3 Matrix +typedef struct { + cmsVEC3 v[3]; + + } cmsMAT3; + +CMSAPI void CMSEXPORT _cmsVEC3init(cmsVEC3* r, cmsFloat64Number x, cmsFloat64Number y, cmsFloat64Number z); +CMSAPI void CMSEXPORT _cmsVEC3minus(cmsVEC3* r, const cmsVEC3* a, const cmsVEC3* b); +CMSAPI void CMSEXPORT _cmsVEC3cross(cmsVEC3* r, const cmsVEC3* u, const cmsVEC3* v); +CMSAPI cmsFloat64Number CMSEXPORT _cmsVEC3dot(const cmsVEC3* u, const cmsVEC3* v); +CMSAPI cmsFloat64Number CMSEXPORT _cmsVEC3length(const cmsVEC3* a); +CMSAPI cmsFloat64Number CMSEXPORT _cmsVEC3distance(const cmsVEC3* a, const cmsVEC3* b); + +CMSAPI void CMSEXPORT _cmsMAT3identity(cmsMAT3* a); +CMSAPI cmsBool CMSEXPORT _cmsMAT3isIdentity(const cmsMAT3* a); +CMSAPI void CMSEXPORT _cmsMAT3per(cmsMAT3* r, const cmsMAT3* a, const cmsMAT3* b); +CMSAPI cmsBool CMSEXPORT _cmsMAT3inverse(const cmsMAT3* a, cmsMAT3* b); +CMSAPI cmsBool CMSEXPORT _cmsMAT3solve(cmsVEC3* x, cmsMAT3* a, cmsVEC3* b); +CMSAPI void CMSEXPORT _cmsMAT3eval(cmsVEC3* r, const cmsMAT3* a, const cmsVEC3* v); + + +// Error logging ------------------------------------------------------------------------------------- + +CMSAPI void CMSEXPORT cmsSignalError(cmsContext ContextID, cmsUInt32Number ErrorCode, const char *ErrorText, ...); + +// Memory management ---------------------------------------------------------------------------------- + +CMSAPI void* CMSEXPORT _cmsMalloc(cmsContext ContextID, cmsUInt32Number size); +CMSAPI void* CMSEXPORT _cmsMallocZero(cmsContext ContextID, cmsUInt32Number size); +CMSAPI void* CMSEXPORT _cmsCalloc(cmsContext ContextID, cmsUInt32Number num, cmsUInt32Number size); +CMSAPI void* CMSEXPORT _cmsRealloc(cmsContext ContextID, void* Ptr, cmsUInt32Number NewSize); +CMSAPI void CMSEXPORT _cmsFree(cmsContext ContextID, void* Ptr); +CMSAPI void* CMSEXPORT _cmsDupMem(cmsContext ContextID, const void* Org, cmsUInt32Number size); + +// I/O handler ---------------------------------------------------------------------------------- + +struct _cms_io_handler { + + void* stream; // Associated stream, which is implemented differently depending on media. + + cmsContext ContextID; + cmsUInt32Number UsedSpace; + cmsUInt32Number ReportedSize; + char PhysicalFile[cmsMAX_PATH]; + + cmsUInt32Number (* Read)(struct _cms_io_handler* iohandler, void *Buffer, + cmsUInt32Number size, + cmsUInt32Number count); + cmsBool (* Seek)(struct _cms_io_handler* iohandler, cmsUInt32Number offset); + cmsBool (* Close)(struct _cms_io_handler* iohandler); + cmsUInt32Number (* Tell)(struct _cms_io_handler* iohandler); + cmsBool (* Write)(struct _cms_io_handler* iohandler, cmsUInt32Number size, + const void* Buffer); +}; + +// Endianess adjust functions +CMSAPI cmsUInt16Number CMSEXPORT _cmsAdjustEndianess16(cmsUInt16Number Word); +CMSAPI cmsUInt32Number CMSEXPORT _cmsAdjustEndianess32(cmsUInt32Number Value); +CMSAPI void CMSEXPORT _cmsAdjustEndianess64(cmsUInt64Number* Result, cmsUInt64Number* QWord); + +// Helper IO functions +CMSAPI cmsBool CMSEXPORT _cmsReadUInt8Number(cmsIOHANDLER* io, cmsUInt8Number* n); +CMSAPI cmsBool CMSEXPORT _cmsReadUInt16Number(cmsIOHANDLER* io, cmsUInt16Number* n); +CMSAPI cmsBool CMSEXPORT _cmsReadUInt32Number(cmsIOHANDLER* io, cmsUInt32Number* n); +CMSAPI cmsBool CMSEXPORT _cmsReadFloat32Number(cmsIOHANDLER* io, cmsFloat32Number* n); +CMSAPI cmsBool CMSEXPORT _cmsReadUInt64Number(cmsIOHANDLER* io, cmsUInt64Number* n); +CMSAPI cmsBool CMSEXPORT _cmsRead15Fixed16Number(cmsIOHANDLER* io, cmsFloat64Number* n); +CMSAPI cmsBool CMSEXPORT _cmsReadXYZNumber(cmsIOHANDLER* io, cmsCIEXYZ* XYZ); +CMSAPI cmsBool CMSEXPORT _cmsReadUInt16Array(cmsIOHANDLER* io, cmsUInt32Number n, cmsUInt16Number* Array); + +CMSAPI cmsBool CMSEXPORT _cmsWriteUInt8Number(cmsIOHANDLER* io, cmsUInt8Number n); +CMSAPI cmsBool CMSEXPORT _cmsWriteUInt16Number(cmsIOHANDLER* io, cmsUInt16Number n); +CMSAPI cmsBool CMSEXPORT _cmsWriteUInt32Number(cmsIOHANDLER* io, cmsUInt32Number n); +CMSAPI cmsBool CMSEXPORT _cmsWriteFloat32Number(cmsIOHANDLER* io, cmsFloat32Number n); +CMSAPI cmsBool CMSEXPORT _cmsWriteUInt64Number(cmsIOHANDLER* io, cmsUInt64Number* n); +CMSAPI cmsBool CMSEXPORT _cmsWrite15Fixed16Number(cmsIOHANDLER* io, cmsFloat64Number n); +CMSAPI cmsBool CMSEXPORT _cmsWriteXYZNumber(cmsIOHANDLER* io, const cmsCIEXYZ* XYZ); +CMSAPI cmsBool CMSEXPORT _cmsWriteUInt16Array(cmsIOHANDLER* io, cmsUInt32Number n, const cmsUInt16Number* Array); + +// ICC base tag +typedef struct { + cmsTagTypeSignature sig; + cmsInt8Number reserved[4]; + +} _cmsTagBase; + +// Type base helper functions +CMSAPI cmsTagTypeSignature CMSEXPORT _cmsReadTypeBase(cmsIOHANDLER* io); +CMSAPI cmsBool CMSEXPORT _cmsWriteTypeBase(cmsIOHANDLER* io, cmsTagTypeSignature sig); + +// Alignment functions +CMSAPI cmsBool CMSEXPORT _cmsReadAlignment(cmsIOHANDLER* io); +CMSAPI cmsBool CMSEXPORT _cmsWriteAlignment(cmsIOHANDLER* io); + +// To deal with text streams. 2K at most +CMSAPI cmsBool CMSEXPORT _cmsIOPrintf(cmsIOHANDLER* io, const char* frm, ...); + +// Fixed point helper functions +CMSAPI cmsFloat64Number CMSEXPORT _cms8Fixed8toDouble(cmsUInt16Number fixed8); +CMSAPI cmsUInt16Number CMSEXPORT _cmsDoubleTo8Fixed8(cmsFloat64Number val); + +CMSAPI cmsFloat64Number CMSEXPORT _cms15Fixed16toDouble(cmsS15Fixed16Number fix32); +CMSAPI cmsS15Fixed16Number CMSEXPORT _cmsDoubleTo15Fixed16(cmsFloat64Number v); + +// Date/time helper functions +CMSAPI void CMSEXPORT _cmsEncodeDateTimeNumber(cmsDateTimeNumber *Dest, const struct tm *Source); +CMSAPI void CMSEXPORT _cmsDecodeDateTimeNumber(const cmsDateTimeNumber *Source, struct tm *Dest); + +//---------------------------------------------------------------------------------------------------------- + +// Shared callbacks for user data +typedef void (* _cmsFreeUserDataFn)(cmsContext ContextID, void* Data); +typedef void* (* _cmsDupUserDataFn)(cmsContext ContextID, const void* Data); + +//---------------------------------------------------------------------------------------------------------- + +// Plug-in foundation +#define cmsPluginMagicNumber 0x61637070 // 'acpp' + +#define cmsPluginMemHandlerSig 0x6D656D48 // 'memH' +#define cmsPluginInterpolationSig 0x696E7048 // 'inpH' +#define cmsPluginParametricCurveSig 0x70617248 // 'parH' +#define cmsPluginFormattersSig 0x66726D48 // 'frmH +#define cmsPluginTagTypeSig 0x74797048 // 'typH' +#define cmsPluginTagSig 0x74616748 // 'tagH' +#define cmsPluginRenderingIntentSig 0x696E7448 // 'intH' +#define cmsPluginMultiProcessElementSig 0x6D706548 // 'mpeH' +#define cmsPluginOptimizationSig 0x6F707448 // 'optH' +#define cmsPluginTransformSig 0x7A666D48 // 'xfmH' + +typedef struct _cmsPluginBaseStruct { + + cmsUInt32Number Magic; // 'acpp' signature + cmsUInt32Number ExpectedVersion; // Expected version of LittleCMS + cmsUInt32Number Type; // Type of plug-in + struct _cmsPluginBaseStruct* Next; // For multiple plugin definition. NULL for end of list. + +} cmsPluginBase; + +// Maximum number of types in a plugin array +#define MAX_TYPES_IN_LCMS_PLUGIN 20 + +//---------------------------------------------------------------------------------------------------------- + +// Memory handler. Each new plug-in type replaces current behaviour +typedef struct { + + cmsPluginBase base; + + // Required + void * (* MallocPtr)(cmsContext ContextID, cmsUInt32Number size); + void (* FreePtr)(cmsContext ContextID, void *Ptr); + void * (* ReallocPtr)(cmsContext ContextID, void* Ptr, cmsUInt32Number NewSize); + + // Optional + void * (* MallocZeroPtr)(cmsContext ContextID, cmsUInt32Number size); + void * (* CallocPtr)(cmsContext ContextID, cmsUInt32Number num, cmsUInt32Number size); + void * (* DupPtr)(cmsContext ContextID, const void* Org, cmsUInt32Number size); + +} cmsPluginMemHandler; + + +// ------------------------------------------------------------------------------------------------------------------ + +// Interpolation. 16 bits and floating point versions. +struct _cms_interp_struc; + +// Interpolation callbacks + +// 16 bits forward interpolation. This function performs precision-limited linear interpolation +// and is supposed to be quite fast. Implementation may be tetrahedral or trilinear, and plug-ins may +// choose to implement any other interpolation algorithm. +typedef void (* _cmsInterpFn16)(register const cmsUInt16Number Input[], + register cmsUInt16Number Output[], + register const struct _cms_interp_struc* p); + +// Floating point forward interpolation. Full precision interpolation using floats. This is not a +// time critical function. Implementation may be tetrahedral or trilinear, and plug-ins may +// choose to implement any other interpolation algorithm. +typedef void (* _cmsInterpFnFloat)(cmsFloat32Number const Input[], + cmsFloat32Number Output[], + const struct _cms_interp_struc* p); + + + +// This type holds a pointer to an interpolator that can be either 16 bits or float +typedef union { + _cmsInterpFn16 Lerp16; // Forward interpolation in 16 bits + _cmsInterpFnFloat LerpFloat; // Forward interpolation in floating point +} cmsInterpFunction; + +// Flags for interpolator selection +#define CMS_LERP_FLAGS_16BITS 0x0000 // The default +#define CMS_LERP_FLAGS_FLOAT 0x0001 // Requires different implementation +#define CMS_LERP_FLAGS_TRILINEAR 0x0100 // Hint only + + +#define MAX_INPUT_DIMENSIONS 8 + +typedef struct _cms_interp_struc { // Used on all interpolations. Supplied by lcms2 when calling the interpolation function + + cmsContext ContextID; // The calling thread + + cmsUInt32Number dwFlags; // Keep original flags + cmsUInt32Number nInputs; // != 1 only in 3D interpolation + cmsUInt32Number nOutputs; // != 1 only in 3D interpolation + + cmsUInt32Number nSamples[MAX_INPUT_DIMENSIONS]; // Valid on all kinds of tables + cmsUInt32Number Domain[MAX_INPUT_DIMENSIONS]; // Domain = nSamples - 1 + + cmsUInt32Number opta[MAX_INPUT_DIMENSIONS]; // Optimization for 3D CLUT. This is the number of nodes premultiplied for each + // dimension. For example, in 7 nodes, 7, 7^2 , 7^3, 7^4, etc. On non-regular + // Samplings may vary according of the number of nodes for each dimension. + + const void *Table; // Points to the actual interpolation table + cmsInterpFunction Interpolation; // Points to the function to do the interpolation + + } cmsInterpParams; + +// Interpolators factory +typedef cmsInterpFunction (* cmsInterpFnFactory)(cmsUInt32Number nInputChannels, cmsUInt32Number nOutputChannels, cmsUInt32Number dwFlags); + +// The plug-in +typedef struct { + cmsPluginBase base; + + // Points to a user-supplied function which implements the factory + cmsInterpFnFactory InterpolatorsFactory; + +} cmsPluginInterpolation; + +//---------------------------------------------------------------------------------------------------------- + +// Parametric curves. A negative type means same function but analytically inverted. Max. number of params is 10 + +// Evaluator callback for user-suplied parametric curves. May implement more than one type +typedef cmsFloat64Number (* cmsParametricCurveEvaluator)(cmsInt32Number Type, const cmsFloat64Number Params[10], cmsFloat64Number R); + +// Plug-in may implement an arbitrary number of parametric curves +typedef struct { + cmsPluginBase base; + + cmsUInt32Number nFunctions; // Number of supported functions + cmsUInt32Number FunctionTypes[MAX_TYPES_IN_LCMS_PLUGIN]; // The identification types + cmsUInt32Number ParameterCount[MAX_TYPES_IN_LCMS_PLUGIN]; // Number of parameters for each function + + cmsParametricCurveEvaluator Evaluator; // The evaluator + +} cmsPluginParametricCurves; +//---------------------------------------------------------------------------------------------------------- + +// Formatters. This plug-in adds new handlers, replacing them if they already exist. Formatters dealing with +// cmsFloat32Number (bps = 4) or double (bps = 0) types are requested via FormatterFloat callback. Others come across +// Formatter16 callback + +struct _cmstransform_struct; + +typedef cmsUInt8Number* (* cmsFormatter16)(register struct _cmstransform_struct* CMMcargo, + register cmsUInt16Number Values[], + register cmsUInt8Number* Buffer, + register cmsUInt32Number Stride); + +typedef cmsUInt8Number* (* cmsFormatterFloat)(struct _cmstransform_struct* CMMcargo, + cmsFloat32Number Values[], + cmsUInt8Number* Buffer, + cmsUInt32Number Stride); + +// This type holds a pointer to a formatter that can be either 16 bits or cmsFloat32Number +typedef union { + cmsFormatter16 Fmt16; + cmsFormatterFloat FmtFloat; + +} cmsFormatter; + +#define CMS_PACK_FLAGS_16BITS 0x0000 +#define CMS_PACK_FLAGS_FLOAT 0x0001 + +typedef enum { cmsFormatterInput=0, cmsFormatterOutput=1 } cmsFormatterDirection; + +typedef cmsFormatter (* cmsFormatterFactory)(cmsUInt32Number Type, // Specific type, i.e. TYPE_RGB_8 + cmsFormatterDirection Dir, + cmsUInt32Number dwFlags); // precision + +// Plug-in may implement an arbitrary number of formatters +typedef struct { + cmsPluginBase base; + cmsFormatterFactory FormattersFactory; + +} cmsPluginFormatters; + +//---------------------------------------------------------------------------------------------------------- + +// Tag type handler. Each type is free to return anything it wants, and it is up to the caller to +// know in advance what is the type contained in the tag. +typedef struct _cms_typehandler_struct { + + cmsTagTypeSignature Signature; // The signature of the type + + // Allocates and reads items + void * (* ReadPtr)(struct _cms_typehandler_struct* self, + cmsIOHANDLER* io, + cmsUInt32Number* nItems, + cmsUInt32Number SizeOfTag); + + // Writes n Items + cmsBool (* WritePtr)(struct _cms_typehandler_struct* self, + cmsIOHANDLER* io, + void* Ptr, + cmsUInt32Number nItems); + + // Duplicate an item or array of items + void* (* DupPtr)(struct _cms_typehandler_struct* self, + const void *Ptr, + cmsUInt32Number n); + + // Free all resources + void (* FreePtr)(struct _cms_typehandler_struct* self, + void *Ptr); + + // Additional parameters used by the calling thread + cmsContext ContextID; + cmsUInt32Number ICCVersion; + +} cmsTagTypeHandler; + +// Each plug-in implements a single type +typedef struct { + cmsPluginBase base; + cmsTagTypeHandler Handler; + +} cmsPluginTagType; + +//---------------------------------------------------------------------------------------------------------- + +// This is the tag plugin, which identifies tags. For writing, a pointer to function is provided. +// This function should return the desired type for this tag, given the version of profile +// and the data being serialized. +typedef struct { + + cmsUInt32Number ElemCount; // If this tag needs an array, how many elements should keep + + // For reading. + cmsUInt32Number nSupportedTypes; // In how many types this tag can come (MAX_TYPES_IN_LCMS_PLUGIN maximum) + cmsTagTypeSignature SupportedTypes[MAX_TYPES_IN_LCMS_PLUGIN]; + + // For writting + cmsTagTypeSignature (* DecideType)(cmsFloat64Number ICCVersion, const void *Data); + +} cmsTagDescriptor; + +// Plug-in implements a single tag +typedef struct { + cmsPluginBase base; + + cmsTagSignature Signature; + cmsTagDescriptor Descriptor; + +} cmsPluginTag; + +//---------------------------------------------------------------------------------------------------------- + +// Custom intents. This function should join all profiles specified in the array in +// a single LUT. Any custom intent in the chain redirects to custom function. If more than +// one custom intent is found, the one located first is invoked. Usually users should use only one +// custom intent, so mixing custom intents in same multiprofile transform is not supported. + +typedef cmsPipeline* (* cmsIntentFn)( cmsContext ContextID, + cmsUInt32Number nProfiles, + cmsUInt32Number Intents[], + cmsHPROFILE hProfiles[], + cmsBool BPC[], + cmsFloat64Number AdaptationStates[], + cmsUInt32Number dwFlags); + + +// Each plug-in defines a single intent number. +typedef struct { + cmsPluginBase base; + cmsUInt32Number Intent; + cmsIntentFn Link; + char Description[256]; + +} cmsPluginRenderingIntent; + + +// The default ICC intents (perceptual, saturation, rel.col and abs.col) +CMSAPI cmsPipeline* CMSEXPORT _cmsDefaultICCintents(cmsContext ContextID, + cmsUInt32Number nProfiles, + cmsUInt32Number Intents[], + cmsHPROFILE hProfiles[], + cmsBool BPC[], + cmsFloat64Number AdaptationStates[], + cmsUInt32Number dwFlags); + + +//---------------------------------------------------------------------------------------------------------- + +// Pipelines, Multi Process Elements. + +typedef void (* _cmsStageEvalFn) (const cmsFloat32Number In[], cmsFloat32Number Out[], const cmsStage* mpe); +typedef void*(* _cmsStageDupElemFn) (cmsStage* mpe); +typedef void (* _cmsStageFreeElemFn) (cmsStage* mpe); + + +// This function allocates a generic MPE +CMSAPI cmsStage* CMSEXPORT _cmsStageAllocPlaceholder(cmsContext ContextID, + cmsStageSignature Type, + cmsUInt32Number InputChannels, + cmsUInt32Number OutputChannels, + _cmsStageEvalFn EvalPtr, // Points to fn that evaluates the element (always in floating point) + _cmsStageDupElemFn DupElemPtr, // Points to a fn that duplicates the stage + _cmsStageFreeElemFn FreePtr, // Points to a fn that sets the element free + void* Data); // A generic pointer to whatever memory needed by the element +typedef struct { + cmsPluginBase base; + cmsTagTypeHandler Handler; + +} cmsPluginMultiProcessElement; + + +// Data kept in "Element" member of cmsStage + +// Curves +typedef struct { + cmsUInt32Number nCurves; + cmsToneCurve** TheCurves; + +} _cmsStageToneCurvesData; + +// Matrix +typedef struct { + cmsFloat64Number* Double; // floating point for the matrix + cmsFloat64Number* Offset; // The offset + +} _cmsStageMatrixData; + +// CLUT +typedef struct { + + union { // Can have only one of both representations at same time + cmsUInt16Number* T; // Points to the table 16 bits table + cmsFloat32Number* TFloat; // Points to the cmsFloat32Number table + + } Tab; + + cmsInterpParams* Params; + cmsUInt32Number nEntries; + cmsBool HasFloatValues; + +} _cmsStageCLutData; + + +//---------------------------------------------------------------------------------------------------------- +// Optimization. Using this plug-in, additional optimization strategies may be implemented. +// The function should return TRUE if any optimization is done on the LUT, this terminates +// the optimization search. Or FALSE if it is unable to optimize and want to give a chance +// to the rest of optimizers. + +typedef void (* _cmsOPTeval16Fn)(register const cmsUInt16Number In[], + register cmsUInt16Number Out[], + register const void* Data); + + +typedef cmsBool (* _cmsOPToptimizeFn)(cmsPipeline** Lut, + cmsUInt32Number Intent, + cmsUInt32Number* InputFormat, + cmsUInt32Number* OutputFormat, + cmsUInt32Number* dwFlags); + +// This function may be used to set the optional evaluator and a block of private data. If private data is being used, an optional +// duplicator and free functions should also be specified in order to duplicate the LUT construct. Use NULL to inhibit such functionality. + +CMSAPI void CMSEXPORT _cmsPipelineSetOptimizationParameters(cmsPipeline* Lut, + _cmsOPTeval16Fn Eval16, + void* PrivateData, + _cmsFreeUserDataFn FreePrivateDataFn, + _cmsDupUserDataFn DupPrivateDataFn); + +typedef struct { + cmsPluginBase base; + + // Optimize entry point + _cmsOPToptimizeFn OptimizePtr; + +} cmsPluginOptimization; + +//---------------------------------------------------------------------------------------------------------- +// Full xform +typedef void (* _cmsTransformFn)(struct _cmstransform_struct *CMMcargo, + const void* InputBuffer, + void* OutputBuffer, + cmsUInt32Number Size, + cmsUInt32Number Stride); + +typedef cmsBool (* _cmsTransformFactory)(_cmsTransformFn* xform, + void** UserData, + _cmsFreeUserDataFn* FreePrivateDataFn, + cmsPipeline** Lut, + cmsUInt32Number* InputFormat, + cmsUInt32Number* OutputFormat, + cmsUInt32Number* dwFlags); + + +// Retrieve user data as specified by the factory +CMSAPI void CMSEXPORT _cmsSetTransformUserData(struct _cmstransform_struct *CMMcargo, void* ptr, _cmsFreeUserDataFn FreePrivateDataFn); +CMSAPI void * CMSEXPORT _cmsGetTransformUserData(struct _cmstransform_struct *CMMcargo); + + +// Retrieve formatters +CMSAPI void CMSEXPORT _cmsGetTransformFormatters16 (struct _cmstransform_struct *CMMcargo, cmsFormatter16* FromInput, cmsFormatter16* ToOutput); +CMSAPI void CMSEXPORT _cmsGetTransformFormattersFloat(struct _cmstransform_struct *CMMcargo, cmsFormatterFloat* FromInput, cmsFormatterFloat* ToOutput); + +typedef struct { + cmsPluginBase base; + + // Transform entry point + _cmsTransformFactory Factory; + +} cmsPluginTransform; + + +#ifndef CMS_USE_CPP_API +# ifdef __cplusplus + } +# endif +#endif + +#define _lcms_plugin_H +#endif diff --git a/jni/lcms2-2.5/install-sh b/jni/lcms2-2.5/install-sh new file mode 100755 index 00000000..6781b987 --- /dev/null +++ b/jni/lcms2-2.5/install-sh @@ -0,0 +1,520 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2009-04-28.21; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. + +nl=' +' +IFS=" "" $nl" + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit=${DOITPROG-} +if test -z "$doit"; then + doit_exec=exec +else + doit_exec=$doit +fi + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_glob='?' +initialize_posix_glob=' + test "$posix_glob" != "?" || { + if (set -f) 2>/dev/null; then + posix_glob= + else + posix_glob=: + fi + } +' + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +no_target_directory= + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *' '* | *' +'* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -t) dst_arg=$2 + shift;; + + -T) no_target_directory=true;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call `install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + trap '(exit $?); exit' 1 2 13 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names starting with `-'. + case $src in + -*) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + + dst=$dst_arg + # Protect names starting with `-'. + case $dst in + -*) dst=./$dst;; + esac + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + # Prefer dirname, but fall back on a substitute if dirname fails. + dstdir=` + (dirname "$dst") 2>/dev/null || + expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$dst" : 'X\(//\)[^/]' \| \ + X"$dst" : 'X\(//\)$' \| \ + X"$dst" : 'X\(/\)' \| . 2>/dev/null || + echo X"$dst" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q' + ` + + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + + if (umask $mkdir_umask && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writeable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + ls_ld_tmpdir=`ls -ld "$tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/d" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + -*) prefix='./';; + *) prefix='';; + esac + + eval "$initialize_posix_glob" + + oIFS=$IFS + IFS=/ + $posix_glob set -f + set fnord $dstdir + shift + $posix_glob set +f + IFS=$oIFS + + prefixes= + + for d + do + test -z "$d" && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + + eval "$initialize_posix_glob" && + $posix_glob set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + $posix_glob set +f && + + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/jni/lcms2-2.5/lcms2.pc.in b/jni/lcms2-2.5/lcms2.pc.in new file mode 100644 index 00000000..b715f59a --- /dev/null +++ b/jni/lcms2-2.5/lcms2.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: @PACKAGE@ +Description: LCMS Color Management Library +Version: @VERSION@ +Libs: -L${libdir} -llcms2 +Libs.private: @LIB_MATH@ +Cflags: -I${includedir} diff --git a/jni/lcms2-2.5/missing b/jni/lcms2-2.5/missing new file mode 100755 index 00000000..64b5f901 --- /dev/null +++ b/jni/lcms2-2.5/missing @@ -0,0 +1,353 @@ +#! /bin/sh +# Common stub for a few missing GNU programs while installing. + +scriptversion=2004-09-07.08 + +# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004 +# Free Software Foundation, Inc. +# Originally by Fran,cois Pinard , 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 +fi + +run=: + +# In the cases where this matters, `missing' is being run in the +# srcdir already. +if test -f configure.ac; then + configure_ac=configure.ac +else + configure_ac=configure.in +fi + +msg="missing on your system" + +case "$1" in +--run) + # Try to run requested program, and just exit if it succeeds. + run= + shift + "$@" && exit 0 + # Exit code 63 means version mismatch. This often happens + # when the user try to use an ancient version of a tool on + # a file that requires a minimum version. In this case we + # we should proceed has if the program had been absent, or + # if --run hadn't been passed. + if test $? = 63; then + run=: + msg="probably too old" + fi + ;; + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an +error status if there is no known handling for PROGRAM. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + --run try to run the given command, and emulate it if it fails + +Supported PROGRAM values: + aclocal touch file \`aclocal.m4' + autoconf touch file \`configure' + autoheader touch file \`config.h.in' + automake touch all \`Makefile.in' files + bison create \`y.tab.[ch]', if possible, from existing .[ch] + flex create \`lex.yy.c', if possible, from existing .c + help2man touch the output file + lex create \`lex.yy.c', if possible, from existing .c + makeinfo touch the output file + tar try tar, gnutar, gtar, then tar without non-portable flags + yacc create \`y.tab.[ch]', if possible, from existing .[ch] + +Send bug reports to ." + exit 0 + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing $scriptversion (GNU Automake)" + exit 0 + ;; + + -*) + echo 1>&2 "$0: Unknown \`$1' option" + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 + ;; + +esac + +# Now exit if we have it, but it failed. Also exit now if we +# don't have it and --version was passed (most likely to detect +# the program). +case "$1" in + lex|yacc) + # Not GNU programs, they don't have --version. + ;; + + tar) + if test -n "$run"; then + echo 1>&2 "ERROR: \`tar' requires --run" + exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + exit 1 + fi + ;; + + *) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + # Could not run --version or --help. This is probably someone + # running `$TOOL --version' or `$TOOL --help' to check whether + # $TOOL exists and not knowing $TOOL uses missing. + exit 1 + fi + ;; +esac + +# If it does not exist, or fails to run (possibly an outdated version), +# try to emulate it. +case "$1" in + aclocal*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acinclude.m4' or \`${configure_ac}'. You might want + to install the \`Automake' and \`Perl' packages. Grab them from + any GNU archive site." + touch aclocal.m4 + ;; + + autoconf) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`${configure_ac}'. You might want to install the + \`Autoconf' and \`GNU m4' packages. Grab them from any GNU + archive site." + touch configure + ;; + + autoheader) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acconfig.h' or \`${configure_ac}'. You might want + to install the \`Autoconf' and \`GNU m4' packages. Grab them + from any GNU archive site." + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` + test -z "$files" && files="config.h" + touch_files= + for f in $files; do + case "$f" in + *:*) touch_files="$touch_files "`echo "$f" | + sed -e 's/^[^:]*://' -e 's/:.*//'`;; + *) touch_files="$touch_files $f.in";; + esac + done + touch $touch_files + ;; + + automake*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. + You might want to install the \`Automake' and \`Perl' packages. + Grab them from any GNU archive site." + find . -type f -name Makefile.am -print | + sed 's/\.am$/.in/' | + while read f; do touch "$f"; done + ;; + + autom4te) + echo 1>&2 "\ +WARNING: \`$1' is needed, but is $msg. + You might have modified some files without having the + proper tools for further handling them. + You can get \`$1' as part of \`Autoconf' from any GNU + archive site." + + file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'` + test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'` + if test -f "$file"; then + touch $file + else + test -z "$file" || exec >$file + echo "#! /bin/sh" + echo "# Created by GNU Automake missing as a replacement of" + echo "# $ $@" + echo "exit 0" + chmod +x $file + exit 1 + fi + ;; + + bison|yacc) + echo 1>&2 "\ +WARNING: \`$1' $msg. You should only need it if + you modified a \`.y' file. You may need the \`Bison' package + in order for those modifications to take effect. You can get + \`Bison' from any GNU archive site." + rm -f y.tab.c y.tab.h + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.y) + SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.c + fi + SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.h + fi + ;; + esac + fi + if [ ! -f y.tab.h ]; then + echo >y.tab.h + fi + if [ ! -f y.tab.c ]; then + echo 'main() { return 0; }' >y.tab.c + fi + ;; + + lex|flex) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.l' file. You may need the \`Flex' package + in order for those modifications to take effect. You can get + \`Flex' from any GNU archive site." + rm -f lex.yy.c + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.l) + SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" lex.yy.c + fi + ;; + esac + fi + if [ ! -f lex.yy.c ]; then + echo 'main() { return 0; }' >lex.yy.c + fi + ;; + + help2man) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a dependency of a manual page. You may need the + \`Help2man' package in order for those modifications to take + effect. You can get \`Help2man' from any GNU archive site." + + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'` + fi + if [ -f "$file" ]; then + touch $file + else + test -z "$file" || exec >$file + echo ".ab help2man is required to generate this page" + exit 1 + fi + ;; + + makeinfo) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.texi' or \`.texinfo' file, or any other file + indirectly affecting the aspect of the manual. The spurious + call might also be the consequence of using a buggy \`make' (AIX, + DU, IRIX). You might want to install the \`Texinfo' package or + the \`GNU make' package. Grab either from any GNU archive site." + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` + file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` + fi + touch $file + ;; + + tar) + shift + + # We have already tried tar in the generic part. + # Look for gnutar/gtar before invocation to avoid ugly error + # messages. + if (gnutar --version > /dev/null 2>&1); then + gnutar "$@" && exit 0 + fi + if (gtar --version > /dev/null 2>&1); then + gtar "$@" && exit 0 + fi + firstarg="$1" + if shift; then + case "$firstarg" in + *o*) + firstarg=`echo "$firstarg" | sed s/o//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + case "$firstarg" in + *h*) + firstarg=`echo "$firstarg" | sed s/h//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + fi + + echo 1>&2 "\ +WARNING: I can't seem to be able to run \`tar' with the given arguments. + You may want to install GNU tar or Free paxutils, or check the + command line arguments." + exit 1 + ;; + + *) + echo 1>&2 "\ +WARNING: \`$1' is needed, and is $msg. + You might have modified some files without having the + proper tools for further handling them. Check the \`README' file, + it often tells you about the needed prerequisites for installing + this package. You may also peek at any GNU archive site, in case + some other package would contain this missing \`$1' program." + exit 1 + ;; +esac + +exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/jni/lcms2-2.5/src/Makefile.am b/jni/lcms2-2.5/src/Makefile.am new file mode 100644 index 00000000..0e49793a --- /dev/null +++ b/jni/lcms2-2.5/src/Makefile.am @@ -0,0 +1,31 @@ +# +# Makefile for building lcms 2 library +# + +# Don't require all the GNU mandated files +AUTOMAKE_OPTIONS = 1.7 foreign + +# CFLAGS = -pedantic -Wall -std=c99 -O3 + +includedir = ${prefix}/include + +# Shared libraries built in this directory +lib_LTLIBRARIES = liblcms2.la + +LIBRARY_CURRENT = @LIBRARY_CURRENT@ +LIBRARY_REVISION = @LIBRARY_REVISION@ +LIBRARY_AGE = @LIBRARY_AGE@ + +INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include + +liblcms2_la_LDFLAGS = -no-undefined \ + -version-info $(LIBRARY_CURRENT):$(LIBRARY_REVISION):$(LIBRARY_AGE) + +liblcms2_la_LIBADD = $(LCMS_LIB_DEPLIBS) + +liblcms2_la_SOURCES = \ + cmscnvrt.c cmserr.c cmsgamma.c cmsgmt.c cmsintrp.c cmsio0.c cmsio1.c cmslut.c \ + cmsplugin.c cmssm.c cmsmd5.c cmsmtrx.c cmspack.c cmspcs.c cmswtpnt.c cmsxform.c \ + cmssamp.c cmsnamed.c cmscam02.c cmsvirt.c cmstypes.c cmscgats.c cmsps2.c cmsopt.c \ + cmshalf.c lcms2_internal.h + diff --git a/jni/lcms2-2.5/src/Makefile.in b/jni/lcms2-2.5/src/Makefile.in new file mode 100644 index 00000000..158fc014 --- /dev/null +++ b/jni/lcms2-2.5/src/Makefile.in @@ -0,0 +1,618 @@ +# Makefile.in generated by automake 1.11.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# +# Makefile for building lcms 2 library +# + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(libdir)" +LTLIBRARIES = $(lib_LTLIBRARIES) +am__DEPENDENCIES_1 = +liblcms2_la_DEPENDENCIES = $(am__DEPENDENCIES_1) +am_liblcms2_la_OBJECTS = cmscnvrt.lo cmserr.lo cmsgamma.lo cmsgmt.lo \ + cmsintrp.lo cmsio0.lo cmsio1.lo cmslut.lo cmsplugin.lo \ + cmssm.lo cmsmd5.lo cmsmtrx.lo cmspack.lo cmspcs.lo cmswtpnt.lo \ + cmsxform.lo cmssamp.lo cmsnamed.lo cmscam02.lo cmsvirt.lo \ + cmstypes.lo cmscgats.lo cmsps2.lo cmsopt.lo cmshalf.lo +liblcms2_la_OBJECTS = $(am_liblcms2_la_OBJECTS) +liblcms2_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(liblcms2_la_LDFLAGS) $(LDFLAGS) -o $@ +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(liblcms2_la_SOURCES) +DIST_SOURCES = $(liblcms2_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +JPEGICC_DEPLIBS = @JPEGICC_DEPLIBS@ +LCMS_LIB_DEPLIBS = @LCMS_LIB_DEPLIBS@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBRARY_AGE = @LIBRARY_AGE@ +LIBRARY_CURRENT = @LIBRARY_CURRENT@ +LIBRARY_REVISION = @LIBRARY_REVISION@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBTOOL_DEPS = @LIBTOOL_DEPS@ +LIB_JPEG = @LIB_JPEG@ +LIB_MATH = @LIB_MATH@ +LIB_TIFF = @LIB_TIFF@ +LIB_ZLIB = @LIB_ZLIB@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +TIFFICC_DEPLIBS = @TIFFICC_DEPLIBS@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ + +# CFLAGS = -pedantic -Wall -std=c99 -O3 +includedir = ${prefix}/include +infodir = @infodir@ +inline = @inline@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ + +# Don't require all the GNU mandated files +AUTOMAKE_OPTIONS = 1.7 foreign + +# Shared libraries built in this directory +lib_LTLIBRARIES = liblcms2.la +INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include +liblcms2_la_LDFLAGS = -no-undefined \ + -version-info $(LIBRARY_CURRENT):$(LIBRARY_REVISION):$(LIBRARY_AGE) + +liblcms2_la_LIBADD = $(LCMS_LIB_DEPLIBS) +liblcms2_la_SOURCES = \ + cmscnvrt.c cmserr.c cmsgamma.c cmsgmt.c cmsintrp.c cmsio0.c cmsio1.c cmslut.c \ + cmsplugin.c cmssm.c cmsmd5.c cmsmtrx.c cmspack.c cmspcs.c cmswtpnt.c cmsxform.c \ + cmssamp.c cmsnamed.c cmscam02.c cmsvirt.c cmstypes.c cmscgats.c cmsps2.c cmsopt.c \ + cmshalf.c lcms2_internal.h + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +liblcms2.la: $(liblcms2_la_OBJECTS) $(liblcms2_la_DEPENDENCIES) $(EXTRA_liblcms2_la_DEPENDENCIES) + $(liblcms2_la_LINK) -rpath $(libdir) $(liblcms2_la_OBJECTS) $(liblcms2_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmscam02.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmscgats.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmscnvrt.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmserr.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmsgamma.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmsgmt.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmshalf.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmsintrp.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmsio0.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmsio1.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmslut.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmsmd5.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmsmtrx.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmsnamed.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmsopt.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmspack.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmspcs.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmsplugin.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmsps2.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmssamp.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmssm.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmstypes.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmsvirt.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmswtpnt.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmsxform.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(libdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-libLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-libLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libLTLIBRARIES clean-libtool ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am \ + install-libLTLIBRARIES install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-libLTLIBRARIES + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/jni/lcms2-2.5/src/cmscam02.c b/jni/lcms2-2.5/src/cmscam02.c new file mode 100644 index 00000000..6aeed1e1 --- /dev/null +++ b/jni/lcms2-2.5/src/cmscam02.c @@ -0,0 +1,483 @@ +//--------------------------------------------------------------------------------- +// +// Little Color Management System +// Copyright (c) 1998-2012 Marti Maria Saguer +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//--------------------------------------------------------------------------------- +// + +#include "lcms2_internal.h" + +// CIECAM 02 appearance model. Many thanks to Jordi Vilar for the debugging. + +// ---------- Implementation -------------------------------------------- + +typedef struct { + + cmsFloat64Number XYZ[3]; + cmsFloat64Number RGB[3]; + cmsFloat64Number RGBc[3]; + cmsFloat64Number RGBp[3]; + cmsFloat64Number RGBpa[3]; + cmsFloat64Number a, b, h, e, H, A, J, Q, s, t, C, M; + cmsFloat64Number abC[2]; + cmsFloat64Number abs[2]; + cmsFloat64Number abM[2]; + +} CAM02COLOR; + +typedef struct { + + CAM02COLOR adoptedWhite; + cmsFloat64Number LA, Yb; + cmsFloat64Number F, c, Nc; + cmsUInt32Number surround; + cmsFloat64Number n, Nbb, Ncb, z, FL, D; + + cmsContext ContextID; + +} cmsCIECAM02; + + +static +cmsFloat64Number compute_n(cmsCIECAM02* pMod) +{ + return (pMod -> Yb / pMod -> adoptedWhite.XYZ[1]); +} + +static +cmsFloat64Number compute_z(cmsCIECAM02* pMod) +{ + return (1.48 + pow(pMod -> n, 0.5)); +} + +static +cmsFloat64Number computeNbb(cmsCIECAM02* pMod) +{ + return (0.725 * pow((1.0 / pMod -> n), 0.2)); +} + +static +cmsFloat64Number computeFL(cmsCIECAM02* pMod) +{ + cmsFloat64Number k, FL; + + k = 1.0 / ((5.0 * pMod->LA) + 1.0); + FL = 0.2 * pow(k, 4.0) * (5.0 * pMod->LA) + 0.1 * + (pow((1.0 - pow(k, 4.0)), 2.0)) * + (pow((5.0 * pMod->LA), (1.0 / 3.0))); + + return FL; +} + +static +cmsFloat64Number computeD(cmsCIECAM02* pMod) +{ + cmsFloat64Number D; + + D = pMod->F - (1.0/3.6)*(exp(((-pMod ->LA-42) / 92.0))); + + return D; +} + + +static +CAM02COLOR XYZtoCAT02(CAM02COLOR clr) +{ + clr.RGB[0] = (clr.XYZ[0] * 0.7328) + (clr.XYZ[1] * 0.4296) + (clr.XYZ[2] * -0.1624); + clr.RGB[1] = (clr.XYZ[0] * -0.7036) + (clr.XYZ[1] * 1.6975) + (clr.XYZ[2] * 0.0061); + clr.RGB[2] = (clr.XYZ[0] * 0.0030) + (clr.XYZ[1] * 0.0136) + (clr.XYZ[2] * 0.9834); + + return clr; +} + +static +CAM02COLOR ChromaticAdaptation(CAM02COLOR clr, cmsCIECAM02* pMod) +{ + cmsUInt32Number i; + + for (i = 0; i < 3; i++) { + clr.RGBc[i] = ((pMod -> adoptedWhite.XYZ[1] * + (pMod->D / pMod -> adoptedWhite.RGB[i])) + + (1.0 - pMod->D)) * clr.RGB[i]; + } + + return clr; +} + + +static +CAM02COLOR CAT02toHPE(CAM02COLOR clr) +{ + cmsFloat64Number M[9]; + + M[0] =(( 0.38971 * 1.096124) + (0.68898 * 0.454369) + (-0.07868 * -0.009628)); + M[1] =(( 0.38971 * -0.278869) + (0.68898 * 0.473533) + (-0.07868 * -0.005698)); + M[2] =(( 0.38971 * 0.182745) + (0.68898 * 0.072098) + (-0.07868 * 1.015326)); + M[3] =((-0.22981 * 1.096124) + (1.18340 * 0.454369) + ( 0.04641 * -0.009628)); + M[4] =((-0.22981 * -0.278869) + (1.18340 * 0.473533) + ( 0.04641 * -0.005698)); + M[5] =((-0.22981 * 0.182745) + (1.18340 * 0.072098) + ( 0.04641 * 1.015326)); + M[6] =(-0.009628); + M[7] =(-0.005698); + M[8] =( 1.015326); + + clr.RGBp[0] = (clr.RGBc[0] * M[0]) + (clr.RGBc[1] * M[1]) + (clr.RGBc[2] * M[2]); + clr.RGBp[1] = (clr.RGBc[0] * M[3]) + (clr.RGBc[1] * M[4]) + (clr.RGBc[2] * M[5]); + clr.RGBp[2] = (clr.RGBc[0] * M[6]) + (clr.RGBc[1] * M[7]) + (clr.RGBc[2] * M[8]); + + return clr; +} + +static +CAM02COLOR NonlinearCompression(CAM02COLOR clr, cmsCIECAM02* pMod) +{ + cmsUInt32Number i; + cmsFloat64Number temp; + + for (i = 0; i < 3; i++) { + if (clr.RGBp[i] < 0) { + + temp = pow((-1.0 * pMod->FL * clr.RGBp[i] / 100.0), 0.42); + clr.RGBpa[i] = (-1.0 * 400.0 * temp) / (temp + 27.13) + 0.1; + } + else { + temp = pow((pMod->FL * clr.RGBp[i] / 100.0), 0.42); + clr.RGBpa[i] = (400.0 * temp) / (temp + 27.13) + 0.1; + } + } + + clr.A = (((2.0 * clr.RGBpa[0]) + clr.RGBpa[1] + + (clr.RGBpa[2] / 20.0)) - 0.305) * pMod->Nbb; + + return clr; +} + +static +CAM02COLOR ComputeCorrelates(CAM02COLOR clr, cmsCIECAM02* pMod) +{ + cmsFloat64Number a, b, temp, e, t, r2d, d2r; + + a = clr.RGBpa[0] - (12.0 * clr.RGBpa[1] / 11.0) + (clr.RGBpa[2] / 11.0); + b = (clr.RGBpa[0] + clr.RGBpa[1] - (2.0 * clr.RGBpa[2])) / 9.0; + + r2d = (180.0 / 3.141592654); + if (a == 0) { + if (b == 0) clr.h = 0; + else if (b > 0) clr.h = 90; + else clr.h = 270; + } + else if (a > 0) { + temp = b / a; + if (b > 0) clr.h = (r2d * atan(temp)); + else if (b == 0) clr.h = 0; + else clr.h = (r2d * atan(temp)) + 360; + } + else { + temp = b / a; + clr.h = (r2d * atan(temp)) + 180; + } + + d2r = (3.141592654 / 180.0); + e = ((12500.0 / 13.0) * pMod->Nc * pMod->Ncb) * + (cos((clr.h * d2r + 2.0)) + 3.8); + + if (clr.h < 20.14) { + temp = ((clr.h + 122.47)/1.2) + ((20.14 - clr.h)/0.8); + clr.H = 300 + (100*((clr.h + 122.47)/1.2)) / temp; + } + else if (clr.h < 90.0) { + temp = ((clr.h - 20.14)/0.8) + ((90.00 - clr.h)/0.7); + clr.H = (100*((clr.h - 20.14)/0.8)) / temp; + } + else if (clr.h < 164.25) { + temp = ((clr.h - 90.00)/0.7) + ((164.25 - clr.h)/1.0); + clr.H = 100 + ((100*((clr.h - 90.00)/0.7)) / temp); + } + else if (clr.h < 237.53) { + temp = ((clr.h - 164.25)/1.0) + ((237.53 - clr.h)/1.2); + clr.H = 200 + ((100*((clr.h - 164.25)/1.0)) / temp); + } + else { + temp = ((clr.h - 237.53)/1.2) + ((360 - clr.h + 20.14)/0.8); + clr.H = 300 + ((100*((clr.h - 237.53)/1.2)) / temp); + } + + clr.J = 100.0 * pow((clr.A / pMod->adoptedWhite.A), + (pMod->c * pMod->z)); + + clr.Q = (4.0 / pMod->c) * pow((clr.J / 100.0), 0.5) * + (pMod->adoptedWhite.A + 4.0) * pow(pMod->FL, 0.25); + + t = (e * pow(((a * a) + (b * b)), 0.5)) / + (clr.RGBpa[0] + clr.RGBpa[1] + + ((21.0 / 20.0) * clr.RGBpa[2])); + + clr.C = pow(t, 0.9) * pow((clr.J / 100.0), 0.5) * + pow((1.64 - pow(0.29, pMod->n)), 0.73); + + clr.M = clr.C * pow(pMod->FL, 0.25); + clr.s = 100.0 * pow((clr.M / clr.Q), 0.5); + + return clr; +} + + +static +CAM02COLOR InverseCorrelates(CAM02COLOR clr, cmsCIECAM02* pMod) +{ + + cmsFloat64Number t, e, p1, p2, p3, p4, p5, hr, d2r; + d2r = 3.141592654 / 180.0; + + t = pow( (clr.C / (pow((clr.J / 100.0), 0.5) * + (pow((1.64 - pow(0.29, pMod->n)), 0.73)))), + (1.0 / 0.9) ); + e = ((12500.0 / 13.0) * pMod->Nc * pMod->Ncb) * + (cos((clr.h * d2r + 2.0)) + 3.8); + + clr.A = pMod->adoptedWhite.A * pow( + (clr.J / 100.0), + (1.0 / (pMod->c * pMod->z))); + + p1 = e / t; + p2 = (clr.A / pMod->Nbb) + 0.305; + p3 = 21.0 / 20.0; + + hr = clr.h * d2r; + + if (fabs(sin(hr)) >= fabs(cos(hr))) { + p4 = p1 / sin(hr); + clr.b = (p2 * (2.0 + p3) * (460.0 / 1403.0)) / + (p4 + (2.0 + p3) * (220.0 / 1403.0) * + (cos(hr) / sin(hr)) - (27.0 / 1403.0) + + p3 * (6300.0 / 1403.0)); + clr.a = clr.b * (cos(hr) / sin(hr)); + } + else { + p5 = p1 / cos(hr); + clr.a = (p2 * (2.0 + p3) * (460.0 / 1403.0)) / + (p5 + (2.0 + p3) * (220.0 / 1403.0) - + ((27.0 / 1403.0) - p3 * (6300.0 / 1403.0)) * + (sin(hr) / cos(hr))); + clr.b = clr.a * (sin(hr) / cos(hr)); + } + + clr.RGBpa[0] = ((460.0 / 1403.0) * p2) + + ((451.0 / 1403.0) * clr.a) + + ((288.0 / 1403.0) * clr.b); + clr.RGBpa[1] = ((460.0 / 1403.0) * p2) - + ((891.0 / 1403.0) * clr.a) - + ((261.0 / 1403.0) * clr.b); + clr.RGBpa[2] = ((460.0 / 1403.0) * p2) - + ((220.0 / 1403.0) * clr.a) - + ((6300.0 / 1403.0) * clr.b); + + return clr; +} + +static +CAM02COLOR InverseNonlinearity(CAM02COLOR clr, cmsCIECAM02* pMod) +{ + cmsUInt32Number i; + cmsFloat64Number c1; + + for (i = 0; i < 3; i++) { + if ((clr.RGBpa[i] - 0.1) < 0) c1 = -1; + else c1 = 1; + clr.RGBp[i] = c1 * (100.0 / pMod->FL) * + pow(((27.13 * fabs(clr.RGBpa[i] - 0.1)) / + (400.0 - fabs(clr.RGBpa[i] - 0.1))), + (1.0 / 0.42)); + } + + return clr; +} + +static +CAM02COLOR HPEtoCAT02(CAM02COLOR clr) +{ + cmsFloat64Number M[9]; + + M[0] = (( 0.7328 * 1.910197) + (0.4296 * 0.370950)); + M[1] = (( 0.7328 * -1.112124) + (0.4296 * 0.629054)); + M[2] = (( 0.7328 * 0.201908) + (0.4296 * 0.000008) - 0.1624); + M[3] = ((-0.7036 * 1.910197) + (1.6975 * 0.370950)); + M[4] = ((-0.7036 * -1.112124) + (1.6975 * 0.629054)); + M[5] = ((-0.7036 * 0.201908) + (1.6975 * 0.000008) + 0.0061); + M[6] = (( 0.0030 * 1.910197) + (0.0136 * 0.370950)); + M[7] = (( 0.0030 * -1.112124) + (0.0136 * 0.629054)); + M[8] = (( 0.0030 * 0.201908) + (0.0136 * 0.000008) + 0.9834);; + + clr.RGBc[0] = (clr.RGBp[0] * M[0]) + (clr.RGBp[1] * M[1]) + (clr.RGBp[2] * M[2]); + clr.RGBc[1] = (clr.RGBp[0] * M[3]) + (clr.RGBp[1] * M[4]) + (clr.RGBp[2] * M[5]); + clr.RGBc[2] = (clr.RGBp[0] * M[6]) + (clr.RGBp[1] * M[7]) + (clr.RGBp[2] * M[8]); + return clr; +} + + +static +CAM02COLOR InverseChromaticAdaptation(CAM02COLOR clr, cmsCIECAM02* pMod) +{ + cmsUInt32Number i; + for (i = 0; i < 3; i++) { + clr.RGB[i] = clr.RGBc[i] / + ((pMod->adoptedWhite.XYZ[1] * pMod->D / pMod->adoptedWhite.RGB[i]) + 1.0 - pMod->D); + } + return clr; +} + + +static +CAM02COLOR CAT02toXYZ(CAM02COLOR clr) +{ + clr.XYZ[0] = (clr.RGB[0] * 1.096124) + (clr.RGB[1] * -0.278869) + (clr.RGB[2] * 0.182745); + clr.XYZ[1] = (clr.RGB[0] * 0.454369) + (clr.RGB[1] * 0.473533) + (clr.RGB[2] * 0.072098); + clr.XYZ[2] = (clr.RGB[0] * -0.009628) + (clr.RGB[1] * -0.005698) + (clr.RGB[2] * 1.015326); + + return clr; +} + + +cmsHANDLE CMSEXPORT cmsCIECAM02Init(cmsContext ContextID, const cmsViewingConditions* pVC) +{ + cmsCIECAM02* lpMod; + + _cmsAssert(pVC != NULL); + + if((lpMod = (cmsCIECAM02*) _cmsMallocZero(ContextID, sizeof(cmsCIECAM02))) == NULL) { + return NULL; + } + + lpMod ->ContextID = ContextID; + + lpMod ->adoptedWhite.XYZ[0] = pVC ->whitePoint.X; + lpMod ->adoptedWhite.XYZ[1] = pVC ->whitePoint.Y; + lpMod ->adoptedWhite.XYZ[2] = pVC ->whitePoint.Z; + + lpMod -> LA = pVC ->La; + lpMod -> Yb = pVC ->Yb; + lpMod -> D = pVC ->D_value; + lpMod -> surround = pVC ->surround; + + switch (lpMod -> surround) { + + + case CUTSHEET_SURROUND: + lpMod->F = 0.8; + lpMod->c = 0.41; + lpMod->Nc = 0.8; + break; + + case DARK_SURROUND: + lpMod -> F = 0.8; + lpMod -> c = 0.525; + lpMod -> Nc = 0.8; + break; + + case DIM_SURROUND: + lpMod -> F = 0.9; + lpMod -> c = 0.59; + lpMod -> Nc = 0.95; + break; + + default: + // Average surround + lpMod -> F = 1.0; + lpMod -> c = 0.69; + lpMod -> Nc = 1.0; + } + + lpMod -> n = compute_n(lpMod); + lpMod -> z = compute_z(lpMod); + lpMod -> Nbb = computeNbb(lpMod); + lpMod -> FL = computeFL(lpMod); + + if (lpMod -> D == D_CALCULATE) { + lpMod -> D = computeD(lpMod); + } + + lpMod -> Ncb = lpMod -> Nbb; + + lpMod -> adoptedWhite = XYZtoCAT02(lpMod -> adoptedWhite); + lpMod -> adoptedWhite = ChromaticAdaptation(lpMod -> adoptedWhite, lpMod); + lpMod -> adoptedWhite = CAT02toHPE(lpMod -> adoptedWhite); + lpMod -> adoptedWhite = NonlinearCompression(lpMod -> adoptedWhite, lpMod); + + return (cmsHANDLE) lpMod; + +} + +void CMSEXPORT cmsCIECAM02Done(cmsHANDLE hModel) +{ + cmsCIECAM02* lpMod = (cmsCIECAM02*) hModel; + + if (lpMod) _cmsFree(lpMod ->ContextID, lpMod); +} + + +void CMSEXPORT cmsCIECAM02Forward(cmsHANDLE hModel, const cmsCIEXYZ* pIn, cmsJCh* pOut) +{ + CAM02COLOR clr; + cmsCIECAM02* lpMod = (cmsCIECAM02*) hModel; + + _cmsAssert(lpMod != NULL); + _cmsAssert(pIn != NULL); + _cmsAssert(pOut != NULL); + + clr.XYZ[0] = pIn ->X; + clr.XYZ[1] = pIn ->Y; + clr.XYZ[2] = pIn ->Z; + + clr = XYZtoCAT02(clr); + clr = ChromaticAdaptation(clr, lpMod); + clr = CAT02toHPE(clr); + clr = NonlinearCompression(clr, lpMod); + clr = ComputeCorrelates(clr, lpMod); + + pOut ->J = clr.J; + pOut ->C = clr.C; + pOut ->h = clr.h; +} + +void CMSEXPORT cmsCIECAM02Reverse(cmsHANDLE hModel, const cmsJCh* pIn, cmsCIEXYZ* pOut) +{ + CAM02COLOR clr; + cmsCIECAM02* lpMod = (cmsCIECAM02*) hModel; + + _cmsAssert(lpMod != NULL); + _cmsAssert(pIn != NULL); + _cmsAssert(pOut != NULL); + + clr.J = pIn -> J; + clr.C = pIn -> C; + clr.h = pIn -> h; + + clr = InverseCorrelates(clr, lpMod); + clr = InverseNonlinearity(clr, lpMod); + clr = HPEtoCAT02(clr); + clr = InverseChromaticAdaptation(clr, lpMod); + clr = CAT02toXYZ(clr); + + pOut ->X = clr.XYZ[0]; + pOut ->Y = clr.XYZ[1]; + pOut ->Z = clr.XYZ[2]; +} + diff --git a/jni/lcms2-2.5/src/cmscgats.c b/jni/lcms2-2.5/src/cmscgats.c new file mode 100644 index 00000000..53730e97 --- /dev/null +++ b/jni/lcms2-2.5/src/cmscgats.c @@ -0,0 +1,2773 @@ +//--------------------------------------------------------------------------------- +// +// Little Color Management System +// Copyright (c) 1998-2012 Marti Maria Saguer +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//--------------------------------------------------------------------------------- +// + +#include "lcms2_internal.h" + + +// IT8.7 / CGATS.17-200x handling ----------------------------------------------------------------------------- + + +#define MAXID 128 // Max length of identifier +#define MAXSTR 1024 // Max length of string +#define MAXTABLES 255 // Max Number of tables in a single stream +#define MAXINCLUDE 20 // Max number of nested includes + +#define DEFAULT_DBL_FORMAT "%.10g" // Double formatting + +#ifdef CMS_IS_WINDOWS_ +# include +# define DIR_CHAR '\\' +#else +# define DIR_CHAR '/' +#endif + + +// Symbols +typedef enum { + + SNONE, + SINUM, // Integer + SDNUM, // Real + SIDENT, // Identifier + SSTRING, // string + SCOMMENT, // comment + SEOLN, // End of line + SEOF, // End of stream + SSYNERROR, // Syntax error found on stream + + // Keywords + + SBEGIN_DATA, + SBEGIN_DATA_FORMAT, + SEND_DATA, + SEND_DATA_FORMAT, + SKEYWORD, + SDATA_FORMAT_ID, + SINCLUDE + + } SYMBOL; + + +// How to write the value +typedef enum { + + WRITE_UNCOOKED, + WRITE_STRINGIFY, + WRITE_HEXADECIMAL, + WRITE_BINARY, + WRITE_PAIR + + } WRITEMODE; + +// Linked list of variable names +typedef struct _KeyVal { + + struct _KeyVal* Next; + char* Keyword; // Name of variable + struct _KeyVal* NextSubkey; // If key is a dictionary, points to the next item + char* Subkey; // If key is a dictionary, points to the subkey name + char* Value; // Points to value + WRITEMODE WriteAs; // How to write the value + + } KEYVALUE; + + +// Linked list of memory chunks (Memory sink) +typedef struct _OwnedMem { + + struct _OwnedMem* Next; + void * Ptr; // Point to value + + } OWNEDMEM; + +// Suballocator +typedef struct _SubAllocator { + + cmsUInt8Number* Block; + cmsUInt32Number BlockSize; + cmsUInt32Number Used; + + } SUBALLOCATOR; + +// Table. Each individual table can hold properties and rows & cols +typedef struct _Table { + + char SheetType[MAXSTR]; // The first row of the IT8 (the type) + + int nSamples, nPatches; // Cols, Rows + int SampleID; // Pos of ID + + KEYVALUE* HeaderList; // The properties + + char** DataFormat; // The binary stream descriptor + char** Data; // The binary stream + + } TABLE; + +// File stream being parsed +typedef struct _FileContext { + char FileName[cmsMAX_PATH]; // File name if being readed from file + FILE* Stream; // File stream or NULL if holded in memory + } FILECTX; + +// This struct hold all information about an open IT8 handler. +typedef struct { + + + cmsUInt32Number TablesCount; // How many tables in this stream + cmsUInt32Number nTable; // The actual table + + TABLE Tab[MAXTABLES]; + + // Memory management + OWNEDMEM* MemorySink; // The storage backend + SUBALLOCATOR Allocator; // String suballocator -- just to keep it fast + + // Parser state machine + SYMBOL sy; // Current symbol + int ch; // Current character + + int inum; // integer value + cmsFloat64Number dnum; // real value + char id[MAXID]; // identifier + char str[MAXSTR]; // string + + // Allowed keywords & datasets. They have visibility on whole stream + KEYVALUE* ValidKeywords; + KEYVALUE* ValidSampleID; + + char* Source; // Points to loc. being parsed + int lineno; // line counter for error reporting + + FILECTX* FileStack[MAXINCLUDE]; // Stack of files being parsed + int IncludeSP; // Include Stack Pointer + + char* MemoryBlock; // The stream if holded in memory + + char DoubleFormatter[MAXID];// Printf-like 'cmsFloat64Number' formatter + + cmsContext ContextID; // The threading context + + } cmsIT8; + + +// The stream for save operations +typedef struct { + + FILE* stream; // For save-to-file behaviour + + cmsUInt8Number* Base; + cmsUInt8Number* Ptr; // For save-to-mem behaviour + cmsUInt32Number Used; + cmsUInt32Number Max; + + } SAVESTREAM; + + +// ------------------------------------------------------ cmsIT8 parsing routines + + +// A keyword +typedef struct { + + const char *id; + SYMBOL sy; + + } KEYWORD; + +// The keyword->symbol translation table. Sorting is required. +static const KEYWORD TabKeys[] = { + + {"$INCLUDE", SINCLUDE}, // This is an extension! + {".INCLUDE", SINCLUDE}, // This is an extension! + + {"BEGIN_DATA", SBEGIN_DATA }, + {"BEGIN_DATA_FORMAT", SBEGIN_DATA_FORMAT }, + {"DATA_FORMAT_IDENTIFIER", SDATA_FORMAT_ID}, + {"END_DATA", SEND_DATA}, + {"END_DATA_FORMAT", SEND_DATA_FORMAT}, + {"KEYWORD", SKEYWORD} + }; + +#define NUMKEYS (sizeof(TabKeys)/sizeof(KEYWORD)) + +// Predefined properties + +// A property +typedef struct { + const char *id; // The identifier + WRITEMODE as; // How is supposed to be written + } PROPERTY; + +static PROPERTY PredefinedProperties[] = { + + {"NUMBER_OF_FIELDS", WRITE_UNCOOKED}, // Required - NUMBER OF FIELDS + {"NUMBER_OF_SETS", WRITE_UNCOOKED}, // Required - NUMBER OF SETS + {"ORIGINATOR", WRITE_STRINGIFY}, // Required - Identifies the specific system, organization or individual that created the data file. + {"FILE_DESCRIPTOR", WRITE_STRINGIFY}, // Required - Describes the purpose or contents of the data file. + {"CREATED", WRITE_STRINGIFY}, // Required - Indicates date of creation of the data file. + {"DESCRIPTOR", WRITE_STRINGIFY}, // Required - Describes the purpose or contents of the data file. + {"DIFFUSE_GEOMETRY", WRITE_STRINGIFY}, // The diffuse geometry used. Allowed values are "sphere" or "opal". + {"MANUFACTURER", WRITE_STRINGIFY}, + {"MANUFACTURE", WRITE_STRINGIFY}, // Some broken Fuji targets does store this value + {"PROD_DATE", WRITE_STRINGIFY}, // Identifies year and month of production of the target in the form yyyy:mm. + {"SERIAL", WRITE_STRINGIFY}, // Uniquely identifies individual physical target. + + {"MATERIAL", WRITE_STRINGIFY}, // Identifies the material on which the target was produced using a code + // uniquely identifying th e material. This is intend ed to be used for IT8.7 + // physical targets only (i.e . IT8.7/1 a nd IT8.7/2). + + {"INSTRUMENTATION", WRITE_STRINGIFY}, // Used to report the specific instrumentation used (manufacturer and + // model number) to generate the data reported. This data will often + // provide more information about the particular data collected than an + // extensive list of specific details. This is particularly important for + // spectral data or data derived from spectrophotometry. + + {"MEASUREMENT_SOURCE", WRITE_STRINGIFY}, // Illumination used for spectral measurements. This data helps provide + // a guide to the potential for issues of paper fluorescence, etc. + + {"PRINT_CONDITIONS", WRITE_STRINGIFY}, // Used to define the characteristics of the printed sheet being reported. + // Where standard conditions have been defined (e.g., SWOP at nominal) + // named conditions may suffice. Otherwise, detailed information is + // needed. + + {"SAMPLE_BACKING", WRITE_STRINGIFY}, // Identifies the backing material used behind the sample during + // measurement. Allowed values are “black”, “white”, or {"na". + + {"CHISQ_DOF", WRITE_STRINGIFY}, // Degrees of freedom associated with the Chi squared statistic + + // below properties are new in recent specs: + + {"MEASUREMENT_GEOMETRY", WRITE_STRINGIFY}, // The type of measurement, either reflection or transmission, should be indicated + // along with details of the geometry and the aperture size and shape. For example, + // for transmission measurements it is important to identify 0/diffuse, diffuse/0, + // opal or integrating sphere, etc. For reflection it is important to identify 0/45, + // 45/0, sphere (specular included or excluded), etc. + + {"FILTER", WRITE_STRINGIFY}, // Identifies the use of physical filter(s) during measurement. Typically used to + // denote the use of filters such as none, D65, Red, Green or Blue. + + {"POLARIZATION", WRITE_STRINGIFY}, // Identifies the use of a physical polarization filter during measurement. Allowed + // values are {"yes”, “white”, “none” or “na”. + + {"WEIGHTING_FUNCTION", WRITE_PAIR}, // Indicates such functions as: the CIE standard observer functions used in the + // calculation of various data parameters (2 degree and 10 degree), CIE standard + // illuminant functions used in the calculation of various data parameters (e.g., D50, + // D65, etc.), density status response, etc. If used there shall be at least one + // name-value pair following the WEIGHTING_FUNCTION tag/keyword. The first attribute + // in the set shall be {"name" and shall identify the particular parameter used. + // The second shall be {"value" and shall provide the value associated with that name. + // For ASCII data, a string containing the Name and Value attribute pairs shall follow + // the weighting function keyword. A semi-colon separates attribute pairs from each + // other and within the attribute the name and value are separated by a comma. + + {"COMPUTATIONAL_PARAMETER", WRITE_PAIR}, // Parameter that is used in computing a value from measured data. Name is the name + // of the calculation, parameter is the name of the parameter used in the calculation + // and value is the value of the parameter. + + {"TARGET_TYPE", WRITE_STRINGIFY}, // The type of target being measured, e.g. IT8.7/1, IT8.7/3, user defined, etc. + + {"COLORANT", WRITE_STRINGIFY}, // Identifies the colorant(s) used in creating the target. + + {"TABLE_DESCRIPTOR", WRITE_STRINGIFY}, // Describes the purpose or contents of a data table. + + {"TABLE_NAME", WRITE_STRINGIFY} // Provides a short name for a data table. +}; + +#define NUMPREDEFINEDPROPS (sizeof(PredefinedProperties)/sizeof(PROPERTY)) + + +// Predefined sample types on dataset +static const char* PredefinedSampleID[] = { + "SAMPLE_ID", // Identifies sample that data represents + "STRING", // Identifies label, or other non-machine readable value. + // Value must begin and end with a " symbol + + "CMYK_C", // Cyan component of CMYK data expressed as a percentage + "CMYK_M", // Magenta component of CMYK data expressed as a percentage + "CMYK_Y", // Yellow component of CMYK data expressed as a percentage + "CMYK_K", // Black component of CMYK data expressed as a percentage + "D_RED", // Red filter density + "D_GREEN", // Green filter density + "D_BLUE", // Blue filter density + "D_VIS", // Visual filter density + "D_MAJOR_FILTER", // Major filter d ensity + "RGB_R", // Red component of RGB data + "RGB_G", // Green component of RGB data + "RGB_B", // Blue com ponent of RGB data + "SPECTRAL_NM", // Wavelength of measurement expressed in nanometers + "SPECTRAL_PCT", // Percentage reflectance/transmittance + "SPECTRAL_DEC", // Reflectance/transmittance + "XYZ_X", // X component of tristimulus data + "XYZ_Y", // Y component of tristimulus data + "XYZ_Z", // Z component of tristimulus data + "XYY_X" // x component of chromaticity data + "XYY_Y", // y component of chromaticity data + "XYY_CAPY", // Y component of tristimulus data + "LAB_L", // L* component of Lab data + "LAB_A", // a* component of Lab data + "LAB_B", // b* component of Lab data + "LAB_C", // C*ab component of Lab data + "LAB_H", // hab component of Lab data + "LAB_DE", // CIE dE + "LAB_DE_94", // CIE dE using CIE 94 + "LAB_DE_CMC", // dE using CMC + "LAB_DE_2000", // CIE dE using CIE DE 2000 + "MEAN_DE", // Mean Delta E (LAB_DE) of samples compared to batch average + // (Used for data files for ANSI IT8.7/1 and IT8.7/2 targets) + "STDEV_X", // Standard deviation of X (tristimulus data) + "STDEV_Y", // Standard deviation of Y (tristimulus data) + "STDEV_Z", // Standard deviation of Z (tristimulus data) + "STDEV_L", // Standard deviation of L* + "STDEV_A", // Standard deviation of a* + "STDEV_B", // Standard deviation of b* + "STDEV_DE", // Standard deviation of CIE dE + "CHI_SQD_PAR"}; // The average of the standard deviations of L*, a* and b*. It is + // used to derive an estimate of the chi-squared parameter which is + // recommended as the predictor of the variability of dE + +#define NUMPREDEFINEDSAMPLEID (sizeof(PredefinedSampleID)/sizeof(char *)) + +//Forward declaration of some internal functions +static void* AllocChunk(cmsIT8* it8, cmsUInt32Number size); + +// Checks whatever c is a separator +static +cmsBool isseparator(int c) +{ + return (c == ' ') || (c == '\t') ; +} + +// Checks whatever c is a valid identifier char +static +cmsBool ismiddle(int c) +{ + return (!isseparator(c) && (c != '#') && (c !='\"') && (c != '\'') && (c > 32) && (c < 127)); +} + +// Checks whatsever c is a valid identifier middle char. +static +cmsBool isidchar(int c) +{ + return isalnum(c) || ismiddle(c); +} + +// Checks whatsever c is a valid identifier first char. +static +cmsBool isfirstidchar(int c) +{ + return !isdigit(c) && ismiddle(c); +} + +// Guess whether the supplied path looks like an absolute path +static +cmsBool isabsolutepath(const char *path) +{ + char ThreeChars[4]; + + if(path == NULL) + return FALSE; + if (path[0] == 0) + return FALSE; + + strncpy(ThreeChars, path, 3); + ThreeChars[3] = 0; + + if(ThreeChars[0] == DIR_CHAR) + return TRUE; + +#ifdef CMS_IS_WINDOWS_ + if (isalpha((int) ThreeChars[0]) && ThreeChars[1] == ':') + return TRUE; +#endif + return FALSE; +} + + +// Makes a file path based on a given reference path +// NOTE: this function doesn't check if the path exists or even if it's legal +static +cmsBool BuildAbsolutePath(const char *relPath, const char *basePath, char *buffer, cmsUInt32Number MaxLen) +{ + char *tail; + cmsUInt32Number len; + + // Already absolute? + if (isabsolutepath(relPath)) { + + strncpy(buffer, relPath, MaxLen); + buffer[MaxLen-1] = 0; + return TRUE; + } + + // No, search for last + strncpy(buffer, basePath, MaxLen); + buffer[MaxLen-1] = 0; + + tail = strrchr(buffer, DIR_CHAR); + if (tail == NULL) return FALSE; // Is not absolute and has no separators?? + + len = (cmsUInt32Number) (tail - buffer); + if (len >= MaxLen) return FALSE; + + // No need to assure zero terminator over here + strncpy(tail + 1, relPath, MaxLen - len); + + return TRUE; +} + + +// Make sure no exploit is being even tried +static +const char* NoMeta(const char* str) +{ + if (strchr(str, '%') != NULL) + return "**** CORRUPTED FORMAT STRING ***"; + + return str; +} + +// Syntax error +static +cmsBool SynError(cmsIT8* it8, const char *Txt, ...) +{ + char Buffer[256], ErrMsg[1024]; + va_list args; + + va_start(args, Txt); + vsnprintf(Buffer, 255, Txt, args); + Buffer[255] = 0; + va_end(args); + + snprintf(ErrMsg, 1023, "%s: Line %d, %s", it8->FileStack[it8 ->IncludeSP]->FileName, it8->lineno, Buffer); + ErrMsg[1023] = 0; + it8->sy = SSYNERROR; + cmsSignalError(it8 ->ContextID, cmsERROR_CORRUPTION_DETECTED, "%s", ErrMsg); + return FALSE; +} + +// Check if current symbol is same as specified. issue an error else. +static +cmsBool Check(cmsIT8* it8, SYMBOL sy, const char* Err) +{ + if (it8 -> sy != sy) + return SynError(it8, NoMeta(Err)); + return TRUE; +} + +// Read Next character from stream +static +void NextCh(cmsIT8* it8) +{ + if (it8 -> FileStack[it8 ->IncludeSP]->Stream) { + + it8 ->ch = fgetc(it8 ->FileStack[it8 ->IncludeSP]->Stream); + + if (feof(it8 -> FileStack[it8 ->IncludeSP]->Stream)) { + + if (it8 ->IncludeSP > 0) { + + fclose(it8 ->FileStack[it8->IncludeSP--]->Stream); + it8 -> ch = ' '; // Whitespace to be ignored + + } else + it8 ->ch = 0; // EOF + } + } + else { + it8->ch = *it8->Source; + if (it8->ch) it8->Source++; + } +} + + +// Try to see if current identifier is a keyword, if so return the referred symbol +static +SYMBOL BinSrchKey(const char *id) +{ + int l = 1; + int r = NUMKEYS; + int x, res; + + while (r >= l) + { + x = (l+r)/2; + res = cmsstrcasecmp(id, TabKeys[x-1].id); + if (res == 0) return TabKeys[x-1].sy; + if (res < 0) r = x - 1; + else l = x + 1; + } + + return SNONE; +} + + +// 10 ^n +static +cmsFloat64Number xpow10(int n) +{ + return pow(10, (cmsFloat64Number) n); +} + + +// Reads a Real number, tries to follow from integer number +static +void ReadReal(cmsIT8* it8, int inum) +{ + it8->dnum = (cmsFloat64Number) inum; + + while (isdigit(it8->ch)) { + + it8->dnum = it8->dnum * 10.0 + (it8->ch - '0'); + NextCh(it8); + } + + if (it8->ch == '.') { // Decimal point + + cmsFloat64Number frac = 0.0; // fraction + int prec = 0; // precision + + NextCh(it8); // Eats dec. point + + while (isdigit(it8->ch)) { + + frac = frac * 10.0 + (it8->ch - '0'); + prec++; + NextCh(it8); + } + + it8->dnum = it8->dnum + (frac / xpow10(prec)); + } + + // Exponent, example 34.00E+20 + if (toupper(it8->ch) == 'E') { + + int e; + int sgn; + + NextCh(it8); sgn = 1; + + if (it8->ch == '-') { + + sgn = -1; NextCh(it8); + } + else + if (it8->ch == '+') { + + sgn = +1; + NextCh(it8); + } + + e = 0; + while (isdigit(it8->ch)) { + + if ((cmsFloat64Number) e * 10L < INT_MAX) + e = e * 10 + (it8->ch - '0'); + + NextCh(it8); + } + + e = sgn*e; + it8 -> dnum = it8 -> dnum * xpow10(e); + } +} + +// Parses a float number +// This can not call directly atof because it uses locale dependant +// parsing, while CCMX files always use . as decimal separator +static +cmsFloat64Number ParseFloatNumber(const char *Buffer) +{ + cmsFloat64Number dnum = 0.0; + int sign = 1; + + // keep safe + if (Buffer == NULL) return 0.0; + + if (*Buffer == '-' || *Buffer == '+') { + + sign = (*Buffer == '-') ? -1 : 1; + Buffer++; + } + + + while (*Buffer && isdigit((int) *Buffer)) { + + dnum = dnum * 10.0 + (*Buffer - '0'); + if (*Buffer) Buffer++; + } + + if (*Buffer == '.') { + + cmsFloat64Number frac = 0.0; // fraction + int prec = 0; // precission + + if (*Buffer) Buffer++; + + while (*Buffer && isdigit((int) *Buffer)) { + + frac = frac * 10.0 + (*Buffer - '0'); + prec++; + if (*Buffer) Buffer++; + } + + dnum = dnum + (frac / xpow10(prec)); + } + + // Exponent, example 34.00E+20 + if (*Buffer && toupper(*Buffer) == 'E') { + + int e; + int sgn; + + if (*Buffer) Buffer++; + sgn = 1; + + if (*Buffer == '-') { + + sgn = -1; + if (*Buffer) Buffer++; + } + else + if (*Buffer == '+') { + + sgn = +1; + if (*Buffer) Buffer++; + } + + e = 0; + while (*Buffer && isdigit((int) *Buffer)) { + + if ((cmsFloat64Number) e * 10L < INT_MAX) + e = e * 10 + (*Buffer - '0'); + + if (*Buffer) Buffer++; + } + + e = sgn*e; + dnum = dnum * xpow10(e); + } + + return sign * dnum; +} + + +// Reads next symbol +static +void InSymbol(cmsIT8* it8) +{ + register char *idptr; + register int k; + SYMBOL key; + int sng; + + do { + + while (isseparator(it8->ch)) + NextCh(it8); + + if (isfirstidchar(it8->ch)) { // Identifier + + k = 0; + idptr = it8->id; + + do { + + if (++k < MAXID) *idptr++ = (char) it8->ch; + + NextCh(it8); + + } while (isidchar(it8->ch)); + + *idptr = '\0'; + + + key = BinSrchKey(it8->id); + if (key == SNONE) it8->sy = SIDENT; + else it8->sy = key; + + } + else // Is a number? + if (isdigit(it8->ch) || it8->ch == '.' || it8->ch == '-' || it8->ch == '+') + { + int sign = 1; + + if (it8->ch == '-') { + sign = -1; + NextCh(it8); + } + + it8->inum = 0; + it8->sy = SINUM; + + if (it8->ch == '0') { // 0xnnnn (Hexa) or 0bnnnn (Binary) + + NextCh(it8); + if (toupper(it8->ch) == 'X') { + + int j; + + NextCh(it8); + while (isxdigit(it8->ch)) + { + it8->ch = toupper(it8->ch); + if (it8->ch >= 'A' && it8->ch <= 'F') j = it8->ch -'A'+10; + else j = it8->ch - '0'; + + if ((long) it8->inum * 16L > (long) INT_MAX) + { + SynError(it8, "Invalid hexadecimal number"); + return; + } + + it8->inum = it8->inum * 16 + j; + NextCh(it8); + } + return; + } + + if (toupper(it8->ch) == 'B') { // Binary + + int j; + + NextCh(it8); + while (it8->ch == '0' || it8->ch == '1') + { + j = it8->ch - '0'; + + if ((long) it8->inum * 2L > (long) INT_MAX) + { + SynError(it8, "Invalid binary number"); + return; + } + + it8->inum = it8->inum * 2 + j; + NextCh(it8); + } + return; + } + } + + + while (isdigit(it8->ch)) { + + if ((long) it8->inum * 10L > (long) INT_MAX) { + ReadReal(it8, it8->inum); + it8->sy = SDNUM; + it8->dnum *= sign; + return; + } + + it8->inum = it8->inum * 10 + (it8->ch - '0'); + NextCh(it8); + } + + if (it8->ch == '.') { + + ReadReal(it8, it8->inum); + it8->sy = SDNUM; + it8->dnum *= sign; + return; + } + + it8 -> inum *= sign; + + // Special case. Numbers followed by letters are taken as identifiers + + if (isidchar(it8 ->ch)) { + + if (it8 ->sy == SINUM) { + + sprintf(it8->id, "%d", it8->inum); + } + else { + + sprintf(it8->id, it8 ->DoubleFormatter, it8->dnum); + } + + k = (int) strlen(it8 ->id); + idptr = it8 ->id + k; + do { + + if (++k < MAXID) *idptr++ = (char) it8->ch; + + NextCh(it8); + + } while (isidchar(it8->ch)); + + *idptr = '\0'; + it8->sy = SIDENT; + } + return; + + } + else + switch ((int) it8->ch) { + + // EOF marker -- ignore it + case '\x1a': + NextCh(it8); + break; + + // Eof stream markers + case 0: + case -1: + it8->sy = SEOF; + break; + + + // Next line + case '\r': + NextCh(it8); + if (it8 ->ch == '\n') + NextCh(it8); + it8->sy = SEOLN; + it8->lineno++; + break; + + case '\n': + NextCh(it8); + it8->sy = SEOLN; + it8->lineno++; + break; + + // Comment + case '#': + NextCh(it8); + while (it8->ch && it8->ch != '\n' && it8->ch != '\r') + NextCh(it8); + + it8->sy = SCOMMENT; + break; + + // String. + case '\'': + case '\"': + idptr = it8->str; + sng = it8->ch; + k = 0; + NextCh(it8); + + while (k < MAXSTR && it8->ch != sng) { + + if (it8->ch == '\n'|| it8->ch == '\r') k = MAXSTR+1; + else { + *idptr++ = (char) it8->ch; + NextCh(it8); + k++; + } + } + + it8->sy = SSTRING; + *idptr = '\0'; + NextCh(it8); + break; + + + default: + SynError(it8, "Unrecognized character: 0x%x", it8 ->ch); + return; + } + + } while (it8->sy == SCOMMENT); + + // Handle the include special token + + if (it8 -> sy == SINCLUDE) { + + FILECTX* FileNest; + + if(it8 -> IncludeSP >= (MAXINCLUDE-1)) { + + SynError(it8, "Too many recursion levels"); + return; + } + + InSymbol(it8); + if (!Check(it8, SSTRING, "Filename expected")) return; + + FileNest = it8 -> FileStack[it8 -> IncludeSP + 1]; + if(FileNest == NULL) { + + FileNest = it8 ->FileStack[it8 -> IncludeSP + 1] = (FILECTX*)AllocChunk(it8, sizeof(FILECTX)); + //if(FileNest == NULL) + // TODO: how to manage out-of-memory conditions? + } + + if (BuildAbsolutePath(it8->str, + it8->FileStack[it8->IncludeSP]->FileName, + FileNest->FileName, cmsMAX_PATH-1) == FALSE) { + SynError(it8, "File path too long"); + return; + } + + FileNest->Stream = fopen(FileNest->FileName, "rt"); + if (FileNest->Stream == NULL) { + + SynError(it8, "File %s not found", FileNest->FileName); + return; + } + it8->IncludeSP++; + + it8 ->ch = ' '; + InSymbol(it8); + } + +} + +// Checks end of line separator +static +cmsBool CheckEOLN(cmsIT8* it8) +{ + if (!Check(it8, SEOLN, "Expected separator")) return FALSE; + while (it8 -> sy == SEOLN) + InSymbol(it8); + return TRUE; + +} + +// Skip a symbol + +static +void Skip(cmsIT8* it8, SYMBOL sy) +{ + if (it8->sy == sy && it8->sy != SEOF) + InSymbol(it8); +} + + +// Skip multiple EOLN +static +void SkipEOLN(cmsIT8* it8) +{ + while (it8->sy == SEOLN) { + InSymbol(it8); + } +} + + +// Returns a string holding current value +static +cmsBool GetVal(cmsIT8* it8, char* Buffer, cmsUInt32Number max, const char* ErrorTitle) +{ + switch (it8->sy) { + + case SEOLN: // Empty value + Buffer[0]=0; + break; + case SIDENT: strncpy(Buffer, it8->id, max); + Buffer[max-1]=0; + break; + case SINUM: snprintf(Buffer, max, "%d", it8 -> inum); break; + case SDNUM: snprintf(Buffer, max, it8->DoubleFormatter, it8 -> dnum); break; + case SSTRING: strncpy(Buffer, it8->str, max); + Buffer[max-1] = 0; + break; + + + default: + return SynError(it8, "%s", ErrorTitle); + } + + Buffer[max] = 0; + return TRUE; +} + +// ---------------------------------------------------------- Table + +static +TABLE* GetTable(cmsIT8* it8) +{ + if ((it8 -> nTable >= it8 ->TablesCount)) { + + SynError(it8, "Table %d out of sequence", it8 -> nTable); + return it8 -> Tab; + } + + return it8 ->Tab + it8 ->nTable; +} + +// ---------------------------------------------------------- Memory management + + +// Frees an allocator and owned memory +void CMSEXPORT cmsIT8Free(cmsHANDLE hIT8) +{ + cmsIT8* it8 = (cmsIT8*) hIT8; + + if (it8 == NULL) + return; + + if (it8->MemorySink) { + + OWNEDMEM* p; + OWNEDMEM* n; + + for (p = it8->MemorySink; p != NULL; p = n) { + + n = p->Next; + if (p->Ptr) _cmsFree(it8 ->ContextID, p->Ptr); + _cmsFree(it8 ->ContextID, p); + } + } + + if (it8->MemoryBlock) + _cmsFree(it8 ->ContextID, it8->MemoryBlock); + + _cmsFree(it8 ->ContextID, it8); +} + + +// Allocates a chunk of data, keep linked list +static +void* AllocBigBlock(cmsIT8* it8, cmsUInt32Number size) +{ + OWNEDMEM* ptr1; + void* ptr = _cmsMallocZero(it8->ContextID, size); + + if (ptr != NULL) { + + ptr1 = (OWNEDMEM*) _cmsMallocZero(it8 ->ContextID, sizeof(OWNEDMEM)); + + if (ptr1 == NULL) { + + _cmsFree(it8 ->ContextID, ptr); + return NULL; + } + + ptr1-> Ptr = ptr; + ptr1-> Next = it8 -> MemorySink; + it8 -> MemorySink = ptr1; + } + + return ptr; +} + + +// Suballocator. +static +void* AllocChunk(cmsIT8* it8, cmsUInt32Number size) +{ + cmsUInt32Number Free = it8 ->Allocator.BlockSize - it8 ->Allocator.Used; + cmsUInt8Number* ptr; + + size = _cmsALIGNMEM(size); + + if (size > Free) { + + if (it8 -> Allocator.BlockSize == 0) + + it8 -> Allocator.BlockSize = 20*1024; + else + it8 ->Allocator.BlockSize *= 2; + + if (it8 ->Allocator.BlockSize < size) + it8 ->Allocator.BlockSize = size; + + it8 ->Allocator.Used = 0; + it8 ->Allocator.Block = (cmsUInt8Number*) AllocBigBlock(it8, it8 ->Allocator.BlockSize); + } + + ptr = it8 ->Allocator.Block + it8 ->Allocator.Used; + it8 ->Allocator.Used += size; + + return (void*) ptr; + +} + + +// Allocates a string +static +char *AllocString(cmsIT8* it8, const char* str) +{ + cmsUInt32Number Size = (cmsUInt32Number) strlen(str)+1; + char *ptr; + + + ptr = (char *) AllocChunk(it8, Size); + if (ptr) strncpy (ptr, str, Size-1); + + return ptr; +} + +// Searches through linked list + +static +cmsBool IsAvailableOnList(KEYVALUE* p, const char* Key, const char* Subkey, KEYVALUE** LastPtr) +{ + if (LastPtr) *LastPtr = p; + + for (; p != NULL; p = p->Next) { + + if (LastPtr) *LastPtr = p; + + if (*Key != '#') { // Comments are ignored + + if (cmsstrcasecmp(Key, p->Keyword) == 0) + break; + } + } + + if (p == NULL) + return FALSE; + + if (Subkey == 0) + return TRUE; + + for (; p != NULL; p = p->NextSubkey) { + + if (p ->Subkey == NULL) continue; + + if (LastPtr) *LastPtr = p; + + if (cmsstrcasecmp(Subkey, p->Subkey) == 0) + return TRUE; + } + + return FALSE; +} + + + +// Add a property into a linked list +static +KEYVALUE* AddToList(cmsIT8* it8, KEYVALUE** Head, const char *Key, const char *Subkey, const char* xValue, WRITEMODE WriteAs) +{ + KEYVALUE* p; + KEYVALUE* last; + + + // Check if property is already in list + + if (IsAvailableOnList(*Head, Key, Subkey, &p)) { + + // This may work for editing properties + + // return SynError(it8, "duplicate key <%s>", Key); + } + else { + + last = p; + + // Allocate the container + p = (KEYVALUE*) AllocChunk(it8, sizeof(KEYVALUE)); + if (p == NULL) + { + SynError(it8, "AddToList: out of memory"); + return NULL; + } + + // Store name and value + p->Keyword = AllocString(it8, Key); + p->Subkey = (Subkey == NULL) ? NULL : AllocString(it8, Subkey); + + // Keep the container in our list + if (*Head == NULL) { + *Head = p; + } + else + { + if (Subkey != NULL && last != NULL) { + + last->NextSubkey = p; + + // If Subkey is not null, then last is the last property with the same key, + // but not necessarily is the last property in the list, so we need to move + // to the actual list end + while (last->Next != NULL) + last = last->Next; + } + + if (last != NULL) last->Next = p; + } + + p->Next = NULL; + p->NextSubkey = NULL; + } + + p->WriteAs = WriteAs; + + if (xValue != NULL) { + + p->Value = AllocString(it8, xValue); + } + else { + p->Value = NULL; + } + + return p; +} + +static +KEYVALUE* AddAvailableProperty(cmsIT8* it8, const char* Key, WRITEMODE as) +{ + return AddToList(it8, &it8->ValidKeywords, Key, NULL, NULL, as); +} + + +static +KEYVALUE* AddAvailableSampleID(cmsIT8* it8, const char* Key) +{ + return AddToList(it8, &it8->ValidSampleID, Key, NULL, NULL, WRITE_UNCOOKED); +} + + +static +void AllocTable(cmsIT8* it8) +{ + TABLE* t; + + t = it8 ->Tab + it8 ->TablesCount; + + t->HeaderList = NULL; + t->DataFormat = NULL; + t->Data = NULL; + + it8 ->TablesCount++; +} + + +cmsInt32Number CMSEXPORT cmsIT8SetTable(cmsHANDLE IT8, cmsUInt32Number nTable) +{ + cmsIT8* it8 = (cmsIT8*) IT8; + + if (nTable >= it8 ->TablesCount) { + + if (nTable == it8 ->TablesCount) { + + AllocTable(it8); + } + else { + SynError(it8, "Table %d is out of sequence", nTable); + return -1; + } + } + + it8 ->nTable = nTable; + + return (cmsInt32Number) nTable; +} + + + +// Init an empty container +cmsHANDLE CMSEXPORT cmsIT8Alloc(cmsContext ContextID) +{ + cmsIT8* it8; + cmsUInt32Number i; + + it8 = (cmsIT8*) _cmsMallocZero(ContextID, sizeof(cmsIT8)); + if (it8 == NULL) return NULL; + + AllocTable(it8); + + it8->MemoryBlock = NULL; + it8->MemorySink = NULL; + + it8 ->nTable = 0; + + it8->ContextID = ContextID; + it8->Allocator.Used = 0; + it8->Allocator.Block = NULL; + it8->Allocator.BlockSize = 0; + + it8->ValidKeywords = NULL; + it8->ValidSampleID = NULL; + + it8 -> sy = SNONE; + it8 -> ch = ' '; + it8 -> Source = NULL; + it8 -> inum = 0; + it8 -> dnum = 0.0; + + it8->FileStack[0] = (FILECTX*)AllocChunk(it8, sizeof(FILECTX)); + it8->IncludeSP = 0; + it8 -> lineno = 1; + + strcpy(it8->DoubleFormatter, DEFAULT_DBL_FORMAT); + cmsIT8SetSheetType((cmsHANDLE) it8, "CGATS.17"); + + // Initialize predefined properties & data + + for (i=0; i < NUMPREDEFINEDPROPS; i++) + AddAvailableProperty(it8, PredefinedProperties[i].id, PredefinedProperties[i].as); + + for (i=0; i < NUMPREDEFINEDSAMPLEID; i++) + AddAvailableSampleID(it8, PredefinedSampleID[i]); + + + return (cmsHANDLE) it8; +} + + +const char* CMSEXPORT cmsIT8GetSheetType(cmsHANDLE hIT8) +{ + return GetTable((cmsIT8*) hIT8)->SheetType; +} + +cmsBool CMSEXPORT cmsIT8SetSheetType(cmsHANDLE hIT8, const char* Type) +{ + TABLE* t = GetTable((cmsIT8*) hIT8); + + strncpy(t ->SheetType, Type, MAXSTR-1); + t ->SheetType[MAXSTR-1] = 0; + return TRUE; +} + +cmsBool CMSEXPORT cmsIT8SetComment(cmsHANDLE hIT8, const char* Val) +{ + cmsIT8* it8 = (cmsIT8*) hIT8; + + if (!Val) return FALSE; + if (!*Val) return FALSE; + + return AddToList(it8, &GetTable(it8)->HeaderList, "# ", NULL, Val, WRITE_UNCOOKED) != NULL; +} + +// Sets a property +cmsBool CMSEXPORT cmsIT8SetPropertyStr(cmsHANDLE hIT8, const char* Key, const char *Val) +{ + cmsIT8* it8 = (cmsIT8*) hIT8; + + if (!Val) return FALSE; + if (!*Val) return FALSE; + + return AddToList(it8, &GetTable(it8)->HeaderList, Key, NULL, Val, WRITE_STRINGIFY) != NULL; +} + +cmsBool CMSEXPORT cmsIT8SetPropertyDbl(cmsHANDLE hIT8, const char* cProp, cmsFloat64Number Val) +{ + cmsIT8* it8 = (cmsIT8*) hIT8; + char Buffer[1024]; + + sprintf(Buffer, it8->DoubleFormatter, Val); + + return AddToList(it8, &GetTable(it8)->HeaderList, cProp, NULL, Buffer, WRITE_UNCOOKED) != NULL; +} + +cmsBool CMSEXPORT cmsIT8SetPropertyHex(cmsHANDLE hIT8, const char* cProp, cmsUInt32Number Val) +{ + cmsIT8* it8 = (cmsIT8*) hIT8; + char Buffer[1024]; + + sprintf(Buffer, "%u", Val); + + return AddToList(it8, &GetTable(it8)->HeaderList, cProp, NULL, Buffer, WRITE_HEXADECIMAL) != NULL; +} + +cmsBool CMSEXPORT cmsIT8SetPropertyUncooked(cmsHANDLE hIT8, const char* Key, const char* Buffer) +{ + cmsIT8* it8 = (cmsIT8*) hIT8; + + return AddToList(it8, &GetTable(it8)->HeaderList, Key, NULL, Buffer, WRITE_UNCOOKED) != NULL; +} + +cmsBool CMSEXPORT cmsIT8SetPropertyMulti(cmsHANDLE hIT8, const char* Key, const char* SubKey, const char *Buffer) +{ + cmsIT8* it8 = (cmsIT8*) hIT8; + + return AddToList(it8, &GetTable(it8)->HeaderList, Key, SubKey, Buffer, WRITE_PAIR) != NULL; +} + +// Gets a property +const char* CMSEXPORT cmsIT8GetProperty(cmsHANDLE hIT8, const char* Key) +{ + cmsIT8* it8 = (cmsIT8*) hIT8; + KEYVALUE* p; + + if (IsAvailableOnList(GetTable(it8) -> HeaderList, Key, NULL, &p)) + { + return p -> Value; + } + return NULL; +} + + +cmsFloat64Number CMSEXPORT cmsIT8GetPropertyDbl(cmsHANDLE hIT8, const char* cProp) +{ + const char *v = cmsIT8GetProperty(hIT8, cProp); + + if (v == NULL) return 0.0; + + return ParseFloatNumber(v); +} + +const char* CMSEXPORT cmsIT8GetPropertyMulti(cmsHANDLE hIT8, const char* Key, const char *SubKey) +{ + cmsIT8* it8 = (cmsIT8*) hIT8; + KEYVALUE* p; + + if (IsAvailableOnList(GetTable(it8) -> HeaderList, Key, SubKey, &p)) { + return p -> Value; + } + return NULL; +} + +// ----------------------------------------------------------------- Datasets + + +static +void AllocateDataFormat(cmsIT8* it8) +{ + TABLE* t = GetTable(it8); + + if (t -> DataFormat) return; // Already allocated + + t -> nSamples = (int) cmsIT8GetPropertyDbl(it8, "NUMBER_OF_FIELDS"); + + if (t -> nSamples <= 0) { + + SynError(it8, "AllocateDataFormat: Unknown NUMBER_OF_FIELDS"); + t -> nSamples = 10; + } + + t -> DataFormat = (char**) AllocChunk (it8, ((cmsUInt32Number) t->nSamples + 1) * sizeof(char *)); + if (t->DataFormat == NULL) { + + SynError(it8, "AllocateDataFormat: Unable to allocate dataFormat array"); + } + +} + +static +const char *GetDataFormat(cmsIT8* it8, int n) +{ + TABLE* t = GetTable(it8); + + if (t->DataFormat) + return t->DataFormat[n]; + + return NULL; +} + +static +cmsBool SetDataFormat(cmsIT8* it8, int n, const char *label) +{ + TABLE* t = GetTable(it8); + + if (!t->DataFormat) + AllocateDataFormat(it8); + + if (n > t -> nSamples) { + SynError(it8, "More than NUMBER_OF_FIELDS fields."); + return FALSE; + } + + if (t->DataFormat) { + t->DataFormat[n] = AllocString(it8, label); + } + + return TRUE; +} + + +cmsBool CMSEXPORT cmsIT8SetDataFormat(cmsHANDLE h, int n, const char *Sample) +{ + cmsIT8* it8 = (cmsIT8*) h; + return SetDataFormat(it8, n, Sample); +} + +static +void AllocateDataSet(cmsIT8* it8) +{ + TABLE* t = GetTable(it8); + + if (t -> Data) return; // Already allocated + + t-> nSamples = atoi(cmsIT8GetProperty(it8, "NUMBER_OF_FIELDS")); + t-> nPatches = atoi(cmsIT8GetProperty(it8, "NUMBER_OF_SETS")); + + t-> Data = (char**)AllocChunk (it8, ((cmsUInt32Number) t->nSamples + 1) * ((cmsUInt32Number) t->nPatches + 1) *sizeof (char*)); + if (t->Data == NULL) { + + SynError(it8, "AllocateDataSet: Unable to allocate data array"); + } + +} + +static +char* GetData(cmsIT8* it8, int nSet, int nField) +{ + TABLE* t = GetTable(it8); + int nSamples = t -> nSamples; + int nPatches = t -> nPatches; + + if (nSet >= nPatches || nField >= nSamples) + return NULL; + + if (!t->Data) return NULL; + return t->Data [nSet * nSamples + nField]; +} + +static +cmsBool SetData(cmsIT8* it8, int nSet, int nField, const char *Val) +{ + TABLE* t = GetTable(it8); + + if (!t->Data) + AllocateDataSet(it8); + + if (!t->Data) return FALSE; + + if (nSet > t -> nPatches || nSet < 0) { + + return SynError(it8, "Patch %d out of range, there are %d patches", nSet, t -> nPatches); + } + + if (nField > t ->nSamples || nField < 0) { + return SynError(it8, "Sample %d out of range, there are %d samples", nField, t ->nSamples); + + } + + t->Data [nSet * t -> nSamples + nField] = AllocString(it8, Val); + return TRUE; +} + + +// --------------------------------------------------------------- File I/O + + +// Writes a string to file +static +void WriteStr(SAVESTREAM* f, const char *str) +{ + cmsUInt32Number len; + + if (str == NULL) + str = " "; + + // Length to write + len = (cmsUInt32Number) strlen(str); + f ->Used += len; + + + if (f ->stream) { // Should I write it to a file? + + if (fwrite(str, 1, len, f->stream) != len) { + cmsSignalError(0, cmsERROR_WRITE, "Write to file error in CGATS parser"); + return; + } + + } + else { // Or to a memory block? + + if (f ->Base) { // Am I just counting the bytes? + + if (f ->Used > f ->Max) { + + cmsSignalError(0, cmsERROR_WRITE, "Write to memory overflows in CGATS parser"); + return; + } + + memmove(f ->Ptr, str, len); + f->Ptr += len; + } + + } +} + + +// Write formatted + +static +void Writef(SAVESTREAM* f, const char* frm, ...) +{ + char Buffer[4096]; + va_list args; + + va_start(args, frm); + vsnprintf(Buffer, 4095, frm, args); + Buffer[4095] = 0; + WriteStr(f, Buffer); + va_end(args); + +} + +// Writes full header +static +void WriteHeader(cmsIT8* it8, SAVESTREAM* fp) +{ + KEYVALUE* p; + TABLE* t = GetTable(it8); + + // Writes the type + WriteStr(fp, t->SheetType); + WriteStr(fp, "\n"); + + for (p = t->HeaderList; (p != NULL); p = p->Next) + { + if (*p ->Keyword == '#') { + + char* Pt; + + WriteStr(fp, "#\n# "); + for (Pt = p ->Value; *Pt; Pt++) { + + + Writef(fp, "%c", *Pt); + + if (*Pt == '\n') { + WriteStr(fp, "# "); + } + } + + WriteStr(fp, "\n#\n"); + continue; + } + + + if (!IsAvailableOnList(it8-> ValidKeywords, p->Keyword, NULL, NULL)) { + +#ifdef CMS_STRICT_CGATS + WriteStr(fp, "KEYWORD\t\""); + WriteStr(fp, p->Keyword); + WriteStr(fp, "\"\n"); +#endif + + AddAvailableProperty(it8, p->Keyword, WRITE_UNCOOKED); + } + + WriteStr(fp, p->Keyword); + if (p->Value) { + + switch (p ->WriteAs) { + + case WRITE_UNCOOKED: + Writef(fp, "\t%s", p ->Value); + break; + + case WRITE_STRINGIFY: + Writef(fp, "\t\"%s\"", p->Value ); + break; + + case WRITE_HEXADECIMAL: + Writef(fp, "\t0x%X", atoi(p ->Value)); + break; + + case WRITE_BINARY: + Writef(fp, "\t0x%B", atoi(p ->Value)); + break; + + case WRITE_PAIR: + Writef(fp, "\t\"%s,%s\"", p->Subkey, p->Value); + break; + + default: SynError(it8, "Unknown write mode %d", p ->WriteAs); + return; + } + } + + WriteStr (fp, "\n"); + } + +} + + +// Writes the data format +static +void WriteDataFormat(SAVESTREAM* fp, cmsIT8* it8) +{ + int i, nSamples; + TABLE* t = GetTable(it8); + + if (!t -> DataFormat) return; + + WriteStr(fp, "BEGIN_DATA_FORMAT\n"); + WriteStr(fp, " "); + nSamples = atoi(cmsIT8GetProperty(it8, "NUMBER_OF_FIELDS")); + + for (i = 0; i < nSamples; i++) { + + WriteStr(fp, t->DataFormat[i]); + WriteStr(fp, ((i == (nSamples-1)) ? "\n" : "\t")); + } + + WriteStr (fp, "END_DATA_FORMAT\n"); +} + + +// Writes data array +static +void WriteData(SAVESTREAM* fp, cmsIT8* it8) +{ + int i, j; + TABLE* t = GetTable(it8); + + if (!t->Data) return; + + WriteStr (fp, "BEGIN_DATA\n"); + + t->nPatches = atoi(cmsIT8GetProperty(it8, "NUMBER_OF_SETS")); + + for (i = 0; i < t-> nPatches; i++) { + + WriteStr(fp, " "); + + for (j = 0; j < t->nSamples; j++) { + + char *ptr = t->Data[i*t->nSamples+j]; + + if (ptr == NULL) WriteStr(fp, "\"\""); + else { + // If value contains whitespace, enclose within quote + + if (strchr(ptr, ' ') != NULL) { + + WriteStr(fp, "\""); + WriteStr(fp, ptr); + WriteStr(fp, "\""); + } + else + WriteStr(fp, ptr); + } + + WriteStr(fp, ((j == (t->nSamples-1)) ? "\n" : "\t")); + } + } + WriteStr (fp, "END_DATA\n"); +} + + + +// Saves whole file +cmsBool CMSEXPORT cmsIT8SaveToFile(cmsHANDLE hIT8, const char* cFileName) +{ + SAVESTREAM sd; + cmsUInt32Number i; + cmsIT8* it8 = (cmsIT8*) hIT8; + + memset(&sd, 0, sizeof(sd)); + + sd.stream = fopen(cFileName, "wt"); + if (!sd.stream) return FALSE; + + for (i=0; i < it8 ->TablesCount; i++) { + + cmsIT8SetTable(hIT8, i); + WriteHeader(it8, &sd); + WriteDataFormat(&sd, it8); + WriteData(&sd, it8); + } + + if (fclose(sd.stream) != 0) return FALSE; + + return TRUE; +} + + +// Saves to memory +cmsBool CMSEXPORT cmsIT8SaveToMem(cmsHANDLE hIT8, void *MemPtr, cmsUInt32Number* BytesNeeded) +{ + SAVESTREAM sd; + cmsUInt32Number i; + cmsIT8* it8 = (cmsIT8*) hIT8; + + memset(&sd, 0, sizeof(sd)); + + sd.stream = NULL; + sd.Base = (cmsUInt8Number*) MemPtr; + sd.Ptr = sd.Base; + + sd.Used = 0; + + if (sd.Base) + sd.Max = *BytesNeeded; // Write to memory? + else + sd.Max = 0; // Just counting the needed bytes + + for (i=0; i < it8 ->TablesCount; i++) { + + cmsIT8SetTable(hIT8, i); + WriteHeader(it8, &sd); + WriteDataFormat(&sd, it8); + WriteData(&sd, it8); + } + + sd.Used++; // The \0 at the very end + + if (sd.Base) + *sd.Ptr = 0; + + *BytesNeeded = sd.Used; + + return TRUE; +} + + +// -------------------------------------------------------------- Higer level parsing + +static +cmsBool DataFormatSection(cmsIT8* it8) +{ + int iField = 0; + TABLE* t = GetTable(it8); + + InSymbol(it8); // Eats "BEGIN_DATA_FORMAT" + CheckEOLN(it8); + + while (it8->sy != SEND_DATA_FORMAT && + it8->sy != SEOLN && + it8->sy != SEOF && + it8->sy != SSYNERROR) { + + if (it8->sy != SIDENT) { + + return SynError(it8, "Sample type expected"); + } + + if (!SetDataFormat(it8, iField, it8->id)) return FALSE; + iField++; + + InSymbol(it8); + SkipEOLN(it8); + } + + SkipEOLN(it8); + Skip(it8, SEND_DATA_FORMAT); + SkipEOLN(it8); + + if (iField != t ->nSamples) { + SynError(it8, "Count mismatch. NUMBER_OF_FIELDS was %d, found %d\n", t ->nSamples, iField); + + + } + + return TRUE; +} + + + +static +cmsBool DataSection (cmsIT8* it8) +{ + int iField = 0; + int iSet = 0; + char Buffer[256]; + TABLE* t = GetTable(it8); + + InSymbol(it8); // Eats "BEGIN_DATA" + CheckEOLN(it8); + + if (!t->Data) + AllocateDataSet(it8); + + while (it8->sy != SEND_DATA && it8->sy != SEOF) + { + if (iField >= t -> nSamples) { + iField = 0; + iSet++; + + } + + if (it8->sy != SEND_DATA && it8->sy != SEOF) { + + if (!GetVal(it8, Buffer, 255, "Sample data expected")) + return FALSE; + + if (!SetData(it8, iSet, iField, Buffer)) + return FALSE; + + iField++; + + InSymbol(it8); + SkipEOLN(it8); + } + } + + SkipEOLN(it8); + Skip(it8, SEND_DATA); + SkipEOLN(it8); + + // Check for data completion. + + if ((iSet+1) != t -> nPatches) + return SynError(it8, "Count mismatch. NUMBER_OF_SETS was %d, found %d\n", t ->nPatches, iSet+1); + + return TRUE; +} + + + + +static +cmsBool HeaderSection(cmsIT8* it8) +{ + char VarName[MAXID]; + char Buffer[MAXSTR]; + KEYVALUE* Key; + + while (it8->sy != SEOF && + it8->sy != SSYNERROR && + it8->sy != SBEGIN_DATA_FORMAT && + it8->sy != SBEGIN_DATA) { + + + switch (it8 -> sy) { + + case SKEYWORD: + InSymbol(it8); + if (!GetVal(it8, Buffer, MAXSTR-1, "Keyword expected")) return FALSE; + if (!AddAvailableProperty(it8, Buffer, WRITE_UNCOOKED)) return FALSE; + InSymbol(it8); + break; + + + case SDATA_FORMAT_ID: + InSymbol(it8); + if (!GetVal(it8, Buffer, MAXSTR-1, "Keyword expected")) return FALSE; + if (!AddAvailableSampleID(it8, Buffer)) return FALSE; + InSymbol(it8); + break; + + + case SIDENT: + strncpy(VarName, it8->id, MAXID-1); + VarName[MAXID-1] = 0; + + if (!IsAvailableOnList(it8-> ValidKeywords, VarName, NULL, &Key)) { + +#ifdef CMS_STRICT_CGATS + return SynError(it8, "Undefined keyword '%s'", VarName); +#else + Key = AddAvailableProperty(it8, VarName, WRITE_UNCOOKED); + if (Key == NULL) return FALSE; +#endif + } + + InSymbol(it8); + if (!GetVal(it8, Buffer, MAXSTR-1, "Property data expected")) return FALSE; + + if(Key->WriteAs != WRITE_PAIR) { + AddToList(it8, &GetTable(it8)->HeaderList, VarName, NULL, Buffer, + (it8->sy == SSTRING) ? WRITE_STRINGIFY : WRITE_UNCOOKED); + } + else { + const char *Subkey; + char *Nextkey; + if (it8->sy != SSTRING) + return SynError(it8, "Invalid value '%s' for property '%s'.", Buffer, VarName); + + // chop the string as a list of "subkey, value" pairs, using ';' as a separator + for (Subkey = Buffer; Subkey != NULL; Subkey = Nextkey) + { + char *Value, *temp; + + // identify token pair boundary + Nextkey = (char*) strchr(Subkey, ';'); + if(Nextkey) + *Nextkey++ = '\0'; + + // for each pair, split the subkey and the value + Value = (char*) strrchr(Subkey, ','); + if(Value == NULL) + return SynError(it8, "Invalid value for property '%s'.", VarName); + + // gobble the spaces before the coma, and the coma itself + temp = Value++; + do *temp-- = '\0'; while(temp >= Subkey && *temp == ' '); + + // gobble any space at the right + temp = Value + strlen(Value) - 1; + while(*temp == ' ') *temp-- = '\0'; + + // trim the strings from the left + Subkey += strspn(Subkey, " "); + Value += strspn(Value, " "); + + if(Subkey[0] == 0 || Value[0] == 0) + return SynError(it8, "Invalid value for property '%s'.", VarName); + AddToList(it8, &GetTable(it8)->HeaderList, VarName, Subkey, Value, WRITE_PAIR); + } + } + + InSymbol(it8); + break; + + + case SEOLN: break; + + default: + return SynError(it8, "expected keyword or identifier"); + } + + SkipEOLN(it8); + } + + return TRUE; + +} + + +static +void ReadType(cmsIT8* it8, char* SheetTypePtr) +{ + // First line is a very special case. + + while (isseparator(it8->ch)) + NextCh(it8); + + while (it8->ch != '\r' && it8 ->ch != '\n' && it8->ch != '\t' && it8 -> ch != -1) { + + *SheetTypePtr++= (char) it8 ->ch; + NextCh(it8); + } + + *SheetTypePtr = 0; +} + + +static +cmsBool ParseIT8(cmsIT8* it8, cmsBool nosheet) +{ + char* SheetTypePtr = it8 ->Tab[0].SheetType; + + if (nosheet == 0) { + ReadType(it8, SheetTypePtr); + } + + InSymbol(it8); + + SkipEOLN(it8); + + while (it8-> sy != SEOF && + it8-> sy != SSYNERROR) { + + switch (it8 -> sy) { + + case SBEGIN_DATA_FORMAT: + if (!DataFormatSection(it8)) return FALSE; + break; + + case SBEGIN_DATA: + + if (!DataSection(it8)) return FALSE; + + if (it8 -> sy != SEOF) { + + AllocTable(it8); + it8 ->nTable = it8 ->TablesCount - 1; + + // Read sheet type if present. We only support identifier and string. + // is a type string + // anything else, is not a type string + if (nosheet == 0) { + + if (it8 ->sy == SIDENT) { + + // May be a type sheet or may be a prop value statement. We cannot use insymbol in + // this special case... + while (isseparator(it8->ch)) + NextCh(it8); + + // If a newline is found, then this is a type string + if (it8 ->ch == '\n' || it8->ch == '\r') { + + cmsIT8SetSheetType(it8, it8 ->id); + InSymbol(it8); + } + else + { + // It is not. Just continue + cmsIT8SetSheetType(it8, ""); + } + } + else + // Validate quoted strings + if (it8 ->sy == SSTRING) { + cmsIT8SetSheetType(it8, it8 ->str); + InSymbol(it8); + } + } + + } + break; + + case SEOLN: + SkipEOLN(it8); + break; + + default: + if (!HeaderSection(it8)) return FALSE; + } + + } + + return (it8 -> sy != SSYNERROR); +} + + + +// Init usefull pointers + +static +void CookPointers(cmsIT8* it8) +{ + int idField, i; + char* Fld; + cmsUInt32Number j; + cmsUInt32Number nOldTable = it8 ->nTable; + + for (j=0; j < it8 ->TablesCount; j++) { + + TABLE* t = it8 ->Tab + j; + + t -> SampleID = 0; + it8 ->nTable = j; + + for (idField = 0; idField < t -> nSamples; idField++) + { + if (t ->DataFormat == NULL){ + SynError(it8, "Undefined DATA_FORMAT"); + return; + } + + Fld = t->DataFormat[idField]; + if (!Fld) continue; + + + if (cmsstrcasecmp(Fld, "SAMPLE_ID") == 0) { + + t -> SampleID = idField; + + for (i=0; i < t -> nPatches; i++) { + + char *Data = GetData(it8, i, idField); + if (Data) { + char Buffer[256]; + + strncpy(Buffer, Data, 255); + Buffer[255] = 0; + + if (strlen(Buffer) <= strlen(Data)) + strcpy(Data, Buffer); + else + SetData(it8, i, idField, Buffer); + + } + } + + } + + // "LABEL" is an extension. It keeps references to forward tables + + if ((cmsstrcasecmp(Fld, "LABEL") == 0) || Fld[0] == '$' ) { + + // Search for table references... + for (i=0; i < t -> nPatches; i++) { + + char *Label = GetData(it8, i, idField); + + if (Label) { + + cmsUInt32Number k; + + // This is the label, search for a table containing + // this property + + for (k=0; k < it8 ->TablesCount; k++) { + + TABLE* Table = it8 ->Tab + k; + KEYVALUE* p; + + if (IsAvailableOnList(Table->HeaderList, Label, NULL, &p)) { + + // Available, keep type and table + char Buffer[256]; + + char *Type = p ->Value; + int nTable = (int) k; + + snprintf(Buffer, 255, "%s %d %s", Label, nTable, Type ); + + SetData(it8, i, idField, Buffer); + } + } + + + } + + } + + + } + + } + } + + it8 ->nTable = nOldTable; +} + +// Try to infere if the file is a CGATS/IT8 file at all. Read first line +// that should be something like some printable characters plus a \n +// returns 0 if this is not like a CGATS, or an integer otherwise. This integer is the number of words in first line? +static +int IsMyBlock(cmsUInt8Number* Buffer, int n) +{ + int words = 1, space = 0, quot = 0; + int i; + + if (n < 10) return 0; // Too small + + if (n > 132) + n = 132; + + for (i = 1; i < n; i++) { + + switch(Buffer[i]) + { + case '\n': + case '\r': + return ((quot == 1) || (words > 2)) ? 0 : words; + case '\t': + case ' ': + if(!quot && !space) + space = 1; + break; + case '\"': + quot = !quot; + break; + default: + if (Buffer[i] < 32) return 0; + if (Buffer[i] > 127) return 0; + words += space; + space = 0; + break; + } + } + + return 0; +} + + +static +cmsBool IsMyFile(const char* FileName) +{ + FILE *fp; + cmsUInt32Number Size; + cmsUInt8Number Ptr[133]; + + fp = fopen(FileName, "rt"); + if (!fp) { + cmsSignalError(0, cmsERROR_FILE, "File '%s' not found", FileName); + return FALSE; + } + + Size = (cmsUInt32Number) fread(Ptr, 1, 132, fp); + + if (fclose(fp) != 0) + return FALSE; + + Ptr[Size] = '\0'; + + return IsMyBlock(Ptr, Size); +} + +// ---------------------------------------------------------- Exported routines + + +cmsHANDLE CMSEXPORT cmsIT8LoadFromMem(cmsContext ContextID, void *Ptr, cmsUInt32Number len) +{ + cmsHANDLE hIT8; + cmsIT8* it8; + int type; + + _cmsAssert(Ptr != NULL); + _cmsAssert(len != 0); + + type = IsMyBlock((cmsUInt8Number*)Ptr, len); + if (type == 0) return NULL; + + hIT8 = cmsIT8Alloc(ContextID); + if (!hIT8) return NULL; + + it8 = (cmsIT8*) hIT8; + it8 ->MemoryBlock = (char*) _cmsMalloc(ContextID, len + 1); + + strncpy(it8 ->MemoryBlock, (const char*) Ptr, len); + it8 ->MemoryBlock[len] = 0; + + strncpy(it8->FileStack[0]->FileName, "", cmsMAX_PATH-1); + it8-> Source = it8 -> MemoryBlock; + + if (!ParseIT8(it8, type-1)) { + + cmsIT8Free(hIT8); + return FALSE; + } + + CookPointers(it8); + it8 ->nTable = 0; + + _cmsFree(ContextID, it8->MemoryBlock); + it8 -> MemoryBlock = NULL; + + return hIT8; + + +} + + +cmsHANDLE CMSEXPORT cmsIT8LoadFromFile(cmsContext ContextID, const char* cFileName) +{ + + cmsHANDLE hIT8; + cmsIT8* it8; + int type; + + _cmsAssert(cFileName != NULL); + + type = IsMyFile(cFileName); + if (type == 0) return NULL; + + hIT8 = cmsIT8Alloc(ContextID); + it8 = (cmsIT8*) hIT8; + if (!hIT8) return NULL; + + + it8 ->FileStack[0]->Stream = fopen(cFileName, "rt"); + + if (!it8 ->FileStack[0]->Stream) { + cmsIT8Free(hIT8); + return NULL; + } + + + strncpy(it8->FileStack[0]->FileName, cFileName, cmsMAX_PATH-1); + it8->FileStack[0]->FileName[cmsMAX_PATH-1] = 0; + + if (!ParseIT8(it8, type-1)) { + + fclose(it8 ->FileStack[0]->Stream); + cmsIT8Free(hIT8); + return NULL; + } + + CookPointers(it8); + it8 ->nTable = 0; + + if (fclose(it8 ->FileStack[0]->Stream)!= 0) { + cmsIT8Free(hIT8); + return NULL; + } + + return hIT8; + +} + +int CMSEXPORT cmsIT8EnumDataFormat(cmsHANDLE hIT8, char ***SampleNames) +{ + cmsIT8* it8 = (cmsIT8*) hIT8; + TABLE* t; + + _cmsAssert(hIT8 != NULL); + + t = GetTable(it8); + + if (SampleNames) + *SampleNames = t -> DataFormat; + return t -> nSamples; +} + + +cmsUInt32Number CMSEXPORT cmsIT8EnumProperties(cmsHANDLE hIT8, char ***PropertyNames) +{ + cmsIT8* it8 = (cmsIT8*) hIT8; + KEYVALUE* p; + cmsUInt32Number n; + char **Props; + TABLE* t; + + _cmsAssert(hIT8 != NULL); + + t = GetTable(it8); + + // Pass#1 - count properties + + n = 0; + for (p = t -> HeaderList; p != NULL; p = p->Next) { + n++; + } + + + Props = (char **) AllocChunk(it8, sizeof(char *) * n); + + // Pass#2 - Fill pointers + n = 0; + for (p = t -> HeaderList; p != NULL; p = p->Next) { + Props[n++] = p -> Keyword; + } + + *PropertyNames = Props; + return n; +} + +cmsUInt32Number CMSEXPORT cmsIT8EnumPropertyMulti(cmsHANDLE hIT8, const char* cProp, const char ***SubpropertyNames) +{ + cmsIT8* it8 = (cmsIT8*) hIT8; + KEYVALUE *p, *tmp; + cmsUInt32Number n; + const char **Props; + TABLE* t; + + _cmsAssert(hIT8 != NULL); + + + t = GetTable(it8); + + if(!IsAvailableOnList(t->HeaderList, cProp, NULL, &p)) { + *SubpropertyNames = 0; + return 0; + } + + // Pass#1 - count properties + + n = 0; + for (tmp = p; tmp != NULL; tmp = tmp->NextSubkey) { + if(tmp->Subkey != NULL) + n++; + } + + + Props = (const char **) AllocChunk(it8, sizeof(char *) * n); + + // Pass#2 - Fill pointers + n = 0; + for (tmp = p; tmp != NULL; tmp = tmp->NextSubkey) { + if(tmp->Subkey != NULL) + Props[n++] = p ->Subkey; + } + + *SubpropertyNames = Props; + return n; +} + +static +int LocatePatch(cmsIT8* it8, const char* cPatch) +{ + int i; + const char *data; + TABLE* t = GetTable(it8); + + for (i=0; i < t-> nPatches; i++) { + + data = GetData(it8, i, t->SampleID); + + if (data != NULL) { + + if (cmsstrcasecmp(data, cPatch) == 0) + return i; + } + } + + // SynError(it8, "Couldn't find patch '%s'\n", cPatch); + return -1; +} + + +static +int LocateEmptyPatch(cmsIT8* it8) +{ + int i; + const char *data; + TABLE* t = GetTable(it8); + + for (i=0; i < t-> nPatches; i++) { + + data = GetData(it8, i, t->SampleID); + + if (data == NULL) + return i; + + } + + return -1; +} + +static +int LocateSample(cmsIT8* it8, const char* cSample) +{ + int i; + const char *fld; + TABLE* t = GetTable(it8); + + for (i=0; i < t->nSamples; i++) { + + fld = GetDataFormat(it8, i); + if (cmsstrcasecmp(fld, cSample) == 0) + return i; + } + + return -1; + +} + + +int CMSEXPORT cmsIT8FindDataFormat(cmsHANDLE hIT8, const char* cSample) +{ + cmsIT8* it8 = (cmsIT8*) hIT8; + + _cmsAssert(hIT8 != NULL); + + return LocateSample(it8, cSample); +} + + + +const char* CMSEXPORT cmsIT8GetDataRowCol(cmsHANDLE hIT8, int row, int col) +{ + cmsIT8* it8 = (cmsIT8*) hIT8; + + _cmsAssert(hIT8 != NULL); + + return GetData(it8, row, col); +} + + +cmsFloat64Number CMSEXPORT cmsIT8GetDataRowColDbl(cmsHANDLE hIT8, int row, int col) +{ + const char* Buffer; + + Buffer = cmsIT8GetDataRowCol(hIT8, row, col); + + if (Buffer == NULL) return 0.0; + + return ParseFloatNumber(Buffer); +} + + +cmsBool CMSEXPORT cmsIT8SetDataRowCol(cmsHANDLE hIT8, int row, int col, const char* Val) +{ + cmsIT8* it8 = (cmsIT8*) hIT8; + + _cmsAssert(hIT8 != NULL); + + return SetData(it8, row, col, Val); +} + + +cmsBool CMSEXPORT cmsIT8SetDataRowColDbl(cmsHANDLE hIT8, int row, int col, cmsFloat64Number Val) +{ + cmsIT8* it8 = (cmsIT8*) hIT8; + char Buff[256]; + + _cmsAssert(hIT8 != NULL); + + sprintf(Buff, it8->DoubleFormatter, Val); + + return SetData(it8, row, col, Buff); +} + + + +const char* CMSEXPORT cmsIT8GetData(cmsHANDLE hIT8, const char* cPatch, const char* cSample) +{ + cmsIT8* it8 = (cmsIT8*) hIT8; + int iField, iSet; + + _cmsAssert(hIT8 != NULL); + + iField = LocateSample(it8, cSample); + if (iField < 0) { + return NULL; + } + + iSet = LocatePatch(it8, cPatch); + if (iSet < 0) { + return NULL; + } + + return GetData(it8, iSet, iField); +} + + +cmsFloat64Number CMSEXPORT cmsIT8GetDataDbl(cmsHANDLE it8, const char* cPatch, const char* cSample) +{ + const char* Buffer; + + Buffer = cmsIT8GetData(it8, cPatch, cSample); + + return ParseFloatNumber(Buffer); +} + + + +cmsBool CMSEXPORT cmsIT8SetData(cmsHANDLE hIT8, const char* cPatch, const char* cSample, const char *Val) +{ + cmsIT8* it8 = (cmsIT8*) hIT8; + int iField, iSet; + TABLE* t; + + _cmsAssert(hIT8 != NULL); + + t = GetTable(it8); + + iField = LocateSample(it8, cSample); + + if (iField < 0) + return FALSE; + + if (t-> nPatches == 0) { + + AllocateDataFormat(it8); + AllocateDataSet(it8); + CookPointers(it8); + } + + if (cmsstrcasecmp(cSample, "SAMPLE_ID") == 0) { + + iSet = LocateEmptyPatch(it8); + if (iSet < 0) { + return SynError(it8, "Couldn't add more patches '%s'\n", cPatch); + } + + iField = t -> SampleID; + } + else { + iSet = LocatePatch(it8, cPatch); + if (iSet < 0) { + return FALSE; + } + } + + return SetData(it8, iSet, iField, Val); +} + + +cmsBool CMSEXPORT cmsIT8SetDataDbl(cmsHANDLE hIT8, const char* cPatch, + const char* cSample, + cmsFloat64Number Val) +{ + cmsIT8* it8 = (cmsIT8*) hIT8; + char Buff[256]; + + _cmsAssert(hIT8 != NULL); + + snprintf(Buff, 255, it8->DoubleFormatter, Val); + return cmsIT8SetData(hIT8, cPatch, cSample, Buff); +} + +// Buffer should get MAXSTR at least + +const char* CMSEXPORT cmsIT8GetPatchName(cmsHANDLE hIT8, int nPatch, char* buffer) +{ + cmsIT8* it8 = (cmsIT8*) hIT8; + TABLE* t; + char* Data; + + _cmsAssert(hIT8 != NULL); + + t = GetTable(it8); + Data = GetData(it8, nPatch, t->SampleID); + + if (!Data) return NULL; + if (!buffer) return Data; + + strncpy(buffer, Data, MAXSTR-1); + buffer[MAXSTR-1] = 0; + return buffer; +} + +int CMSEXPORT cmsIT8GetPatchByName(cmsHANDLE hIT8, const char *cPatch) +{ + _cmsAssert(hIT8 != NULL); + + return LocatePatch((cmsIT8*)hIT8, cPatch); +} + +cmsUInt32Number CMSEXPORT cmsIT8TableCount(cmsHANDLE hIT8) +{ + cmsIT8* it8 = (cmsIT8*) hIT8; + + _cmsAssert(hIT8 != NULL); + + return it8 ->TablesCount; +} + +// This handles the "LABEL" extension. +// Label, nTable, Type + +int CMSEXPORT cmsIT8SetTableByLabel(cmsHANDLE hIT8, const char* cSet, const char* cField, const char* ExpectedType) +{ + const char* cLabelFld; + char Type[256], Label[256]; + int nTable; + + _cmsAssert(hIT8 != NULL); + + if (cField != NULL && *cField == 0) + cField = "LABEL"; + + if (cField == NULL) + cField = "LABEL"; + + cLabelFld = cmsIT8GetData(hIT8, cSet, cField); + if (!cLabelFld) return -1; + + if (sscanf(cLabelFld, "%255s %d %255s", Label, &nTable, Type) != 3) + return -1; + + if (ExpectedType != NULL && *ExpectedType == 0) + ExpectedType = NULL; + + if (ExpectedType) { + + if (cmsstrcasecmp(Type, ExpectedType) != 0) return -1; + } + + return cmsIT8SetTable(hIT8, nTable); +} + + +cmsBool CMSEXPORT cmsIT8SetIndexColumn(cmsHANDLE hIT8, const char* cSample) +{ + cmsIT8* it8 = (cmsIT8*) hIT8; + int pos; + + _cmsAssert(hIT8 != NULL); + + pos = LocateSample(it8, cSample); + if(pos == -1) + return FALSE; + + it8->Tab[it8->nTable].SampleID = pos; + return TRUE; +} + + +void CMSEXPORT cmsIT8DefineDblFormat(cmsHANDLE hIT8, const char* Formatter) +{ + cmsIT8* it8 = (cmsIT8*) hIT8; + + _cmsAssert(hIT8 != NULL); + + if (Formatter == NULL) + strcpy(it8->DoubleFormatter, DEFAULT_DBL_FORMAT); + else + strncpy(it8->DoubleFormatter, Formatter, sizeof(it8->DoubleFormatter)); + + it8 ->DoubleFormatter[sizeof(it8 ->DoubleFormatter)-1] = 0; +} + diff --git a/jni/lcms2-2.5/src/cmscnvrt.c b/jni/lcms2-2.5/src/cmscnvrt.c new file mode 100644 index 00000000..908f7874 --- /dev/null +++ b/jni/lcms2-2.5/src/cmscnvrt.c @@ -0,0 +1,1070 @@ +//--------------------------------------------------------------------------------- +// +// Little Color Management System +// Copyright (c) 1998-2012 Marti Maria Saguer +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//--------------------------------------------------------------------------------- +// + +#include "lcms2_internal.h" + + +// Link several profiles to obtain a single LUT modelling the whole color transform. Intents, Black point +// compensation and Adaptation parameters may vary across profiles. BPC and Adaptation refers to the PCS +// after the profile. I.e, BPC[0] refers to connexion between profile(0) and profile(1) +cmsPipeline* _cmsLinkProfiles(cmsContext ContextID, + cmsUInt32Number nProfiles, + cmsUInt32Number Intents[], + cmsHPROFILE hProfiles[], + cmsBool BPC[], + cmsFloat64Number AdaptationStates[], + cmsUInt32Number dwFlags); + +//--------------------------------------------------------------------------------- + +// This is the default routine for ICC-style intents. A user may decide to override it by using a plugin. +// Supported intents are perceptual, relative colorimetric, saturation and ICC-absolute colorimetric +static +cmsPipeline* DefaultICCintents(cmsContext ContextID, + cmsUInt32Number nProfiles, + cmsUInt32Number Intents[], + cmsHPROFILE hProfiles[], + cmsBool BPC[], + cmsFloat64Number AdaptationStates[], + cmsUInt32Number dwFlags); + +//--------------------------------------------------------------------------------- + +// This is the entry for black-preserving K-only intents, which are non-ICC. Last profile have to be a output profile +// to do the trick (no devicelinks allowed at that position) +static +cmsPipeline* BlackPreservingKOnlyIntents(cmsContext ContextID, + cmsUInt32Number nProfiles, + cmsUInt32Number Intents[], + cmsHPROFILE hProfiles[], + cmsBool BPC[], + cmsFloat64Number AdaptationStates[], + cmsUInt32Number dwFlags); + +//--------------------------------------------------------------------------------- + +// This is the entry for black-plane preserving, which are non-ICC. Again, Last profile have to be a output profile +// to do the trick (no devicelinks allowed at that position) +static +cmsPipeline* BlackPreservingKPlaneIntents(cmsContext ContextID, + cmsUInt32Number nProfiles, + cmsUInt32Number Intents[], + cmsHPROFILE hProfiles[], + cmsBool BPC[], + cmsFloat64Number AdaptationStates[], + cmsUInt32Number dwFlags); + +//--------------------------------------------------------------------------------- + + +// This is a structure holding implementations for all supported intents. +typedef struct _cms_intents_list { + + cmsUInt32Number Intent; + char Description[256]; + cmsIntentFn Link; + struct _cms_intents_list* Next; + +} cmsIntentsList; + + +// Built-in intents +static cmsIntentsList DefaultIntents[] = { + + { INTENT_PERCEPTUAL, "Perceptual", DefaultICCintents, &DefaultIntents[1] }, + { INTENT_RELATIVE_COLORIMETRIC, "Relative colorimetric", DefaultICCintents, &DefaultIntents[2] }, + { INTENT_SATURATION, "Saturation", DefaultICCintents, &DefaultIntents[3] }, + { INTENT_ABSOLUTE_COLORIMETRIC, "Absolute colorimetric", DefaultICCintents, &DefaultIntents[4] }, + { INTENT_PRESERVE_K_ONLY_PERCEPTUAL, "Perceptual preserving black ink", BlackPreservingKOnlyIntents, &DefaultIntents[5] }, + { INTENT_PRESERVE_K_ONLY_RELATIVE_COLORIMETRIC, "Relative colorimetric preserving black ink", BlackPreservingKOnlyIntents, &DefaultIntents[6] }, + { INTENT_PRESERVE_K_ONLY_SATURATION, "Saturation preserving black ink", BlackPreservingKOnlyIntents, &DefaultIntents[7] }, + { INTENT_PRESERVE_K_PLANE_PERCEPTUAL, "Perceptual preserving black plane", BlackPreservingKPlaneIntents, &DefaultIntents[8] }, + { INTENT_PRESERVE_K_PLANE_RELATIVE_COLORIMETRIC,"Relative colorimetric preserving black plane", BlackPreservingKPlaneIntents, &DefaultIntents[9] }, + { INTENT_PRESERVE_K_PLANE_SATURATION, "Saturation preserving black plane", BlackPreservingKPlaneIntents, NULL } +}; + + +// A pointer to the begining of the list +static cmsIntentsList *Intents = DefaultIntents; + +// Search the list for a suitable intent. Returns NULL if not found +static +cmsIntentsList* SearchIntent(cmsUInt32Number Intent) +{ + cmsIntentsList* pt; + + for (pt = Intents; pt != NULL; pt = pt -> Next) + if (pt ->Intent == Intent) return pt; + + return NULL; +} + +// Black point compensation. Implemented as a linear scaling in XYZ. Black points +// should come relative to the white point. Fills an matrix/offset element m +// which is organized as a 4x4 matrix. +static +void ComputeBlackPointCompensation(const cmsCIEXYZ* BlackPointIn, + const cmsCIEXYZ* BlackPointOut, + cmsMAT3* m, cmsVEC3* off) +{ + cmsFloat64Number ax, ay, az, bx, by, bz, tx, ty, tz; + + // Now we need to compute a matrix plus an offset m and of such of + // [m]*bpin + off = bpout + // [m]*D50 + off = D50 + // + // This is a linear scaling in the form ax+b, where + // a = (bpout - D50) / (bpin - D50) + // b = - D50* (bpout - bpin) / (bpin - D50) + + tx = BlackPointIn->X - cmsD50_XYZ()->X; + ty = BlackPointIn->Y - cmsD50_XYZ()->Y; + tz = BlackPointIn->Z - cmsD50_XYZ()->Z; + + ax = (BlackPointOut->X - cmsD50_XYZ()->X) / tx; + ay = (BlackPointOut->Y - cmsD50_XYZ()->Y) / ty; + az = (BlackPointOut->Z - cmsD50_XYZ()->Z) / tz; + + bx = - cmsD50_XYZ()-> X * (BlackPointOut->X - BlackPointIn->X) / tx; + by = - cmsD50_XYZ()-> Y * (BlackPointOut->Y - BlackPointIn->Y) / ty; + bz = - cmsD50_XYZ()-> Z * (BlackPointOut->Z - BlackPointIn->Z) / tz; + + _cmsVEC3init(&m ->v[0], ax, 0, 0); + _cmsVEC3init(&m ->v[1], 0, ay, 0); + _cmsVEC3init(&m ->v[2], 0, 0, az); + _cmsVEC3init(off, bx, by, bz); + +} + + +// Approximate a blackbody illuminant based on CHAD information +static +cmsFloat64Number CHAD2Temp(const cmsMAT3* Chad) +{ + // Convert D50 across inverse CHAD to get the absolute white point + cmsVEC3 d, s; + cmsCIEXYZ Dest; + cmsCIExyY DestChromaticity; + cmsFloat64Number TempK; + cmsMAT3 m1, m2; + + m1 = *Chad; + if (!_cmsMAT3inverse(&m1, &m2)) return FALSE; + + s.n[VX] = cmsD50_XYZ() -> X; + s.n[VY] = cmsD50_XYZ() -> Y; + s.n[VZ] = cmsD50_XYZ() -> Z; + + _cmsMAT3eval(&d, &m2, &s); + + Dest.X = d.n[VX]; + Dest.Y = d.n[VY]; + Dest.Z = d.n[VZ]; + + cmsXYZ2xyY(&DestChromaticity, &Dest); + + if (!cmsTempFromWhitePoint(&TempK, &DestChromaticity)) + return -1.0; + + return TempK; +} + +// Compute a CHAD based on a given temperature +static + void Temp2CHAD(cmsMAT3* Chad, cmsFloat64Number Temp) +{ + cmsCIEXYZ White; + cmsCIExyY ChromaticityOfWhite; + + cmsWhitePointFromTemp(&ChromaticityOfWhite, Temp); + cmsxyY2XYZ(&White, &ChromaticityOfWhite); + _cmsAdaptationMatrix(Chad, NULL, &White, cmsD50_XYZ()); +} + +// Join scalings to obtain relative input to absolute and then to relative output. +// Result is stored in a 3x3 matrix +static +cmsBool ComputeAbsoluteIntent(cmsFloat64Number AdaptationState, + const cmsCIEXYZ* WhitePointIn, + const cmsMAT3* ChromaticAdaptationMatrixIn, + const cmsCIEXYZ* WhitePointOut, + const cmsMAT3* ChromaticAdaptationMatrixOut, + cmsMAT3* m) +{ + cmsMAT3 Scale, m1, m2, m3, m4; + + // Adaptation state + if (AdaptationState == 1.0) { + + // Observer is fully adapted. Keep chromatic adaptation. + // That is the standard V4 behaviour + _cmsVEC3init(&m->v[0], WhitePointIn->X / WhitePointOut->X, 0, 0); + _cmsVEC3init(&m->v[1], 0, WhitePointIn->Y / WhitePointOut->Y, 0); + _cmsVEC3init(&m->v[2], 0, 0, WhitePointIn->Z / WhitePointOut->Z); + + } + else { + + // Incomplete adaptation. This is an advanced feature. + _cmsVEC3init(&Scale.v[0], WhitePointIn->X / WhitePointOut->X, 0, 0); + _cmsVEC3init(&Scale.v[1], 0, WhitePointIn->Y / WhitePointOut->Y, 0); + _cmsVEC3init(&Scale.v[2], 0, 0, WhitePointIn->Z / WhitePointOut->Z); + + + if (AdaptationState == 0.0) { + + m1 = *ChromaticAdaptationMatrixOut; + _cmsMAT3per(&m2, &m1, &Scale); + // m2 holds CHAD from output white to D50 times abs. col. scaling + + // Observer is not adapted, undo the chromatic adaptation + _cmsMAT3per(m, &m2, ChromaticAdaptationMatrixOut); + + m3 = *ChromaticAdaptationMatrixIn; + if (!_cmsMAT3inverse(&m3, &m4)) return FALSE; + _cmsMAT3per(m, &m2, &m4); + + } else { + + cmsMAT3 MixedCHAD; + cmsFloat64Number TempSrc, TempDest, Temp; + + m1 = *ChromaticAdaptationMatrixIn; + if (!_cmsMAT3inverse(&m1, &m2)) return FALSE; + _cmsMAT3per(&m3, &m2, &Scale); + // m3 holds CHAD from input white to D50 times abs. col. scaling + + TempSrc = CHAD2Temp(ChromaticAdaptationMatrixIn); + TempDest = CHAD2Temp(ChromaticAdaptationMatrixOut); + + if (TempSrc < 0.0 || TempDest < 0.0) return FALSE; // Something went wrong + + if (_cmsMAT3isIdentity(&Scale) && fabs(TempSrc - TempDest) < 0.01) { + + _cmsMAT3identity(m); + return TRUE; + } + + Temp = (1.0 - AdaptationState) * TempDest + AdaptationState * TempSrc; + + // Get a CHAD from whatever output temperature to D50. This replaces output CHAD + Temp2CHAD(&MixedCHAD, Temp); + + _cmsMAT3per(m, &m3, &MixedCHAD); + } + + } + return TRUE; + +} + +// Just to see if m matrix should be applied +static +cmsBool IsEmptyLayer(cmsMAT3* m, cmsVEC3* off) +{ + cmsFloat64Number diff = 0; + cmsMAT3 Ident; + int i; + + if (m == NULL && off == NULL) return TRUE; // NULL is allowed as an empty layer + if (m == NULL && off != NULL) return FALSE; // This is an internal error + + _cmsMAT3identity(&Ident); + + for (i=0; i < 3*3; i++) + diff += fabs(((cmsFloat64Number*)m)[i] - ((cmsFloat64Number*)&Ident)[i]); + + for (i=0; i < 3; i++) + diff += fabs(((cmsFloat64Number*)off)[i]); + + + return (diff < 0.002); +} + + +// Compute the conversion layer +static +cmsBool ComputeConversion(int i, cmsHPROFILE hProfiles[], + cmsUInt32Number Intent, + cmsBool BPC, + cmsFloat64Number AdaptationState, + cmsMAT3* m, cmsVEC3* off) +{ + + int k; + + // m and off are set to identity and this is detected latter on + _cmsMAT3identity(m); + _cmsVEC3init(off, 0, 0, 0); + + // If intent is abs. colorimetric, + if (Intent == INTENT_ABSOLUTE_COLORIMETRIC) { + + cmsCIEXYZ WhitePointIn, WhitePointOut; + cmsMAT3 ChromaticAdaptationMatrixIn, ChromaticAdaptationMatrixOut; + + _cmsReadMediaWhitePoint(&WhitePointIn, hProfiles[i-1]); + _cmsReadCHAD(&ChromaticAdaptationMatrixIn, hProfiles[i-1]); + + _cmsReadMediaWhitePoint(&WhitePointOut, hProfiles[i]); + _cmsReadCHAD(&ChromaticAdaptationMatrixOut, hProfiles[i]); + + if (!ComputeAbsoluteIntent(AdaptationState, + &WhitePointIn, &ChromaticAdaptationMatrixIn, + &WhitePointOut, &ChromaticAdaptationMatrixOut, m)) return FALSE; + + } + else { + // Rest of intents may apply BPC. + + if (BPC) { + + cmsCIEXYZ BlackPointIn, BlackPointOut; + + cmsDetectBlackPoint(&BlackPointIn, hProfiles[i-1], Intent, 0); + cmsDetectDestinationBlackPoint(&BlackPointOut, hProfiles[i], Intent, 0); + + // If black points are equal, then do nothing + if (BlackPointIn.X != BlackPointOut.X || + BlackPointIn.Y != BlackPointOut.Y || + BlackPointIn.Z != BlackPointOut.Z) + ComputeBlackPointCompensation(&BlackPointIn, &BlackPointOut, m, off); + } + } + + // Offset should be adjusted because the encoding. We encode XYZ normalized to 0..1.0, + // to do that, we divide by MAX_ENCODEABLE_XZY. The conversion stage goes XYZ -> XYZ so + // we have first to convert from encoded to XYZ and then convert back to encoded. + // y = Mx + Off + // x = x'c + // y = M x'c + Off + // y = y'c; y' = y / c + // y' = (Mx'c + Off) /c = Mx' + (Off / c) + + for (k=0; k < 3; k++) { + off ->n[k] /= MAX_ENCODEABLE_XYZ; + } + + return TRUE; +} + + +// Add a conversion stage if needed. If a matrix/offset m is given, it applies to XYZ space +static +cmsBool AddConversion(cmsPipeline* Result, cmsColorSpaceSignature InPCS, cmsColorSpaceSignature OutPCS, cmsMAT3* m, cmsVEC3* off) +{ + cmsFloat64Number* m_as_dbl = (cmsFloat64Number*) m; + cmsFloat64Number* off_as_dbl = (cmsFloat64Number*) off; + + // Handle PCS mismatches. A specialized stage is added to the LUT in such case + switch (InPCS) { + + case cmsSigXYZData: // Input profile operates in XYZ + + switch (OutPCS) { + + case cmsSigXYZData: // XYZ -> XYZ + if (!IsEmptyLayer(m, off) && + !cmsPipelineInsertStage(Result, cmsAT_END, cmsStageAllocMatrix(Result ->ContextID, 3, 3, m_as_dbl, off_as_dbl))) + return FALSE; + break; + + case cmsSigLabData: // XYZ -> Lab + if (!IsEmptyLayer(m, off) && + !cmsPipelineInsertStage(Result, cmsAT_END, cmsStageAllocMatrix(Result ->ContextID, 3, 3, m_as_dbl, off_as_dbl))) + return FALSE; + if (!cmsPipelineInsertStage(Result, cmsAT_END, _cmsStageAllocXYZ2Lab(Result ->ContextID))) + return FALSE; + break; + + default: + return FALSE; // Colorspace mismatch + } + break; + + case cmsSigLabData: // Input profile operates in Lab + + switch (OutPCS) { + + case cmsSigXYZData: // Lab -> XYZ + + if (!cmsPipelineInsertStage(Result, cmsAT_END, _cmsStageAllocLab2XYZ(Result ->ContextID))) + return FALSE; + if (!IsEmptyLayer(m, off) && + !cmsPipelineInsertStage(Result, cmsAT_END, cmsStageAllocMatrix(Result ->ContextID, 3, 3, m_as_dbl, off_as_dbl))) + return FALSE; + break; + + case cmsSigLabData: // Lab -> Lab + + if (!IsEmptyLayer(m, off)) { + if (!cmsPipelineInsertStage(Result, cmsAT_END, _cmsStageAllocLab2XYZ(Result ->ContextID)) || + !cmsPipelineInsertStage(Result, cmsAT_END, cmsStageAllocMatrix(Result ->ContextID, 3, 3, m_as_dbl, off_as_dbl)) || + !cmsPipelineInsertStage(Result, cmsAT_END, _cmsStageAllocXYZ2Lab(Result ->ContextID))) + return FALSE; + } + break; + + default: + return FALSE; // Mismatch + } + break; + + // On colorspaces other than PCS, check for same space + default: + if (InPCS != OutPCS) return FALSE; + break; + } + + return TRUE; +} + + +// Is a given space compatible with another? +static +cmsBool ColorSpaceIsCompatible(cmsColorSpaceSignature a, cmsColorSpaceSignature b) +{ + // If they are same, they are compatible. + if (a == b) return TRUE; + + // Check for MCH4 substitution of CMYK + if ((a == cmsSig4colorData) && (b == cmsSigCmykData)) return TRUE; + if ((a == cmsSigCmykData) && (b == cmsSig4colorData)) return TRUE; + + // Check for XYZ/Lab. Those spaces are interchangeable as they can be computed one from other. + if ((a == cmsSigXYZData) && (b == cmsSigLabData)) return TRUE; + if ((a == cmsSigLabData) && (b == cmsSigXYZData)) return TRUE; + + return FALSE; +} + + +// Default handler for ICC-style intents +static +cmsPipeline* DefaultICCintents(cmsContext ContextID, + cmsUInt32Number nProfiles, + cmsUInt32Number TheIntents[], + cmsHPROFILE hProfiles[], + cmsBool BPC[], + cmsFloat64Number AdaptationStates[], + cmsUInt32Number dwFlags) +{ + cmsPipeline* Lut = NULL; + cmsPipeline* Result; + cmsHPROFILE hProfile; + cmsMAT3 m; + cmsVEC3 off; + cmsColorSpaceSignature ColorSpaceIn, ColorSpaceOut, CurrentColorSpace; + cmsProfileClassSignature ClassSig; + cmsUInt32Number i, Intent; + + // For safety + if (nProfiles == 0) return NULL; + + // Allocate an empty LUT for holding the result. 0 as channel count means 'undefined' + Result = cmsPipelineAlloc(ContextID, 0, 0); + if (Result == NULL) return NULL; + + CurrentColorSpace = cmsGetColorSpace(hProfiles[0]); + + for (i=0; i < nProfiles; i++) { + + cmsBool lIsDeviceLink, lIsInput; + + hProfile = hProfiles[i]; + ClassSig = cmsGetDeviceClass(hProfile); + lIsDeviceLink = (ClassSig == cmsSigLinkClass || ClassSig == cmsSigAbstractClass ); + + // First profile is used as input unless devicelink or abstract + if ((i == 0) && !lIsDeviceLink) { + lIsInput = TRUE; + } + else { + // Else use profile in the input direction if current space is not PCS + lIsInput = (CurrentColorSpace != cmsSigXYZData) && + (CurrentColorSpace != cmsSigLabData); + } + + Intent = TheIntents[i]; + + if (lIsInput || lIsDeviceLink) { + + ColorSpaceIn = cmsGetColorSpace(hProfile); + ColorSpaceOut = cmsGetPCS(hProfile); + } + else { + + ColorSpaceIn = cmsGetPCS(hProfile); + ColorSpaceOut = cmsGetColorSpace(hProfile); + } + + if (!ColorSpaceIsCompatible(ColorSpaceIn, CurrentColorSpace)) { + + cmsSignalError(ContextID, cmsERROR_COLORSPACE_CHECK, "ColorSpace mismatch"); + goto Error; + } + + // If devicelink is found, then no custom intent is allowed and we can + // read the LUT to be applied. Settings don't apply here. + if (lIsDeviceLink || ((ClassSig == cmsSigNamedColorClass) && (nProfiles == 1))) { + + // Get the involved LUT from the profile + Lut = _cmsReadDevicelinkLUT(hProfile, Intent); + if (Lut == NULL) goto Error; + + // What about abstract profiles? + if (ClassSig == cmsSigAbstractClass && i > 0) { + if (!ComputeConversion(i, hProfiles, Intent, BPC[i], AdaptationStates[i], &m, &off)) goto Error; + } + else { + _cmsMAT3identity(&m); + _cmsVEC3init(&off, 0, 0, 0); + } + + + if (!AddConversion(Result, CurrentColorSpace, ColorSpaceIn, &m, &off)) goto Error; + + } + else { + + if (lIsInput) { + // Input direction means non-pcs connection, so proceed like devicelinks + Lut = _cmsReadInputLUT(hProfile, Intent); + if (Lut == NULL) goto Error; + } + else { + + // Output direction means PCS connection. Intent may apply here + Lut = _cmsReadOutputLUT(hProfile, Intent); + if (Lut == NULL) goto Error; + + + if (!ComputeConversion(i, hProfiles, Intent, BPC[i], AdaptationStates[i], &m, &off)) goto Error; + if (!AddConversion(Result, CurrentColorSpace, ColorSpaceIn, &m, &off)) goto Error; + + } + } + + // Concatenate to the output LUT + if (!cmsPipelineCat(Result, Lut)) + goto Error; + cmsPipelineFree(Lut); + + // Update current space + CurrentColorSpace = ColorSpaceOut; + } + + return Result; + +Error: + + cmsPipelineFree(Lut); + if (Result != NULL) cmsPipelineFree(Result); + return NULL; + + cmsUNUSED_PARAMETER(dwFlags); +} + + +// Wrapper for DLL calling convention +cmsPipeline* CMSEXPORT _cmsDefaultICCintents(cmsContext ContextID, + cmsUInt32Number nProfiles, + cmsUInt32Number TheIntents[], + cmsHPROFILE hProfiles[], + cmsBool BPC[], + cmsFloat64Number AdaptationStates[], + cmsUInt32Number dwFlags) +{ + return DefaultICCintents(ContextID, nProfiles, TheIntents, hProfiles, BPC, AdaptationStates, dwFlags); +} + +// Black preserving intents --------------------------------------------------------------------------------------------- + +// Translate black-preserving intents to ICC ones +static +int TranslateNonICCIntents(int Intent) +{ + switch (Intent) { + case INTENT_PRESERVE_K_ONLY_PERCEPTUAL: + case INTENT_PRESERVE_K_PLANE_PERCEPTUAL: + return INTENT_PERCEPTUAL; + + case INTENT_PRESERVE_K_ONLY_RELATIVE_COLORIMETRIC: + case INTENT_PRESERVE_K_PLANE_RELATIVE_COLORIMETRIC: + return INTENT_RELATIVE_COLORIMETRIC; + + case INTENT_PRESERVE_K_ONLY_SATURATION: + case INTENT_PRESERVE_K_PLANE_SATURATION: + return INTENT_SATURATION; + + default: return Intent; + } +} + +// Sampler for Black-only preserving CMYK->CMYK transforms + +typedef struct { + cmsPipeline* cmyk2cmyk; // The original transform + cmsToneCurve* KTone; // Black-to-black tone curve + +} GrayOnlyParams; + + +// Preserve black only if that is the only ink used +static +int BlackPreservingGrayOnlySampler(register const cmsUInt16Number In[], register cmsUInt16Number Out[], register void* Cargo) +{ + GrayOnlyParams* bp = (GrayOnlyParams*) Cargo; + + // If going across black only, keep black only + if (In[0] == 0 && In[1] == 0 && In[2] == 0) { + + // TAC does not apply because it is black ink! + Out[0] = Out[1] = Out[2] = 0; + Out[3] = cmsEvalToneCurve16(bp->KTone, In[3]); + return TRUE; + } + + // Keep normal transform for other colors + bp ->cmyk2cmyk ->Eval16Fn(In, Out, bp ->cmyk2cmyk->Data); + return TRUE; +} + +// This is the entry for black-preserving K-only intents, which are non-ICC +static +cmsPipeline* BlackPreservingKOnlyIntents(cmsContext ContextID, + cmsUInt32Number nProfiles, + cmsUInt32Number TheIntents[], + cmsHPROFILE hProfiles[], + cmsBool BPC[], + cmsFloat64Number AdaptationStates[], + cmsUInt32Number dwFlags) +{ + GrayOnlyParams bp; + cmsPipeline* Result; + cmsUInt32Number ICCIntents[256]; + cmsStage* CLUT; + cmsUInt32Number i, nGridPoints; + + + // Sanity check + if (nProfiles < 1 || nProfiles > 255) return NULL; + + // Translate black-preserving intents to ICC ones + for (i=0; i < nProfiles; i++) + ICCIntents[i] = TranslateNonICCIntents(TheIntents[i]); + + // Check for non-cmyk profiles + if (cmsGetColorSpace(hProfiles[0]) != cmsSigCmykData || + cmsGetColorSpace(hProfiles[nProfiles-1]) != cmsSigCmykData) + return DefaultICCintents(ContextID, nProfiles, ICCIntents, hProfiles, BPC, AdaptationStates, dwFlags); + + memset(&bp, 0, sizeof(bp)); + + // Allocate an empty LUT for holding the result + Result = cmsPipelineAlloc(ContextID, 4, 4); + if (Result == NULL) return NULL; + + // Create a LUT holding normal ICC transform + bp.cmyk2cmyk = DefaultICCintents(ContextID, + nProfiles, + ICCIntents, + hProfiles, + BPC, + AdaptationStates, + dwFlags); + + if (bp.cmyk2cmyk == NULL) goto Error; + + // Now, compute the tone curve + bp.KTone = _cmsBuildKToneCurve(ContextID, + 4096, + nProfiles, + ICCIntents, + hProfiles, + BPC, + AdaptationStates, + dwFlags); + + if (bp.KTone == NULL) goto Error; + + + // How many gridpoints are we going to use? + nGridPoints = _cmsReasonableGridpointsByColorspace(cmsSigCmykData, dwFlags); + + // Create the CLUT. 16 bits + CLUT = cmsStageAllocCLut16bit(ContextID, nGridPoints, 4, 4, NULL); + if (CLUT == NULL) goto Error; + + // This is the one and only MPE in this LUT + if (!cmsPipelineInsertStage(Result, cmsAT_BEGIN, CLUT)) + goto Error; + + // Sample it. We cannot afford pre/post linearization this time. + if (!cmsStageSampleCLut16bit(CLUT, BlackPreservingGrayOnlySampler, (void*) &bp, 0)) + goto Error; + + // Get rid of xform and tone curve + cmsPipelineFree(bp.cmyk2cmyk); + cmsFreeToneCurve(bp.KTone); + + return Result; + +Error: + + if (bp.cmyk2cmyk != NULL) cmsPipelineFree(bp.cmyk2cmyk); + if (bp.KTone != NULL) cmsFreeToneCurve(bp.KTone); + if (Result != NULL) cmsPipelineFree(Result); + return NULL; + +} + +// K Plane-preserving CMYK to CMYK ------------------------------------------------------------------------------------ + +typedef struct { + + cmsPipeline* cmyk2cmyk; // The original transform + cmsHTRANSFORM hProofOutput; // Output CMYK to Lab (last profile) + cmsHTRANSFORM cmyk2Lab; // The input chain + cmsToneCurve* KTone; // Black-to-black tone curve + cmsPipeline* LabK2cmyk; // The output profile + cmsFloat64Number MaxError; + + cmsHTRANSFORM hRoundTrip; + cmsFloat64Number MaxTAC; + + +} PreserveKPlaneParams; + + +// The CLUT will be stored at 16 bits, but calculations are performed at cmsFloat32Number precision +static +int BlackPreservingSampler(register const cmsUInt16Number In[], register cmsUInt16Number Out[], register void* Cargo) +{ + int i; + cmsFloat32Number Inf[4], Outf[4]; + cmsFloat32Number LabK[4]; + cmsFloat64Number SumCMY, SumCMYK, Error, Ratio; + cmsCIELab ColorimetricLab, BlackPreservingLab; + PreserveKPlaneParams* bp = (PreserveKPlaneParams*) Cargo; + + // Convert from 16 bits to floating point + for (i=0; i < 4; i++) + Inf[i] = (cmsFloat32Number) (In[i] / 65535.0); + + // Get the K across Tone curve + LabK[3] = cmsEvalToneCurveFloat(bp ->KTone, Inf[3]); + + // If going across black only, keep black only + if (In[0] == 0 && In[1] == 0 && In[2] == 0) { + + Out[0] = Out[1] = Out[2] = 0; + Out[3] = _cmsQuickSaturateWord(LabK[3] * 65535.0); + return TRUE; + } + + // Try the original transform, + cmsPipelineEvalFloat( Inf, Outf, bp ->cmyk2cmyk); + + // Store a copy of the floating point result into 16-bit + for (i=0; i < 4; i++) + Out[i] = _cmsQuickSaturateWord(Outf[i] * 65535.0); + + // Maybe K is already ok (mostly on K=0) + if ( fabs(Outf[3] - LabK[3]) < (3.0 / 65535.0) ) { + return TRUE; + } + + // K differ, mesure and keep Lab measurement for further usage + // this is done in relative colorimetric intent + cmsDoTransform(bp->hProofOutput, Out, &ColorimetricLab, 1); + + // Is not black only and the transform doesn't keep black. + // Obtain the Lab of output CMYK. After that we have Lab + K + cmsDoTransform(bp ->cmyk2Lab, Outf, LabK, 1); + + // Obtain the corresponding CMY using reverse interpolation + // (K is fixed in LabK[3]) + if (!cmsPipelineEvalReverseFloat(LabK, Outf, Outf, bp ->LabK2cmyk)) { + + // Cannot find a suitable value, so use colorimetric xform + // which is already stored in Out[] + return TRUE; + } + + // Make sure to pass thru K (which now is fixed) + Outf[3] = LabK[3]; + + // Apply TAC if needed + SumCMY = Outf[0] + Outf[1] + Outf[2]; + SumCMYK = SumCMY + Outf[3]; + + if (SumCMYK > bp ->MaxTAC) { + + Ratio = 1 - ((SumCMYK - bp->MaxTAC) / SumCMY); + if (Ratio < 0) + Ratio = 0; + } + else + Ratio = 1.0; + + Out[0] = _cmsQuickSaturateWord(Outf[0] * Ratio * 65535.0); // C + Out[1] = _cmsQuickSaturateWord(Outf[1] * Ratio * 65535.0); // M + Out[2] = _cmsQuickSaturateWord(Outf[2] * Ratio * 65535.0); // Y + Out[3] = _cmsQuickSaturateWord(Outf[3] * 65535.0); + + // Estimate the error (this goes 16 bits to Lab DBL) + cmsDoTransform(bp->hProofOutput, Out, &BlackPreservingLab, 1); + Error = cmsDeltaE(&ColorimetricLab, &BlackPreservingLab); + if (Error > bp -> MaxError) + bp->MaxError = Error; + + return TRUE; +} + +// This is the entry for black-plane preserving, which are non-ICC +static +cmsPipeline* BlackPreservingKPlaneIntents(cmsContext ContextID, + cmsUInt32Number nProfiles, + cmsUInt32Number TheIntents[], + cmsHPROFILE hProfiles[], + cmsBool BPC[], + cmsFloat64Number AdaptationStates[], + cmsUInt32Number dwFlags) +{ + PreserveKPlaneParams bp; + cmsPipeline* Result = NULL; + cmsUInt32Number ICCIntents[256]; + cmsStage* CLUT; + cmsUInt32Number i, nGridPoints; + cmsHPROFILE hLab; + + // Sanity check + if (nProfiles < 1 || nProfiles > 255) return NULL; + + // Translate black-preserving intents to ICC ones + for (i=0; i < nProfiles; i++) + ICCIntents[i] = TranslateNonICCIntents(TheIntents[i]); + + // Check for non-cmyk profiles + if (cmsGetColorSpace(hProfiles[0]) != cmsSigCmykData || + !(cmsGetColorSpace(hProfiles[nProfiles-1]) == cmsSigCmykData || + cmsGetDeviceClass(hProfiles[nProfiles-1]) == cmsSigOutputClass)) + return DefaultICCintents(ContextID, nProfiles, ICCIntents, hProfiles, BPC, AdaptationStates, dwFlags); + + // Allocate an empty LUT for holding the result + Result = cmsPipelineAlloc(ContextID, 4, 4); + if (Result == NULL) return NULL; + + + memset(&bp, 0, sizeof(bp)); + + // We need the input LUT of the last profile, assuming this one is responsible of + // black generation. This LUT will be seached in inverse order. + bp.LabK2cmyk = _cmsReadInputLUT(hProfiles[nProfiles-1], INTENT_RELATIVE_COLORIMETRIC); + if (bp.LabK2cmyk == NULL) goto Cleanup; + + // Get total area coverage (in 0..1 domain) + bp.MaxTAC = cmsDetectTAC(hProfiles[nProfiles-1]) / 100.0; + if (bp.MaxTAC <= 0) goto Cleanup; + + + // Create a LUT holding normal ICC transform + bp.cmyk2cmyk = DefaultICCintents(ContextID, + nProfiles, + ICCIntents, + hProfiles, + BPC, + AdaptationStates, + dwFlags); + if (bp.cmyk2cmyk == NULL) goto Cleanup; + + // Now the tone curve + bp.KTone = _cmsBuildKToneCurve(ContextID, 4096, nProfiles, + ICCIntents, + hProfiles, + BPC, + AdaptationStates, + dwFlags); + if (bp.KTone == NULL) goto Cleanup; + + // To measure the output, Last profile to Lab + hLab = cmsCreateLab4ProfileTHR(ContextID, NULL); + bp.hProofOutput = cmsCreateTransformTHR(ContextID, hProfiles[nProfiles-1], + CHANNELS_SH(4)|BYTES_SH(2), hLab, TYPE_Lab_DBL, + INTENT_RELATIVE_COLORIMETRIC, + cmsFLAGS_NOCACHE|cmsFLAGS_NOOPTIMIZE); + if ( bp.hProofOutput == NULL) goto Cleanup; + + // Same as anterior, but lab in the 0..1 range + bp.cmyk2Lab = cmsCreateTransformTHR(ContextID, hProfiles[nProfiles-1], + FLOAT_SH(1)|CHANNELS_SH(4)|BYTES_SH(4), hLab, + FLOAT_SH(1)|CHANNELS_SH(3)|BYTES_SH(4), + INTENT_RELATIVE_COLORIMETRIC, + cmsFLAGS_NOCACHE|cmsFLAGS_NOOPTIMIZE); + if (bp.cmyk2Lab == NULL) goto Cleanup; + cmsCloseProfile(hLab); + + // Error estimation (for debug only) + bp.MaxError = 0; + + // How many gridpoints are we going to use? + nGridPoints = _cmsReasonableGridpointsByColorspace(cmsSigCmykData, dwFlags); + + + CLUT = cmsStageAllocCLut16bit(ContextID, nGridPoints, 4, 4, NULL); + if (CLUT == NULL) goto Cleanup; + + if (!cmsPipelineInsertStage(Result, cmsAT_BEGIN, CLUT)) + goto Cleanup; + + cmsStageSampleCLut16bit(CLUT, BlackPreservingSampler, (void*) &bp, 0); + +Cleanup: + + if (bp.cmyk2cmyk) cmsPipelineFree(bp.cmyk2cmyk); + if (bp.cmyk2Lab) cmsDeleteTransform(bp.cmyk2Lab); + if (bp.hProofOutput) cmsDeleteTransform(bp.hProofOutput); + + if (bp.KTone) cmsFreeToneCurve(bp.KTone); + if (bp.LabK2cmyk) cmsPipelineFree(bp.LabK2cmyk); + + return Result; +} + +// Link routines ------------------------------------------------------------------------------------------------------ + +// Chain several profiles into a single LUT. It just checks the parameters and then calls the handler +// for the first intent in chain. The handler may be user-defined. Is up to the handler to deal with the +// rest of intents in chain. A maximum of 255 profiles at time are supported, which is pretty reasonable. +cmsPipeline* _cmsLinkProfiles(cmsContext ContextID, + cmsUInt32Number nProfiles, + cmsUInt32Number TheIntents[], + cmsHPROFILE hProfiles[], + cmsBool BPC[], + cmsFloat64Number AdaptationStates[], + cmsUInt32Number dwFlags) +{ + cmsUInt32Number i; + cmsIntentsList* Intent; + + // Make sure a reasonable number of profiles is provided + if (nProfiles <= 0 || nProfiles > 255) { + cmsSignalError(ContextID, cmsERROR_RANGE, "Couldn't link '%d' profiles", nProfiles); + return NULL; + } + + for (i=0; i < nProfiles; i++) { + + // Check if black point is really needed or allowed. Note that + // following Adobe's document: + // BPC does not apply to devicelink profiles, nor to abs colorimetric, + // and applies always on V4 perceptual and saturation. + + if (TheIntents[i] == INTENT_ABSOLUTE_COLORIMETRIC) + BPC[i] = FALSE; + + if (TheIntents[i] == INTENT_PERCEPTUAL || TheIntents[i] == INTENT_SATURATION) { + + // Force BPC for V4 profiles in perceptual and saturation + if (cmsGetProfileVersion(hProfiles[i]) >= 4.0) + BPC[i] = TRUE; + } + } + + // Search for a handler. The first intent in the chain defines the handler. That would + // prevent using multiple custom intents in a multiintent chain, but the behaviour of + // this case would present some issues if the custom intent tries to do things like + // preserve primaries. This solution is not perfect, but works well on most cases. + + Intent = SearchIntent(TheIntents[0]); + if (Intent == NULL) { + cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported intent '%d'", TheIntents[0]); + return NULL; + } + + // Call the handler + return Intent ->Link(ContextID, nProfiles, TheIntents, hProfiles, BPC, AdaptationStates, dwFlags); +} + +// ------------------------------------------------------------------------------------------------- + +// Get information about available intents. nMax is the maximum space for the supplied "Codes" +// and "Descriptions" the function returns the total number of intents, which may be greater +// than nMax, although the matrices are not populated beyond this level. +cmsUInt32Number CMSEXPORT cmsGetSupportedIntents(cmsUInt32Number nMax, cmsUInt32Number* Codes, char** Descriptions) +{ + cmsIntentsList* pt; + cmsUInt32Number nIntents; + + for (nIntents=0, pt = Intents; pt != NULL; pt = pt -> Next) + { + if (nIntents < nMax) { + if (Codes != NULL) + Codes[nIntents] = pt ->Intent; + + if (Descriptions != NULL) + Descriptions[nIntents] = pt ->Description; + } + + nIntents++; + } + + return nIntents; +} + +// The plug-in registration. User can add new intents or override default routines +cmsBool _cmsRegisterRenderingIntentPlugin(cmsContext id, cmsPluginBase* Data) +{ + cmsPluginRenderingIntent* Plugin = (cmsPluginRenderingIntent*) Data; + cmsIntentsList* fl; + + // Do we have to reset the intents? + if (Data == NULL) { + + Intents = DefaultIntents; + return TRUE; + } + + fl = SearchIntent(Plugin ->Intent); + + if (fl == NULL) { + fl = (cmsIntentsList*) _cmsPluginMalloc(id, sizeof(cmsIntentsList)); + if (fl == NULL) return FALSE; + } + + fl ->Intent = Plugin ->Intent; + strncpy(fl ->Description, Plugin ->Description, 255); + fl ->Description[255] = 0; + + fl ->Link = Plugin ->Link; + + fl ->Next = Intents; + Intents = fl; + + return TRUE; +} + diff --git a/jni/lcms2-2.5/src/cmserr.c b/jni/lcms2-2.5/src/cmserr.c new file mode 100644 index 00000000..166793f5 --- /dev/null +++ b/jni/lcms2-2.5/src/cmserr.c @@ -0,0 +1,428 @@ +//--------------------------------------------------------------------------------- +// +// Little Color Management System +// Copyright (c) 1998-2012 Marti Maria Saguer +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//--------------------------------------------------------------------------------- + +#include "lcms2_internal.h" + +// I am so tired about incompatibilities on those functions that here are some replacements +// that hopefully would be fully portable. + +// compare two strings ignoring case +int CMSEXPORT cmsstrcasecmp(const char* s1, const char* s2) +{ + register const unsigned char *us1 = (const unsigned char *)s1, + *us2 = (const unsigned char *)s2; + + while (toupper(*us1) == toupper(*us2++)) + if (*us1++ == '\0') + return (0); + return (toupper(*us1) - toupper(*--us2)); +} + +// long int because C99 specifies ftell in such way (7.19.9.2) +long int CMSEXPORT cmsfilelength(FILE* f) +{ + long int p , n; + + p = ftell(f); // register current file position + + if (fseek(f, 0, SEEK_END) != 0) { + return -1; + } + + n = ftell(f); + fseek(f, p, SEEK_SET); // file position restored + + return n; +} + + +// Memory handling ------------------------------------------------------------------ +// +// This is the interface to low-level memory management routines. By default a simple +// wrapping to malloc/free/realloc is provided, although there is a limit on the max +// amount of memoy that can be reclaimed. This is mostly as a safety feature to +// prevent bogus or malintentionated code to allocate huge blocks that otherwise lcms +// would never need. + +#define MAX_MEMORY_FOR_ALLOC ((cmsUInt32Number)(1024U*1024U*512U)) + +// User may override this behaviour by using a memory plug-in, which basically replaces +// the default memory management functions. In this case, no check is performed and it +// is up to the plug-in writter to keep in the safe side. There are only three functions +// required to be implemented: malloc, realloc and free, although the user may want to +// replace the optional mallocZero, calloc and dup as well. + +cmsBool _cmsRegisterMemHandlerPlugin(cmsPluginBase* Plugin); + +// ********************************************************************************* + +// This is the default memory allocation function. It does a very coarse +// check of amout of memory, just to prevent exploits +static +void* _cmsMallocDefaultFn(cmsContext ContextID, cmsUInt32Number size) +{ + if (size > MAX_MEMORY_FOR_ALLOC) return NULL; // Never allow over maximum + + return (void*) malloc(size); + + cmsUNUSED_PARAMETER(ContextID); +} + +// Generic allocate & zero +static +void* _cmsMallocZeroDefaultFn(cmsContext ContextID, cmsUInt32Number size) +{ + void *pt = _cmsMalloc(ContextID, size); + if (pt == NULL) return NULL; + + memset(pt, 0, size); + return pt; +} + + +// The default free function. The only check proformed is against NULL pointers +static +void _cmsFreeDefaultFn(cmsContext ContextID, void *Ptr) +{ + // free(NULL) is defined a no-op by C99, therefore it is safe to + // avoid the check, but it is here just in case... + + if (Ptr) free(Ptr); + + cmsUNUSED_PARAMETER(ContextID); +} + +// The default realloc function. Again it check for exploits. If Ptr is NULL, +// realloc behaves the same way as malloc and allocates a new block of size bytes. +static +void* _cmsReallocDefaultFn(cmsContext ContextID, void* Ptr, cmsUInt32Number size) +{ + + if (size > MAX_MEMORY_FOR_ALLOC) return NULL; // Never realloc over 512Mb + + return realloc(Ptr, size); + + cmsUNUSED_PARAMETER(ContextID); +} + + +// The default calloc function. Allocates an array of num elements, each one of size bytes +// all memory is initialized to zero. +static +void* _cmsCallocDefaultFn(cmsContext ContextID, cmsUInt32Number num, cmsUInt32Number size) +{ + cmsUInt32Number Total = num * size; + + // Preserve calloc behaviour + if (Total == 0) return NULL; + + // Safe check for overflow. + if (num >= UINT_MAX / size) return NULL; + + // Check for overflow + if (Total < num || Total < size) { + return NULL; + } + + if (Total > MAX_MEMORY_FOR_ALLOC) return NULL; // Never alloc over 512Mb + + return _cmsMallocZero(ContextID, Total); +} + +// Generic block duplication +static +void* _cmsDupDefaultFn(cmsContext ContextID, const void* Org, cmsUInt32Number size) +{ + void* mem; + + if (size > MAX_MEMORY_FOR_ALLOC) return NULL; // Never dup over 512Mb + + mem = _cmsMalloc(ContextID, size); + + if (mem != NULL && Org != NULL) + memmove(mem, Org, size); + + return mem; +} + +// Pointers to malloc and _cmsFree functions in current environment +static void * (* MallocPtr)(cmsContext ContextID, cmsUInt32Number size) = _cmsMallocDefaultFn; +static void * (* MallocZeroPtr)(cmsContext ContextID, cmsUInt32Number size) = _cmsMallocZeroDefaultFn; +static void (* FreePtr)(cmsContext ContextID, void *Ptr) = _cmsFreeDefaultFn; +static void * (* ReallocPtr)(cmsContext ContextID, void *Ptr, cmsUInt32Number NewSize) = _cmsReallocDefaultFn; +static void * (* CallocPtr)(cmsContext ContextID, cmsUInt32Number num, cmsUInt32Number size)= _cmsCallocDefaultFn; +static void * (* DupPtr)(cmsContext ContextID, const void* Org, cmsUInt32Number size) = _cmsDupDefaultFn; + +// Plug-in replacement entry +cmsBool _cmsRegisterMemHandlerPlugin(cmsPluginBase *Data) +{ + cmsPluginMemHandler* Plugin = (cmsPluginMemHandler*) Data; + + // NULL forces to reset to defaults + if (Data == NULL) { + + MallocPtr = _cmsMallocDefaultFn; + MallocZeroPtr= _cmsMallocZeroDefaultFn; + FreePtr = _cmsFreeDefaultFn; + ReallocPtr = _cmsReallocDefaultFn; + CallocPtr = _cmsCallocDefaultFn; + DupPtr = _cmsDupDefaultFn; + return TRUE; + } + + // Check for required callbacks + if (Plugin -> MallocPtr == NULL || + Plugin -> FreePtr == NULL || + Plugin -> ReallocPtr == NULL) return FALSE; + + // Set replacement functions + MallocPtr = Plugin -> MallocPtr; + FreePtr = Plugin -> FreePtr; + ReallocPtr = Plugin -> ReallocPtr; + + if (Plugin ->MallocZeroPtr != NULL) MallocZeroPtr = Plugin ->MallocZeroPtr; + if (Plugin ->CallocPtr != NULL) CallocPtr = Plugin -> CallocPtr; + if (Plugin ->DupPtr != NULL) DupPtr = Plugin -> DupPtr; + + return TRUE; +} + +// Generic allocate +void* CMSEXPORT _cmsMalloc(cmsContext ContextID, cmsUInt32Number size) +{ + return MallocPtr(ContextID, size); +} + +// Generic allocate & zero +void* CMSEXPORT _cmsMallocZero(cmsContext ContextID, cmsUInt32Number size) +{ + return MallocZeroPtr(ContextID, size); +} + +// Generic calloc +void* CMSEXPORT _cmsCalloc(cmsContext ContextID, cmsUInt32Number num, cmsUInt32Number size) +{ + return CallocPtr(ContextID, num, size); +} + +// Generic reallocate +void* CMSEXPORT _cmsRealloc(cmsContext ContextID, void* Ptr, cmsUInt32Number size) +{ + return ReallocPtr(ContextID, Ptr, size); +} + +// Generic free memory +void CMSEXPORT _cmsFree(cmsContext ContextID, void* Ptr) +{ + if (Ptr != NULL) FreePtr(ContextID, Ptr); +} + +// Generic block duplication +void* CMSEXPORT _cmsDupMem(cmsContext ContextID, const void* Org, cmsUInt32Number size) +{ + return DupPtr(ContextID, Org, size); +} + +// ******************************************************************************************** + +// Sub allocation takes care of many pointers of small size. The memory allocated in +// this way have be freed at once. Next function allocates a single chunk for linked list +// I prefer this method over realloc due to the big inpact on xput realloc may have if +// memory is being swapped to disk. This approach is safer (although that may not be true on all platforms) +static +_cmsSubAllocator_chunk* _cmsCreateSubAllocChunk(cmsContext ContextID, cmsUInt32Number Initial) +{ + _cmsSubAllocator_chunk* chunk; + + // 20K by default + if (Initial == 0) + Initial = 20*1024; + + // Create the container + chunk = (_cmsSubAllocator_chunk*) _cmsMallocZero(ContextID, sizeof(_cmsSubAllocator_chunk)); + if (chunk == NULL) return NULL; + + // Initialize values + chunk ->Block = (cmsUInt8Number*) _cmsMalloc(ContextID, Initial); + if (chunk ->Block == NULL) { + + // Something went wrong + _cmsFree(ContextID, chunk); + return NULL; + } + + chunk ->BlockSize = Initial; + chunk ->Used = 0; + chunk ->next = NULL; + + return chunk; +} + +// The suballocated is nothing but a pointer to the first element in the list. We also keep +// the thread ID in this structure. +_cmsSubAllocator* _cmsCreateSubAlloc(cmsContext ContextID, cmsUInt32Number Initial) +{ + _cmsSubAllocator* sub; + + // Create the container + sub = (_cmsSubAllocator*) _cmsMallocZero(ContextID, sizeof(_cmsSubAllocator)); + if (sub == NULL) return NULL; + + sub ->ContextID = ContextID; + + sub ->h = _cmsCreateSubAllocChunk(ContextID, Initial); + if (sub ->h == NULL) { + _cmsFree(ContextID, sub); + return NULL; + } + + return sub; +} + + +// Get rid of whole linked list +void _cmsSubAllocDestroy(_cmsSubAllocator* sub) +{ + _cmsSubAllocator_chunk *chunk, *n; + + for (chunk = sub ->h; chunk != NULL; chunk = n) { + + n = chunk->next; + if (chunk->Block != NULL) _cmsFree(sub ->ContextID, chunk->Block); + _cmsFree(sub ->ContextID, chunk); + } + + // Free the header + _cmsFree(sub ->ContextID, sub); +} + + +// Get a pointer to small memory block. +void* _cmsSubAlloc(_cmsSubAllocator* sub, cmsUInt32Number size) +{ + cmsUInt32Number Free = sub -> h ->BlockSize - sub -> h -> Used; + cmsUInt8Number* ptr; + + size = _cmsALIGNMEM(size); + + // Check for memory. If there is no room, allocate a new chunk of double memory size. + if (size > Free) { + + _cmsSubAllocator_chunk* chunk; + cmsUInt32Number newSize; + + newSize = sub -> h ->BlockSize * 2; + if (newSize < size) newSize = size; + + chunk = _cmsCreateSubAllocChunk(sub -> ContextID, newSize); + if (chunk == NULL) return NULL; + + // Link list + chunk ->next = sub ->h; + sub ->h = chunk; + + } + + ptr = sub -> h ->Block + sub -> h ->Used; + sub -> h -> Used += size; + + return (void*) ptr; +} + +// Error logging ****************************************************************** + +// There is no error handling at all. When a funtion fails, it returns proper value. +// For example, all create functions does return NULL on failure. Other return FALSE +// It may be interesting, for the developer, to know why the function is failing. +// for that reason, lcms2 does offer a logging function. This function does recive +// a ENGLISH string with some clues on what is going wrong. You can show this +// info to the end user, or just create some sort of log. +// The logging function should NOT terminate the program, as this obviously can leave +// resources. It is the programmer's responsability to check each function return code +// to make sure it didn't fail. + +// Error messages are limited to MAX_ERROR_MESSAGE_LEN + +#define MAX_ERROR_MESSAGE_LEN 1024 + +// --------------------------------------------------------------------------------------------------------- + +// This is our default log error +static void DefaultLogErrorHandlerFunction(cmsContext ContextID, cmsUInt32Number ErrorCode, const char *Text); + +// The current handler in actual environment +static cmsLogErrorHandlerFunction LogErrorHandler = DefaultLogErrorHandlerFunction; + +// The default error logger does nothing. +static +void DefaultLogErrorHandlerFunction(cmsContext ContextID, cmsUInt32Number ErrorCode, const char *Text) +{ + // fprintf(stderr, "[lcms]: %s\n", Text); + // fflush(stderr); + + cmsUNUSED_PARAMETER(ContextID); + cmsUNUSED_PARAMETER(ErrorCode); + cmsUNUSED_PARAMETER(Text); +} + +// Change log error +void CMSEXPORT cmsSetLogErrorHandler(cmsLogErrorHandlerFunction Fn) +{ + if (Fn == NULL) + LogErrorHandler = DefaultLogErrorHandlerFunction; + else + LogErrorHandler = Fn; +} + +// Log an error +// ErrorText is a text holding an english description of error. +void CMSEXPORT cmsSignalError(cmsContext ContextID, cmsUInt32Number ErrorCode, const char *ErrorText, ...) +{ + va_list args; + char Buffer[MAX_ERROR_MESSAGE_LEN]; + + va_start(args, ErrorText); + vsnprintf(Buffer, MAX_ERROR_MESSAGE_LEN-1, ErrorText, args); + va_end(args); + + // Call handler + LogErrorHandler(ContextID, ErrorCode, Buffer); +} + +// Utility function to print signatures +void _cmsTagSignature2String(char String[5], cmsTagSignature sig) +{ + cmsUInt32Number be; + + // Convert to big endian + be = _cmsAdjustEndianess32((cmsUInt32Number) sig); + + // Move chars + memmove(String, &be, 4); + + // Make sure of terminator + String[4] = 0; +} + diff --git a/jni/lcms2-2.5/src/cmsgamma.c b/jni/lcms2-2.5/src/cmsgamma.c new file mode 100644 index 00000000..e1531034 --- /dev/null +++ b/jni/lcms2-2.5/src/cmsgamma.c @@ -0,0 +1,1206 @@ +//--------------------------------------------------------------------------------- +// +// Little Color Management System +// Copyright (c) 1998-2013 Marti Maria Saguer +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//--------------------------------------------------------------------------------- +// +#include "lcms2_internal.h" + +// Tone curves are powerful constructs that can contain curves specified in diverse ways. +// The curve is stored in segments, where each segment can be sampled or specified by parameters. +// a 16.bit simplification of the *whole* curve is kept for optimization purposes. For float operation, +// each segment is evaluated separately. Plug-ins may be used to define new parametric schemes, +// each plug-in may define up to MAX_TYPES_IN_LCMS_PLUGIN functions types. For defining a function, +// the plug-in should provide the type id, how many parameters each type has, and a pointer to +// a procedure that evaluates the function. In the case of reverse evaluation, the evaluator will +// be called with the type id as a negative value, and a sampled version of the reversed curve +// will be built. + +// ----------------------------------------------------------------- Implementation +// Maxim number of nodes +#define MAX_NODES_IN_CURVE 4097 +#define MINUS_INF (-1E22F) +#define PLUS_INF (+1E22F) + +// The list of supported parametric curves +typedef struct _cmsParametricCurvesCollection_st { + + int nFunctions; // Number of supported functions in this chunk + int FunctionTypes[MAX_TYPES_IN_LCMS_PLUGIN]; // The identification types + int ParameterCount[MAX_TYPES_IN_LCMS_PLUGIN]; // Number of parameters for each function + cmsParametricCurveEvaluator Evaluator; // The evaluator + + struct _cmsParametricCurvesCollection_st* Next; // Next in list + +} _cmsParametricCurvesCollection; + + +// This is the default (built-in) evaluator +static cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Number Params[], cmsFloat64Number R); + +// The built-in list +static _cmsParametricCurvesCollection DefaultCurves = { + 9, // # of curve types + { 1, 2, 3, 4, 5, 6, 7, 8, 108 }, // Parametric curve ID + { 1, 3, 4, 5, 7, 4, 5, 5, 1 }, // Parameters by type + DefaultEvalParametricFn, // Evaluator + NULL // Next in chain +}; + +// The linked list head +static _cmsParametricCurvesCollection* ParametricCurves = &DefaultCurves; + +// As a way to install new parametric curves +cmsBool _cmsRegisterParametricCurvesPlugin(cmsContext id, cmsPluginBase* Data) +{ + cmsPluginParametricCurves* Plugin = (cmsPluginParametricCurves*) Data; + _cmsParametricCurvesCollection* fl; + + if (Data == NULL) { + + ParametricCurves = &DefaultCurves; + return TRUE; + } + + fl = (_cmsParametricCurvesCollection*) _cmsPluginMalloc(id, sizeof(_cmsParametricCurvesCollection)); + if (fl == NULL) return FALSE; + + // Copy the parameters + fl ->Evaluator = Plugin ->Evaluator; + fl ->nFunctions = Plugin ->nFunctions; + + // Make sure no mem overwrites + if (fl ->nFunctions > MAX_TYPES_IN_LCMS_PLUGIN) + fl ->nFunctions = MAX_TYPES_IN_LCMS_PLUGIN; + + // Copy the data + memmove(fl->FunctionTypes, Plugin ->FunctionTypes, fl->nFunctions * sizeof(cmsUInt32Number)); + memmove(fl->ParameterCount, Plugin ->ParameterCount, fl->nFunctions * sizeof(cmsUInt32Number)); + + // Keep linked list + fl ->Next = ParametricCurves; + ParametricCurves = fl; + + // All is ok + return TRUE; +} + + +// Search in type list, return position or -1 if not found +static +int IsInSet(int Type, _cmsParametricCurvesCollection* c) +{ + int i; + + for (i=0; i < c ->nFunctions; i++) + if (abs(Type) == c ->FunctionTypes[i]) return i; + + return -1; +} + + +// Search for the collection which contains a specific type +static +_cmsParametricCurvesCollection *GetParametricCurveByType(int Type, int* index) +{ + _cmsParametricCurvesCollection* c; + int Position; + + for (c = ParametricCurves; c != NULL; c = c ->Next) { + + Position = IsInSet(Type, c); + + if (Position != -1) { + if (index != NULL) + *index = Position; + return c; + } + } + + return NULL; +} + +// Low level allocate, which takes care of memory details. nEntries may be zero, and in this case +// no optimation curve is computed. nSegments may also be zero in the inverse case, where only the +// optimization curve is given. Both features simultaneously is an error +static +cmsToneCurve* AllocateToneCurveStruct(cmsContext ContextID, cmsInt32Number nEntries, + cmsInt32Number nSegments, const cmsCurveSegment* Segments, + const cmsUInt16Number* Values) +{ + cmsToneCurve* p; + int i; + + // We allow huge tables, which are then restricted for smoothing operations + if (nEntries > 65530 || nEntries < 0) { + cmsSignalError(ContextID, cmsERROR_RANGE, "Couldn't create tone curve of more than 65530 entries"); + return NULL; + } + + if (nEntries <= 0 && nSegments <= 0) { + cmsSignalError(ContextID, cmsERROR_RANGE, "Couldn't create tone curve with zero segments and no table"); + return NULL; + } + + // Allocate all required pointers, etc. + p = (cmsToneCurve*) _cmsMallocZero(ContextID, sizeof(cmsToneCurve)); + if (!p) return NULL; + + // In this case, there are no segments + if (nSegments <= 0) { + p ->Segments = NULL; + p ->Evals = NULL; + } + else { + p ->Segments = (cmsCurveSegment*) _cmsCalloc(ContextID, nSegments, sizeof(cmsCurveSegment)); + if (p ->Segments == NULL) goto Error; + + p ->Evals = (cmsParametricCurveEvaluator*) _cmsCalloc(ContextID, nSegments, sizeof(cmsParametricCurveEvaluator)); + if (p ->Evals == NULL) goto Error; + } + + p -> nSegments = nSegments; + + // This 16-bit table contains a limited precision representation of the whole curve and is kept for + // increasing xput on certain operations. + if (nEntries <= 0) { + p ->Table16 = NULL; + } + else { + p ->Table16 = (cmsUInt16Number*) _cmsCalloc(ContextID, nEntries, sizeof(cmsUInt16Number)); + if (p ->Table16 == NULL) goto Error; + } + + p -> nEntries = nEntries; + + // Initialize members if requested + if (Values != NULL && (nEntries > 0)) { + + for (i=0; i < nEntries; i++) + p ->Table16[i] = Values[i]; + } + + // Initialize the segments stuff. The evaluator for each segment is located and a pointer to it + // is placed in advance to maximize performance. + if (Segments != NULL && (nSegments > 0)) { + + _cmsParametricCurvesCollection *c; + + p ->SegInterp = (cmsInterpParams**) _cmsCalloc(ContextID, nSegments, sizeof(cmsInterpParams*)); + if (p ->SegInterp == NULL) goto Error; + + for (i=0; i< nSegments; i++) { + + // Type 0 is a special marker for table-based curves + if (Segments[i].Type == 0) + p ->SegInterp[i] = _cmsComputeInterpParams(ContextID, Segments[i].nGridPoints, 1, 1, NULL, CMS_LERP_FLAGS_FLOAT); + + memmove(&p ->Segments[i], &Segments[i], sizeof(cmsCurveSegment)); + + if (Segments[i].Type == 0 && Segments[i].SampledPoints != NULL) + p ->Segments[i].SampledPoints = (cmsFloat32Number*) _cmsDupMem(ContextID, Segments[i].SampledPoints, sizeof(cmsFloat32Number) * Segments[i].nGridPoints); + else + p ->Segments[i].SampledPoints = NULL; + + + c = GetParametricCurveByType(Segments[i].Type, NULL); + if (c != NULL) + p ->Evals[i] = c ->Evaluator; + } + } + + p ->InterpParams = _cmsComputeInterpParams(ContextID, p ->nEntries, 1, 1, p->Table16, CMS_LERP_FLAGS_16BITS); + if (p->InterpParams != NULL) + return p; + +Error: + if (p -> Segments) _cmsFree(ContextID, p ->Segments); + if (p -> Evals) _cmsFree(ContextID, p -> Evals); + if (p ->Table16) _cmsFree(ContextID, p ->Table16); + _cmsFree(ContextID, p); + return NULL; +} + + +// Parametric Fn using floating point +static +cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Number Params[], cmsFloat64Number R) +{ + cmsFloat64Number e, Val, disc; + + switch (Type) { + + // X = Y ^ Gamma + case 1: + if (R < 0) { + + if (fabs(Params[0] - 1.0) < MATRIX_DET_TOLERANCE) + Val = R; + else + Val = 0; + } + else + Val = pow(R, Params[0]); + break; + + // Type 1 Reversed: X = Y ^1/gamma + case -1: + if (R < 0) { + + if (fabs(Params[0] - 1.0) < MATRIX_DET_TOLERANCE) + Val = R; + else + Val = 0; + } + else + Val = pow(R, 1/Params[0]); + break; + + // CIE 122-1966 + // Y = (aX + b)^Gamma | X >= -b/a + // Y = 0 | else + case 2: + disc = -Params[2] / Params[1]; + + if (R >= disc ) { + + e = Params[1]*R + Params[2]; + + if (e > 0) + Val = pow(e, Params[0]); + else + Val = 0; + } + else + Val = 0; + break; + + // Type 2 Reversed + // X = (Y ^1/g - b) / a + case -2: + if (R < 0) + Val = 0; + else + Val = (pow(R, 1.0/Params[0]) - Params[2]) / Params[1]; + + if (Val < 0) + Val = 0; + break; + + + // IEC 61966-3 + // Y = (aX + b)^Gamma | X <= -b/a + // Y = c | else + case 3: + disc = -Params[2] / Params[1]; + if (disc < 0) + disc = 0; + + if (R >= disc) { + + e = Params[1]*R + Params[2]; + + if (e > 0) + Val = pow(e, Params[0]) + Params[3]; + else + Val = 0; + } + else + Val = Params[3]; + break; + + + // Type 3 reversed + // X=((Y-c)^1/g - b)/a | (Y>=c) + // X=-b/a | (Y= Params[3]) { + + e = R - Params[3]; + + if (e > 0) + Val = (pow(e, 1/Params[0]) - Params[2]) / Params[1]; + else + Val = 0; + } + else { + Val = -Params[2] / Params[1]; + } + break; + + + // IEC 61966-2.1 (sRGB) + // Y = (aX + b)^Gamma | X >= d + // Y = cX | X < d + case 4: + if (R >= Params[4]) { + + e = Params[1]*R + Params[2]; + + if (e > 0) + Val = pow(e, Params[0]); + else + Val = 0; + } + else + Val = R * Params[3]; + break; + + // Type 4 reversed + // X=((Y^1/g-b)/a) | Y >= (ad+b)^g + // X=Y/c | Y< (ad+b)^g + case -4: + e = Params[1] * Params[4] + Params[2]; + if (e < 0) + disc = 0; + else + disc = pow(e, Params[0]); + + if (R >= disc) { + + Val = (pow(R, 1.0/Params[0]) - Params[2]) / Params[1]; + } + else { + Val = R / Params[3]; + } + break; + + + // Y = (aX + b)^Gamma + e | X >= d + // Y = cX + f | X < d + case 5: + if (R >= Params[4]) { + + e = Params[1]*R + Params[2]; + + if (e > 0) + Val = pow(e, Params[0]) + Params[5]; + else + Val = Params[5]; + } + else + Val = R*Params[3] + Params[6]; + break; + + + // Reversed type 5 + // X=((Y-e)1/g-b)/a | Y >=(ad+b)^g+e), cd+f + // X=(Y-f)/c | else + case -5: + + disc = Params[3] * Params[4] + Params[6]; + if (R >= disc) { + + e = R - Params[5]; + if (e < 0) + Val = 0; + else + Val = (pow(e, 1.0/Params[0]) - Params[2]) / Params[1]; + } + else { + Val = (R - Params[6]) / Params[3]; + } + break; + + + // Types 6,7,8 comes from segmented curves as described in ICCSpecRevision_02_11_06_Float.pdf + // Type 6 is basically identical to type 5 without d + + // Y = (a * X + b) ^ Gamma + c + case 6: + e = Params[1]*R + Params[2]; + + if (e < 0) + Val = Params[3]; + else + Val = pow(e, Params[0]) + Params[3]; + break; + + // ((Y - c) ^1/Gamma - b) / a + case -6: + e = R - Params[3]; + if (e < 0) + Val = 0; + else + Val = (pow(e, 1.0/Params[0]) - Params[2]) / Params[1]; + break; + + + // Y = a * log (b * X^Gamma + c) + d + case 7: + + e = Params[2] * pow(R, Params[0]) + Params[3]; + if (e <= 0) + Val = Params[4]; + else + Val = Params[1]*log10(e) + Params[4]; + break; + + // (Y - d) / a = log(b * X ^Gamma + c) + // pow(10, (Y-d) / a) = b * X ^Gamma + c + // pow((pow(10, (Y-d) / a) - c) / b, 1/g) = X + case -7: + Val = pow((pow(10.0, (R-Params[4]) / Params[1]) - Params[3]) / Params[2], 1.0 / Params[0]); + break; + + + //Y = a * b^(c*X+d) + e + case 8: + Val = (Params[0] * pow(Params[1], Params[2] * R + Params[3]) + Params[4]); + break; + + + // Y = (log((y-e) / a) / log(b) - d ) / c + // a=0, b=1, c=2, d=3, e=4, + case -8: + + disc = R - Params[4]; + if (disc < 0) Val = 0; + else + Val = (log(disc / Params[0]) / log(Params[1]) - Params[3]) / Params[2]; + break; + + // S-Shaped: (1 - (1-x)^1/g)^1/g + case 108: + Val = pow(1.0 - pow(1 - R, 1/Params[0]), 1/Params[0]); + break; + + // y = (1 - (1-x)^1/g)^1/g + // y^g = (1 - (1-x)^1/g) + // 1 - y^g = (1-x)^1/g + // (1 - y^g)^g = 1 - x + // 1 - (1 - y^g)^g + case -108: + Val = 1 - pow(1 - pow(R, Params[0]), Params[0]); + break; + + default: + // Unsupported parametric curve. Should never reach here + return 0; + } + + return Val; +} + +// Evaluate a segmented funtion for a single value. Return -1 if no valid segment found . +// If fn type is 0, perform an interpolation on the table +static +cmsFloat64Number EvalSegmentedFn(const cmsToneCurve *g, cmsFloat64Number R) +{ + int i; + + for (i = g ->nSegments-1; i >= 0 ; --i) { + + // Check for domain + if ((R > g ->Segments[i].x0) && (R <= g ->Segments[i].x1)) { + + // Type == 0 means segment is sampled + if (g ->Segments[i].Type == 0) { + + cmsFloat32Number R1 = (cmsFloat32Number) (R - g ->Segments[i].x0) / (g ->Segments[i].x1 - g ->Segments[i].x0); + cmsFloat32Number Out; + + // Setup the table (TODO: clean that) + g ->SegInterp[i]-> Table = g ->Segments[i].SampledPoints; + + g ->SegInterp[i] -> Interpolation.LerpFloat(&R1, &Out, g ->SegInterp[i]); + + return Out; + } + else + return g ->Evals[i](g->Segments[i].Type, g ->Segments[i].Params, R); + } + } + + return MINUS_INF; +} + +// Access to estimated low-res table +cmsUInt32Number CMSEXPORT cmsGetToneCurveEstimatedTableEntries(const cmsToneCurve* t) +{ + _cmsAssert(t != NULL); + return t ->nEntries; +} + +const cmsUInt16Number* CMSEXPORT cmsGetToneCurveEstimatedTable(const cmsToneCurve* t) +{ + _cmsAssert(t != NULL); + return t ->Table16; +} + + +// Create an empty gamma curve, by using tables. This specifies only the limited-precision part, and leaves the +// floating point description empty. +cmsToneCurve* CMSEXPORT cmsBuildTabulatedToneCurve16(cmsContext ContextID, cmsInt32Number nEntries, const cmsUInt16Number Values[]) +{ + return AllocateToneCurveStruct(ContextID, nEntries, 0, NULL, Values); +} + +static +int EntriesByGamma(cmsFloat64Number Gamma) +{ + if (fabs(Gamma - 1.0) < 0.001) return 2; + return 4096; +} + + +// Create a segmented gamma, fill the table +cmsToneCurve* CMSEXPORT cmsBuildSegmentedToneCurve(cmsContext ContextID, + cmsInt32Number nSegments, const cmsCurveSegment Segments[]) +{ + int i; + cmsFloat64Number R, Val; + cmsToneCurve* g; + int nGridPoints = 4096; + + _cmsAssert(Segments != NULL); + + // Optimizatin for identity curves. + if (nSegments == 1 && Segments[0].Type == 1) { + + nGridPoints = EntriesByGamma(Segments[0].Params[0]); + } + + g = AllocateToneCurveStruct(ContextID, nGridPoints, nSegments, Segments, NULL); + if (g == NULL) return NULL; + + // Once we have the floating point version, we can approximate a 16 bit table of 4096 entries + // for performance reasons. This table would normally not be used except on 8/16 bits transforms. + for (i=0; i < nGridPoints; i++) { + + R = (cmsFloat64Number) i / (nGridPoints-1); + + Val = EvalSegmentedFn(g, R); + + // Round and saturate + g ->Table16[i] = _cmsQuickSaturateWord(Val * 65535.0); + } + + return g; +} + +// Use a segmented curve to store the floating point table +cmsToneCurve* CMSEXPORT cmsBuildTabulatedToneCurveFloat(cmsContext ContextID, cmsUInt32Number nEntries, const cmsFloat32Number values[]) +{ + cmsCurveSegment Seg[3]; + + // A segmented tone curve should have function segments in the first and last positions + // Initialize segmented curve part up to 0 to constant value = samples[0] + Seg[0].x0 = MINUS_INF; + Seg[0].x1 = 0; + Seg[0].Type = 6; + + Seg[0].Params[0] = 1; + Seg[0].Params[1] = 0; + Seg[0].Params[2] = 0; + Seg[0].Params[3] = values[0]; + Seg[0].Params[4] = 0; + + // From zero to 1 + Seg[1].x0 = 0; + Seg[1].x1 = 1.0; + Seg[1].Type = 0; + + Seg[1].nGridPoints = nEntries; + Seg[1].SampledPoints = (cmsFloat32Number*) values; + + // Final segment is constant = lastsample + Seg[2].x0 = 1.0; + Seg[2].x1 = PLUS_INF; + Seg[2].Type = 6; + + Seg[2].Params[0] = 1; + Seg[2].Params[1] = 0; + Seg[2].Params[2] = 0; + Seg[2].Params[3] = values[nEntries-1]; + Seg[2].Params[4] = 0; + + + return cmsBuildSegmentedToneCurve(ContextID, 3, Seg); +} + +// Parametric curves +// +// Parameters goes as: Curve, a, b, c, d, e, f +// Type is the ICC type +1 +// if type is negative, then the curve is analyticaly inverted +cmsToneCurve* CMSEXPORT cmsBuildParametricToneCurve(cmsContext ContextID, cmsInt32Number Type, const cmsFloat64Number Params[]) +{ + cmsCurveSegment Seg0; + int Pos = 0; + cmsUInt32Number size; + _cmsParametricCurvesCollection* c = GetParametricCurveByType(Type, &Pos); + + _cmsAssert(Params != NULL); + + if (c == NULL) { + cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Invalid parametric curve type %d", Type); + return NULL; + } + + memset(&Seg0, 0, sizeof(Seg0)); + + Seg0.x0 = MINUS_INF; + Seg0.x1 = PLUS_INF; + Seg0.Type = Type; + + size = c->ParameterCount[Pos] * sizeof(cmsFloat64Number); + memmove(Seg0.Params, Params, size); + + return cmsBuildSegmentedToneCurve(ContextID, 1, &Seg0); +} + + + +// Build a gamma table based on gamma constant +cmsToneCurve* CMSEXPORT cmsBuildGamma(cmsContext ContextID, cmsFloat64Number Gamma) +{ + return cmsBuildParametricToneCurve(ContextID, 1, &Gamma); +} + + +// Free all memory taken by the gamma curve +void CMSEXPORT cmsFreeToneCurve(cmsToneCurve* Curve) +{ + cmsContext ContextID; + + if (Curve == NULL) return; + + ContextID = Curve ->InterpParams->ContextID; + + _cmsFreeInterpParams(Curve ->InterpParams); + + if (Curve -> Table16) + _cmsFree(ContextID, Curve ->Table16); + + if (Curve ->Segments) { + + cmsUInt32Number i; + + for (i=0; i < Curve ->nSegments; i++) { + + if (Curve ->Segments[i].SampledPoints) { + _cmsFree(ContextID, Curve ->Segments[i].SampledPoints); + } + + if (Curve ->SegInterp[i] != 0) + _cmsFreeInterpParams(Curve->SegInterp[i]); + } + + _cmsFree(ContextID, Curve ->Segments); + _cmsFree(ContextID, Curve ->SegInterp); + } + + if (Curve -> Evals) + _cmsFree(ContextID, Curve -> Evals); + + if (Curve) _cmsFree(ContextID, Curve); +} + +// Utility function, free 3 gamma tables +void CMSEXPORT cmsFreeToneCurveTriple(cmsToneCurve* Curve[3]) +{ + + _cmsAssert(Curve != NULL); + + if (Curve[0] != NULL) cmsFreeToneCurve(Curve[0]); + if (Curve[1] != NULL) cmsFreeToneCurve(Curve[1]); + if (Curve[2] != NULL) cmsFreeToneCurve(Curve[2]); + + Curve[0] = Curve[1] = Curve[2] = NULL; +} + + +// Duplicate a gamma table +cmsToneCurve* CMSEXPORT cmsDupToneCurve(const cmsToneCurve* In) +{ + if (In == NULL) return NULL; + + return AllocateToneCurveStruct(In ->InterpParams ->ContextID, In ->nEntries, In ->nSegments, In ->Segments, In ->Table16); +} + +// Joins two curves for X and Y. Curves should be monotonic. +// We want to get +// +// y = Y^-1(X(t)) +// +cmsToneCurve* CMSEXPORT cmsJoinToneCurve(cmsContext ContextID, + const cmsToneCurve* X, + const cmsToneCurve* Y, cmsUInt32Number nResultingPoints) +{ + cmsToneCurve* out = NULL; + cmsToneCurve* Yreversed = NULL; + cmsFloat32Number t, x; + cmsFloat32Number* Res = NULL; + cmsUInt32Number i; + + + _cmsAssert(X != NULL); + _cmsAssert(Y != NULL); + + Yreversed = cmsReverseToneCurveEx(nResultingPoints, Y); + if (Yreversed == NULL) goto Error; + + Res = (cmsFloat32Number*) _cmsCalloc(ContextID, nResultingPoints, sizeof(cmsFloat32Number)); + if (Res == NULL) goto Error; + + //Iterate + for (i=0; i < nResultingPoints; i++) { + + t = (cmsFloat32Number) i / (nResultingPoints-1); + x = cmsEvalToneCurveFloat(X, t); + Res[i] = cmsEvalToneCurveFloat(Yreversed, x); + } + + // Allocate space for output + out = cmsBuildTabulatedToneCurveFloat(ContextID, nResultingPoints, Res); + +Error: + + if (Res != NULL) _cmsFree(ContextID, Res); + if (Yreversed != NULL) cmsFreeToneCurve(Yreversed); + + return out; +} + + + +// Get the surrounding nodes. This is tricky on non-monotonic tables +static +int GetInterval(cmsFloat64Number In, const cmsUInt16Number LutTable[], const struct _cms_interp_struc* p) +{ + int i; + int y0, y1; + + // A 1 point table is not allowed + if (p -> Domain[0] < 1) return -1; + + // Let's see if ascending or descending. + if (LutTable[0] < LutTable[p ->Domain[0]]) { + + // Table is overall ascending + for (i=p->Domain[0]-1; i >=0; --i) { + + y0 = LutTable[i]; + y1 = LutTable[i+1]; + + if (y0 <= y1) { // Increasing + if (In >= y0 && In <= y1) return i; + } + else + if (y1 < y0) { // Decreasing + if (In >= y1 && In <= y0) return i; + } + } + } + else { + // Table is overall descending + for (i=0; i < (int) p -> Domain[0]; i++) { + + y0 = LutTable[i]; + y1 = LutTable[i+1]; + + if (y0 <= y1) { // Increasing + if (In >= y0 && In <= y1) return i; + } + else + if (y1 < y0) { // Decreasing + if (In >= y1 && In <= y0) return i; + } + } + } + + return -1; +} + +// Reverse a gamma table +cmsToneCurve* CMSEXPORT cmsReverseToneCurveEx(cmsInt32Number nResultSamples, const cmsToneCurve* InCurve) +{ + cmsToneCurve *out; + cmsFloat64Number a = 0, b = 0, y, x1, y1, x2, y2; + int i, j; + int Ascending; + + _cmsAssert(InCurve != NULL); + + // Try to reverse it analytically whatever possible + if (InCurve ->nSegments == 1 && InCurve ->Segments[0].Type > 0 && InCurve -> Segments[0].Type <= 5) { + + return cmsBuildParametricToneCurve(InCurve ->InterpParams->ContextID, + -(InCurve -> Segments[0].Type), + InCurve -> Segments[0].Params); + } + + // Nope, reverse the table. + out = cmsBuildTabulatedToneCurve16(InCurve ->InterpParams->ContextID, nResultSamples, NULL); + if (out == NULL) + return NULL; + + // We want to know if this is an ascending or descending table + Ascending = !cmsIsToneCurveDescending(InCurve); + + // Iterate across Y axis + for (i=0; i < nResultSamples; i++) { + + y = (cmsFloat64Number) i * 65535.0 / (nResultSamples - 1); + + // Find interval in which y is within. + j = GetInterval(y, InCurve->Table16, InCurve->InterpParams); + if (j >= 0) { + + + // Get limits of interval + x1 = InCurve ->Table16[j]; + x2 = InCurve ->Table16[j+1]; + + y1 = (cmsFloat64Number) (j * 65535.0) / (InCurve ->nEntries - 1); + y2 = (cmsFloat64Number) ((j+1) * 65535.0 ) / (InCurve ->nEntries - 1); + + // If collapsed, then use any + if (x1 == x2) { + + out ->Table16[i] = _cmsQuickSaturateWord(Ascending ? y2 : y1); + continue; + + } else { + + // Interpolate + a = (y2 - y1) / (x2 - x1); + b = y2 - a * x2; + } + } + + out ->Table16[i] = _cmsQuickSaturateWord(a* y + b); + } + + + return out; +} + +// Reverse a gamma table +cmsToneCurve* CMSEXPORT cmsReverseToneCurve(const cmsToneCurve* InGamma) +{ + _cmsAssert(InGamma != NULL); + + return cmsReverseToneCurveEx(4096, InGamma); +} + +// From: Eilers, P.H.C. (1994) Smoothing and interpolation with finite +// differences. in: Graphic Gems IV, Heckbert, P.S. (ed.), Academic press. +// +// Smoothing and interpolation with second differences. +// +// Input: weights (w), data (y): vector from 1 to m. +// Input: smoothing parameter (lambda), length (m). +// Output: smoothed vector (z): vector from 1 to m. + +static +cmsBool smooth2(cmsContext ContextID, cmsFloat32Number w[], cmsFloat32Number y[], cmsFloat32Number z[], cmsFloat32Number lambda, int m) +{ + int i, i1, i2; + cmsFloat32Number *c, *d, *e; + cmsBool st; + + + c = (cmsFloat32Number*) _cmsCalloc(ContextID, MAX_NODES_IN_CURVE, sizeof(cmsFloat32Number)); + d = (cmsFloat32Number*) _cmsCalloc(ContextID, MAX_NODES_IN_CURVE, sizeof(cmsFloat32Number)); + e = (cmsFloat32Number*) _cmsCalloc(ContextID, MAX_NODES_IN_CURVE, sizeof(cmsFloat32Number)); + + if (c != NULL && d != NULL && e != NULL) { + + + d[1] = w[1] + lambda; + c[1] = -2 * lambda / d[1]; + e[1] = lambda /d[1]; + z[1] = w[1] * y[1]; + d[2] = w[2] + 5 * lambda - d[1] * c[1] * c[1]; + c[2] = (-4 * lambda - d[1] * c[1] * e[1]) / d[2]; + e[2] = lambda / d[2]; + z[2] = w[2] * y[2] - c[1] * z[1]; + + for (i = 3; i < m - 1; i++) { + i1 = i - 1; i2 = i - 2; + d[i]= w[i] + 6 * lambda - c[i1] * c[i1] * d[i1] - e[i2] * e[i2] * d[i2]; + c[i] = (-4 * lambda -d[i1] * c[i1] * e[i1])/ d[i]; + e[i] = lambda / d[i]; + z[i] = w[i] * y[i] - c[i1] * z[i1] - e[i2] * z[i2]; + } + + i1 = m - 2; i2 = m - 3; + + d[m - 1] = w[m - 1] + 5 * lambda -c[i1] * c[i1] * d[i1] - e[i2] * e[i2] * d[i2]; + c[m - 1] = (-2 * lambda - d[i1] * c[i1] * e[i1]) / d[m - 1]; + z[m - 1] = w[m - 1] * y[m - 1] - c[i1] * z[i1] - e[i2] * z[i2]; + i1 = m - 1; i2 = m - 2; + + d[m] = w[m] + lambda - c[i1] * c[i1] * d[i1] - e[i2] * e[i2] * d[i2]; + z[m] = (w[m] * y[m] - c[i1] * z[i1] - e[i2] * z[i2]) / d[m]; + z[m - 1] = z[m - 1] / d[m - 1] - c[m - 1] * z[m]; + + for (i = m - 2; 1<= i; i--) + z[i] = z[i] / d[i] - c[i] * z[i + 1] - e[i] * z[i + 2]; + + st = TRUE; + } + else st = FALSE; + + if (c != NULL) _cmsFree(ContextID, c); + if (d != NULL) _cmsFree(ContextID, d); + if (e != NULL) _cmsFree(ContextID, e); + + return st; +} + +// Smooths a curve sampled at regular intervals. +cmsBool CMSEXPORT cmsSmoothToneCurve(cmsToneCurve* Tab, cmsFloat64Number lambda) +{ + cmsFloat32Number w[MAX_NODES_IN_CURVE], y[MAX_NODES_IN_CURVE], z[MAX_NODES_IN_CURVE]; + int i, nItems, Zeros, Poles; + + if (Tab == NULL) return FALSE; + + if (cmsIsToneCurveLinear(Tab)) return TRUE; // Nothing to do + + nItems = Tab -> nEntries; + + if (nItems >= MAX_NODES_IN_CURVE) { + cmsSignalError(Tab ->InterpParams->ContextID, cmsERROR_RANGE, "cmsSmoothToneCurve: too many points."); + return FALSE; + } + + memset(w, 0, nItems * sizeof(cmsFloat32Number)); + memset(y, 0, nItems * sizeof(cmsFloat32Number)); + memset(z, 0, nItems * sizeof(cmsFloat32Number)); + + for (i=0; i < nItems; i++) + { + y[i+1] = (cmsFloat32Number) Tab -> Table16[i]; + w[i+1] = 1.0; + } + + if (!smooth2(Tab ->InterpParams->ContextID, w, y, z, (cmsFloat32Number) lambda, nItems)) return FALSE; + + // Do some reality - checking... + Zeros = Poles = 0; + for (i=nItems; i > 1; --i) { + + if (z[i] == 0.) Zeros++; + if (z[i] >= 65535.) Poles++; + if (z[i] < z[i-1]) { + cmsSignalError(Tab ->InterpParams->ContextID, cmsERROR_RANGE, "cmsSmoothToneCurve: Non-Monotonic."); + return FALSE; + } + } + + if (Zeros > (nItems / 3)) { + cmsSignalError(Tab ->InterpParams->ContextID, cmsERROR_RANGE, "cmsSmoothToneCurve: Degenerated, mostly zeros."); + return FALSE; + } + if (Poles > (nItems / 3)) { + cmsSignalError(Tab ->InterpParams->ContextID, cmsERROR_RANGE, "cmsSmoothToneCurve: Degenerated, mostly poles."); + return FALSE; + } + + // Seems ok + for (i=0; i < nItems; i++) { + + // Clamp to cmsUInt16Number + Tab -> Table16[i] = _cmsQuickSaturateWord(z[i+1]); + } + + return TRUE; +} + +// Is a table linear? Do not use parametric since we cannot guarantee some weird parameters resulting +// in a linear table. This way assures it is linear in 12 bits, which should be enought in most cases. +cmsBool CMSEXPORT cmsIsToneCurveLinear(const cmsToneCurve* Curve) +{ + cmsUInt32Number i; + int diff; + + _cmsAssert(Curve != NULL); + + for (i=0; i < Curve ->nEntries; i++) { + + diff = abs((int) Curve->Table16[i] - (int) _cmsQuantizeVal(i, Curve ->nEntries)); + if (diff > 0x0f) + return FALSE; + } + + return TRUE; +} + +// Same, but for monotonicity +cmsBool CMSEXPORT cmsIsToneCurveMonotonic(const cmsToneCurve* t) +{ + int n; + int i, last; + cmsBool lDescending; + + _cmsAssert(t != NULL); + + // Degenerated curves are monotonic? Ok, let's pass them + n = t ->nEntries; + if (n < 2) return TRUE; + + // Curve direction + lDescending = cmsIsToneCurveDescending(t); + + if (lDescending) { + + last = t ->Table16[0]; + + for (i = 1; i < n; i++) { + + if (t ->Table16[i] - last > 2) // We allow some ripple + return FALSE; + else + last = t ->Table16[i]; + + } + } + else { + + last = t ->Table16[n-1]; + + for (i = n-2; i >= 0; --i) { + + if (t ->Table16[i] - last > 2) + return FALSE; + else + last = t ->Table16[i]; + + } + } + + return TRUE; +} + +// Same, but for descending tables +cmsBool CMSEXPORT cmsIsToneCurveDescending(const cmsToneCurve* t) +{ + _cmsAssert(t != NULL); + + return t ->Table16[0] > t ->Table16[t ->nEntries-1]; +} + + +// Another info fn: is out gamma table multisegment? +cmsBool CMSEXPORT cmsIsToneCurveMultisegment(const cmsToneCurve* t) +{ + _cmsAssert(t != NULL); + + return t -> nSegments > 1; +} + +cmsInt32Number CMSEXPORT cmsGetToneCurveParametricType(const cmsToneCurve* t) +{ + _cmsAssert(t != NULL); + + if (t -> nSegments != 1) return 0; + return t ->Segments[0].Type; +} + +// We need accuracy this time +cmsFloat32Number CMSEXPORT cmsEvalToneCurveFloat(const cmsToneCurve* Curve, cmsFloat32Number v) +{ + _cmsAssert(Curve != NULL); + + // Check for 16 bits table. If so, this is a limited-precision tone curve + if (Curve ->nSegments == 0) { + + cmsUInt16Number In, Out; + + In = (cmsUInt16Number) _cmsQuickSaturateWord(v * 65535.0); + Out = cmsEvalToneCurve16(Curve, In); + + return (cmsFloat32Number) (Out / 65535.0); + } + + return (cmsFloat32Number) EvalSegmentedFn(Curve, v); +} + +// We need xput over here +cmsUInt16Number CMSEXPORT cmsEvalToneCurve16(const cmsToneCurve* Curve, cmsUInt16Number v) +{ + cmsUInt16Number out; + + _cmsAssert(Curve != NULL); + + Curve ->InterpParams ->Interpolation.Lerp16(&v, &out, Curve ->InterpParams); + return out; +} + + +// Least squares fitting. +// A mathematical procedure for finding the best-fitting curve to a given set of points by +// minimizing the sum of the squares of the offsets ("the residuals") of the points from the curve. +// The sum of the squares of the offsets is used instead of the offset absolute values because +// this allows the residuals to be treated as a continuous differentiable quantity. +// +// y = f(x) = x ^ g +// +// R = (yi - (xi^g)) +// R2 = (yi - (xi^g))2 +// SUM R2 = SUM (yi - (xi^g))2 +// +// dR2/dg = -2 SUM x^g log(x)(y - x^g) +// solving for dR2/dg = 0 +// +// g = 1/n * SUM(log(y) / log(x)) + +cmsFloat64Number CMSEXPORT cmsEstimateGamma(const cmsToneCurve* t, cmsFloat64Number Precision) +{ + cmsFloat64Number gamma, sum, sum2; + cmsFloat64Number n, x, y, Std; + cmsUInt32Number i; + + _cmsAssert(t != NULL); + + sum = sum2 = n = 0; + + // Excluding endpoints + for (i=1; i < (MAX_NODES_IN_CURVE-1); i++) { + + x = (cmsFloat64Number) i / (MAX_NODES_IN_CURVE-1); + y = (cmsFloat64Number) cmsEvalToneCurveFloat(t, (cmsFloat32Number) x); + + // Avoid 7% on lower part to prevent + // artifacts due to linear ramps + + if (y > 0. && y < 1. && x > 0.07) { + + gamma = log(y) / log(x); + sum += gamma; + sum2 += gamma * gamma; + n++; + } + } + + // Take a look on SD to see if gamma isn't exponential at all + Std = sqrt((n * sum2 - sum * sum) / (n*(n-1))); + + if (Std > Precision) + return -1.0; + + return (sum / n); // The mean +} diff --git a/jni/lcms2-2.5/src/cmsgmt.c b/jni/lcms2-2.5/src/cmsgmt.c new file mode 100644 index 00000000..2966f0c6 --- /dev/null +++ b/jni/lcms2-2.5/src/cmsgmt.c @@ -0,0 +1,590 @@ +//--------------------------------------------------------------------------------- +// +// Little Color Management System +// Copyright (c) 1998-2012 Marti Maria Saguer +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//--------------------------------------------------------------------------------- +// + +#include "lcms2_internal.h" + + +// Auxiliar: append a Lab identity after the given sequence of profiles +// and return the transform. Lab profile is closed, rest of profiles are kept open. +cmsHTRANSFORM _cmsChain2Lab(cmsContext ContextID, + cmsUInt32Number nProfiles, + cmsUInt32Number InputFormat, + cmsUInt32Number OutputFormat, + const cmsUInt32Number Intents[], + const cmsHPROFILE hProfiles[], + const cmsBool BPC[], + const cmsFloat64Number AdaptationStates[], + cmsUInt32Number dwFlags) +{ + cmsHTRANSFORM xform; + cmsHPROFILE hLab; + cmsHPROFILE ProfileList[256]; + cmsBool BPCList[256]; + cmsFloat64Number AdaptationList[256]; + cmsUInt32Number IntentList[256]; + cmsUInt32Number i; + + // This is a rather big number and there is no need of dynamic memory + // since we are adding a profile, 254 + 1 = 255 and this is the limit + if (nProfiles > 254) return NULL; + + // The output space + hLab = cmsCreateLab4ProfileTHR(ContextID, NULL); + if (hLab == NULL) return NULL; + + // Create a copy of parameters + for (i=0; i < nProfiles; i++) { + + ProfileList[i] = hProfiles[i]; + BPCList[i] = BPC[i]; + AdaptationList[i] = AdaptationStates[i]; + IntentList[i] = Intents[i]; + } + + // Place Lab identity at chain's end. + ProfileList[nProfiles] = hLab; + BPCList[nProfiles] = 0; + AdaptationList[nProfiles] = 1.0; + IntentList[nProfiles] = INTENT_RELATIVE_COLORIMETRIC; + + // Create the transform + xform = cmsCreateExtendedTransform(ContextID, nProfiles + 1, ProfileList, + BPCList, + IntentList, + AdaptationList, + NULL, 0, + InputFormat, + OutputFormat, + dwFlags); + + cmsCloseProfile(hLab); + + return xform; +} + + +// Compute K -> L* relationship. Flags may include black point compensation. In this case, +// the relationship is assumed from the profile with BPC to a black point zero. +static +cmsToneCurve* ComputeKToLstar(cmsContext ContextID, + cmsUInt32Number nPoints, + cmsUInt32Number nProfiles, + const cmsUInt32Number Intents[], + const cmsHPROFILE hProfiles[], + const cmsBool BPC[], + const cmsFloat64Number AdaptationStates[], + cmsUInt32Number dwFlags) +{ + cmsToneCurve* out = NULL; + cmsUInt32Number i; + cmsHTRANSFORM xform; + cmsCIELab Lab; + cmsFloat32Number cmyk[4]; + cmsFloat32Number* SampledPoints; + + xform = _cmsChain2Lab(ContextID, nProfiles, TYPE_CMYK_FLT, TYPE_Lab_DBL, Intents, hProfiles, BPC, AdaptationStates, dwFlags); + if (xform == NULL) return NULL; + + SampledPoints = (cmsFloat32Number*) _cmsCalloc(ContextID, nPoints, sizeof(cmsFloat32Number)); + if (SampledPoints == NULL) goto Error; + + for (i=0; i < nPoints; i++) { + + cmyk[0] = 0; + cmyk[1] = 0; + cmyk[2] = 0; + cmyk[3] = (cmsFloat32Number) ((i * 100.0) / (nPoints-1)); + + cmsDoTransform(xform, cmyk, &Lab, 1); + SampledPoints[i]= (cmsFloat32Number) (1.0 - Lab.L / 100.0); // Negate K for easier operation + } + + out = cmsBuildTabulatedToneCurveFloat(ContextID, nPoints, SampledPoints); + +Error: + + cmsDeleteTransform(xform); + if (SampledPoints) _cmsFree(ContextID, SampledPoints); + + return out; +} + + +// Compute Black tone curve on a CMYK -> CMYK transform. This is done by +// using the proof direction on both profiles to find K->L* relationship +// then joining both curves. dwFlags may include black point compensation. +cmsToneCurve* _cmsBuildKToneCurve(cmsContext ContextID, + cmsUInt32Number nPoints, + cmsUInt32Number nProfiles, + const cmsUInt32Number Intents[], + const cmsHPROFILE hProfiles[], + const cmsBool BPC[], + const cmsFloat64Number AdaptationStates[], + cmsUInt32Number dwFlags) +{ + cmsToneCurve *in, *out, *KTone; + + // Make sure CMYK -> CMYK + if (cmsGetColorSpace(hProfiles[0]) != cmsSigCmykData || + cmsGetColorSpace(hProfiles[nProfiles-1])!= cmsSigCmykData) return NULL; + + + // Make sure last is an output profile + if (cmsGetDeviceClass(hProfiles[nProfiles - 1]) != cmsSigOutputClass) return NULL; + + // Create individual curves. BPC works also as each K to L* is + // computed as a BPC to zero black point in case of L* + in = ComputeKToLstar(ContextID, nPoints, nProfiles - 1, Intents, hProfiles, BPC, AdaptationStates, dwFlags); + if (in == NULL) return NULL; + + out = ComputeKToLstar(ContextID, nPoints, 1, + Intents + (nProfiles - 1), + hProfiles + (nProfiles - 1), + BPC + (nProfiles - 1), + AdaptationStates + (nProfiles - 1), + dwFlags); + if (out == NULL) { + cmsFreeToneCurve(in); + return NULL; + } + + // Build the relationship. This effectively limits the maximum accuracy to 16 bits, but + // since this is used on black-preserving LUTs, we are not loosing accuracy in any case + KTone = cmsJoinToneCurve(ContextID, in, out, nPoints); + + // Get rid of components + cmsFreeToneCurve(in); cmsFreeToneCurve(out); + + // Something went wrong... + if (KTone == NULL) return NULL; + + // Make sure it is monotonic + if (!cmsIsToneCurveMonotonic(KTone)) { + cmsFreeToneCurve(KTone); + return NULL; + } + + return KTone; +} + + +// Gamut LUT Creation ----------------------------------------------------------------------------------------- + +// Used by gamut & softproofing + +typedef struct { + + cmsHTRANSFORM hInput; // From whatever input color space. 16 bits to DBL + cmsHTRANSFORM hForward, hReverse; // Transforms going from Lab to colorant and back + cmsFloat64Number Thereshold; // The thereshold after which is considered out of gamut + + } GAMUTCHAIN; + +// This sampler does compute gamut boundaries by comparing original +// values with a transform going back and forth. Values above ERR_THERESHOLD +// of maximum are considered out of gamut. + +#define ERR_THERESHOLD 5 + + +static +int GamutSampler(register const cmsUInt16Number In[], register cmsUInt16Number Out[], register void* Cargo) +{ + GAMUTCHAIN* t = (GAMUTCHAIN* ) Cargo; + cmsCIELab LabIn1, LabOut1; + cmsCIELab LabIn2, LabOut2; + cmsUInt16Number Proof[cmsMAXCHANNELS], Proof2[cmsMAXCHANNELS]; + cmsFloat64Number dE1, dE2, ErrorRatio; + + // Assume in-gamut by default. + ErrorRatio = 1.0; + + // Convert input to Lab + cmsDoTransform(t -> hInput, In, &LabIn1, 1); + + // converts from PCS to colorant. This always + // does return in-gamut values, + cmsDoTransform(t -> hForward, &LabIn1, Proof, 1); + + // Now, do the inverse, from colorant to PCS. + cmsDoTransform(t -> hReverse, Proof, &LabOut1, 1); + + memmove(&LabIn2, &LabOut1, sizeof(cmsCIELab)); + + // Try again, but this time taking Check as input + cmsDoTransform(t -> hForward, &LabOut1, Proof2, 1); + cmsDoTransform(t -> hReverse, Proof2, &LabOut2, 1); + + // Take difference of direct value + dE1 = cmsDeltaE(&LabIn1, &LabOut1); + + // Take difference of converted value + dE2 = cmsDeltaE(&LabIn2, &LabOut2); + + + // if dE1 is small and dE2 is small, value is likely to be in gamut + if (dE1 < t->Thereshold && dE2 < t->Thereshold) + Out[0] = 0; + else { + + // if dE1 is small and dE2 is big, undefined. Assume in gamut + if (dE1 < t->Thereshold && dE2 > t->Thereshold) + Out[0] = 0; + else + // dE1 is big and dE2 is small, clearly out of gamut + if (dE1 > t->Thereshold && dE2 < t->Thereshold) + Out[0] = (cmsUInt16Number) _cmsQuickFloor((dE1 - t->Thereshold) + .5); + else { + + // dE1 is big and dE2 is also big, could be due to perceptual mapping + // so take error ratio + if (dE2 == 0.0) + ErrorRatio = dE1; + else + ErrorRatio = dE1 / dE2; + + if (ErrorRatio > t->Thereshold) + Out[0] = (cmsUInt16Number) _cmsQuickFloor((ErrorRatio - t->Thereshold) + .5); + else + Out[0] = 0; + } + } + + + return TRUE; +} + +// Does compute a gamut LUT going back and forth across pcs -> relativ. colorimetric intent -> pcs +// the dE obtained is then annotated on the LUT. Values truely out of gamut are clipped to dE = 0xFFFE +// and values changed are supposed to be handled by any gamut remapping, so, are out of gamut as well. +// +// **WARNING: This algorithm does assume that gamut remapping algorithms does NOT move in-gamut colors, +// of course, many perceptual and saturation intents does not work in such way, but relativ. ones should. + +cmsPipeline* _cmsCreateGamutCheckPipeline(cmsContext ContextID, + cmsHPROFILE hProfiles[], + cmsBool BPC[], + cmsUInt32Number Intents[], + cmsFloat64Number AdaptationStates[], + cmsUInt32Number nGamutPCSposition, + cmsHPROFILE hGamut) +{ + cmsHPROFILE hLab; + cmsPipeline* Gamut; + cmsStage* CLUT; + cmsUInt32Number dwFormat; + GAMUTCHAIN Chain; + int nChannels, nGridpoints; + cmsColorSpaceSignature ColorSpace; + cmsUInt32Number i; + cmsHPROFILE ProfileList[256]; + cmsBool BPCList[256]; + cmsFloat64Number AdaptationList[256]; + cmsUInt32Number IntentList[256]; + + memset(&Chain, 0, sizeof(GAMUTCHAIN)); + + + if (nGamutPCSposition <= 0 || nGamutPCSposition > 255) { + cmsSignalError(ContextID, cmsERROR_RANGE, "Wrong position of PCS. 1..255 expected, %d found.", nGamutPCSposition); + return NULL; + } + + hLab = cmsCreateLab4ProfileTHR(ContextID, NULL); + if (hLab == NULL) return NULL; + + + // The figure of merit. On matrix-shaper profiles, should be almost zero as + // the conversion is pretty exact. On LUT based profiles, different resolutions + // of input and output CLUT may result in differences. + + if (cmsIsMatrixShaper(hGamut)) { + + Chain.Thereshold = 1.0; + } + else { + Chain.Thereshold = ERR_THERESHOLD; + } + + + // Create a copy of parameters + for (i=0; i < nGamutPCSposition; i++) { + ProfileList[i] = hProfiles[i]; + BPCList[i] = BPC[i]; + AdaptationList[i] = AdaptationStates[i]; + IntentList[i] = Intents[i]; + } + + // Fill Lab identity + ProfileList[nGamutPCSposition] = hLab; + BPCList[nGamutPCSposition] = 0; + AdaptationList[nGamutPCSposition] = 1.0; + IntentList[nGamutPCSposition] = INTENT_RELATIVE_COLORIMETRIC; + + + ColorSpace = cmsGetColorSpace(hGamut); + + nChannels = cmsChannelsOf(ColorSpace); + nGridpoints = _cmsReasonableGridpointsByColorspace(ColorSpace, cmsFLAGS_HIGHRESPRECALC); + dwFormat = (CHANNELS_SH(nChannels)|BYTES_SH(2)); + + // 16 bits to Lab double + Chain.hInput = cmsCreateExtendedTransform(ContextID, + nGamutPCSposition + 1, + ProfileList, + BPCList, + IntentList, + AdaptationList, + NULL, 0, + dwFormat, TYPE_Lab_DBL, + cmsFLAGS_NOCACHE); + + + // Does create the forward step. Lab double to device + dwFormat = (CHANNELS_SH(nChannels)|BYTES_SH(2)); + Chain.hForward = cmsCreateTransformTHR(ContextID, + hLab, TYPE_Lab_DBL, + hGamut, dwFormat, + INTENT_RELATIVE_COLORIMETRIC, + cmsFLAGS_NOCACHE); + + // Does create the backwards step + Chain.hReverse = cmsCreateTransformTHR(ContextID, hGamut, dwFormat, + hLab, TYPE_Lab_DBL, + INTENT_RELATIVE_COLORIMETRIC, + cmsFLAGS_NOCACHE); + + + // All ok? + if (Chain.hInput && Chain.hForward && Chain.hReverse) { + + // Go on, try to compute gamut LUT from PCS. This consist on a single channel containing + // dE when doing a transform back and forth on the colorimetric intent. + + Gamut = cmsPipelineAlloc(ContextID, 3, 1); + if (Gamut != NULL) { + + CLUT = cmsStageAllocCLut16bit(ContextID, nGridpoints, nChannels, 1, NULL); + if (!cmsPipelineInsertStage(Gamut, cmsAT_BEGIN, CLUT)) { + cmsPipelineFree(Gamut); + Gamut = NULL; + } + else { + cmsStageSampleCLut16bit(CLUT, GamutSampler, (void*) &Chain, 0); + } + } + } + else + Gamut = NULL; // Didn't work... + + // Free all needed stuff. + if (Chain.hInput) cmsDeleteTransform(Chain.hInput); + if (Chain.hForward) cmsDeleteTransform(Chain.hForward); + if (Chain.hReverse) cmsDeleteTransform(Chain.hReverse); + if (hLab) cmsCloseProfile(hLab); + + // And return computed hull + return Gamut; +} + +// Total Area Coverage estimation ---------------------------------------------------------------- + +typedef struct { + cmsUInt32Number nOutputChans; + cmsHTRANSFORM hRoundTrip; + cmsFloat32Number MaxTAC; + cmsFloat32Number MaxInput[cmsMAXCHANNELS]; + +} cmsTACestimator; + + +// This callback just accounts the maximum ink dropped in the given node. It does not populate any +// memory, as the destination table is NULL. Its only purpose it to know the global maximum. +static +int EstimateTAC(register const cmsUInt16Number In[], register cmsUInt16Number Out[], register void * Cargo) +{ + cmsTACestimator* bp = (cmsTACestimator*) Cargo; + cmsFloat32Number RoundTrip[cmsMAXCHANNELS]; + cmsUInt32Number i; + cmsFloat32Number Sum; + + + // Evaluate the xform + cmsDoTransform(bp->hRoundTrip, In, RoundTrip, 1); + + // All all amounts of ink + for (Sum=0, i=0; i < bp ->nOutputChans; i++) + Sum += RoundTrip[i]; + + // If above maximum, keep track of input values + if (Sum > bp ->MaxTAC) { + + bp ->MaxTAC = Sum; + + for (i=0; i < bp ->nOutputChans; i++) { + bp ->MaxInput[i] = In[i]; + } + } + + return TRUE; + + cmsUNUSED_PARAMETER(Out); +} + + +// Detect Total area coverage of the profile +cmsFloat64Number CMSEXPORT cmsDetectTAC(cmsHPROFILE hProfile) +{ + cmsTACestimator bp; + cmsUInt32Number dwFormatter; + cmsUInt32Number GridPoints[MAX_INPUT_DIMENSIONS]; + cmsHPROFILE hLab; + cmsContext ContextID = cmsGetProfileContextID(hProfile); + + // TAC only works on output profiles + if (cmsGetDeviceClass(hProfile) != cmsSigOutputClass) { + return 0; + } + + // Create a fake formatter for result + dwFormatter = cmsFormatterForColorspaceOfProfile(hProfile, 4, TRUE); + + bp.nOutputChans = T_CHANNELS(dwFormatter); + bp.MaxTAC = 0; // Initial TAC is 0 + + // for safety + if (bp.nOutputChans >= cmsMAXCHANNELS) return 0; + + hLab = cmsCreateLab4ProfileTHR(ContextID, NULL); + if (hLab == NULL) return 0; + // Setup a roundtrip on perceptual intent in output profile for TAC estimation + bp.hRoundTrip = cmsCreateTransformTHR(ContextID, hLab, TYPE_Lab_16, + hProfile, dwFormatter, INTENT_PERCEPTUAL, cmsFLAGS_NOOPTIMIZE|cmsFLAGS_NOCACHE); + + cmsCloseProfile(hLab); + if (bp.hRoundTrip == NULL) return 0; + + // For L* we only need black and white. For C* we need many points + GridPoints[0] = 6; + GridPoints[1] = 74; + GridPoints[2] = 74; + + + if (!cmsSliceSpace16(3, GridPoints, EstimateTAC, &bp)) { + bp.MaxTAC = 0; + } + + cmsDeleteTransform(bp.hRoundTrip); + + // Results in % + return bp.MaxTAC; +} + + +// Carefully, clamp on CIELab space. + +cmsBool CMSEXPORT cmsDesaturateLab(cmsCIELab* Lab, + double amax, double amin, + double bmax, double bmin) +{ + + // Whole Luma surface to zero + + if (Lab -> L < 0) { + + Lab-> L = Lab->a = Lab-> b = 0.0; + return FALSE; + } + + // Clamp white, DISCARD HIGHLIGHTS. This is done + // in such way because icc spec doesn't allow the + // use of L>100 as a highlight means. + + if (Lab->L > 100) + Lab -> L = 100; + + // Check out gamut prism, on a, b faces + + if (Lab -> a < amin || Lab->a > amax|| + Lab -> b < bmin || Lab->b > bmax) { + + cmsCIELCh LCh; + double h, slope; + + // Falls outside a, b limits. Transports to LCh space, + // and then do the clipping + + + if (Lab -> a == 0.0) { // Is hue exactly 90? + + // atan will not work, so clamp here + Lab -> b = Lab->b < 0 ? bmin : bmax; + return TRUE; + } + + cmsLab2LCh(&LCh, Lab); + + slope = Lab -> b / Lab -> a; + h = LCh.h; + + // There are 4 zones + + if ((h >= 0. && h < 45.) || + (h >= 315 && h <= 360.)) { + + // clip by amax + Lab -> a = amax; + Lab -> b = amax * slope; + } + else + if (h >= 45. && h < 135.) + { + // clip by bmax + Lab -> b = bmax; + Lab -> a = bmax / slope; + } + else + if (h >= 135. && h < 225.) { + // clip by amin + Lab -> a = amin; + Lab -> b = amin * slope; + + } + else + if (h >= 225. && h < 315.) { + // clip by bmin + Lab -> b = bmin; + Lab -> a = bmin / slope; + } + else { + cmsSignalError(0, cmsERROR_RANGE, "Invalid angle"); + return FALSE; + } + + } + + return TRUE; +} diff --git a/jni/lcms2-2.5/src/cmshalf.c b/jni/lcms2-2.5/src/cmshalf.c new file mode 100644 index 00000000..204dee96 --- /dev/null +++ b/jni/lcms2-2.5/src/cmshalf.c @@ -0,0 +1,535 @@ +//--------------------------------------------------------------------------------- +// +// Little Color Management System +// Copyright (c) 1998-2012 Marti Maria Saguer +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//--------------------------------------------------------------------------------- +// +// +#include "lcms2_internal.h" + +#ifndef CMS_NO_HALF_SUPPORT + +// This code is inspired in the paper "Fast Half Float Conversions" +// by Jeroen van der Zijp + +static cmsUInt32Number Mantissa[2048] = { + +0x00000000, 0x33800000, 0x34000000, 0x34400000, 0x34800000, 0x34a00000, +0x34c00000, 0x34e00000, 0x35000000, 0x35100000, 0x35200000, 0x35300000, +0x35400000, 0x35500000, 0x35600000, 0x35700000, 0x35800000, 0x35880000, +0x35900000, 0x35980000, 0x35a00000, 0x35a80000, 0x35b00000, 0x35b80000, +0x35c00000, 0x35c80000, 0x35d00000, 0x35d80000, 0x35e00000, 0x35e80000, +0x35f00000, 0x35f80000, 0x36000000, 0x36040000, 0x36080000, 0x360c0000, +0x36100000, 0x36140000, 0x36180000, 0x361c0000, 0x36200000, 0x36240000, +0x36280000, 0x362c0000, 0x36300000, 0x36340000, 0x36380000, 0x363c0000, +0x36400000, 0x36440000, 0x36480000, 0x364c0000, 0x36500000, 0x36540000, +0x36580000, 0x365c0000, 0x36600000, 0x36640000, 0x36680000, 0x366c0000, +0x36700000, 0x36740000, 0x36780000, 0x367c0000, 0x36800000, 0x36820000, +0x36840000, 0x36860000, 0x36880000, 0x368a0000, 0x368c0000, 0x368e0000, +0x36900000, 0x36920000, 0x36940000, 0x36960000, 0x36980000, 0x369a0000, +0x369c0000, 0x369e0000, 0x36a00000, 0x36a20000, 0x36a40000, 0x36a60000, +0x36a80000, 0x36aa0000, 0x36ac0000, 0x36ae0000, 0x36b00000, 0x36b20000, +0x36b40000, 0x36b60000, 0x36b80000, 0x36ba0000, 0x36bc0000, 0x36be0000, +0x36c00000, 0x36c20000, 0x36c40000, 0x36c60000, 0x36c80000, 0x36ca0000, +0x36cc0000, 0x36ce0000, 0x36d00000, 0x36d20000, 0x36d40000, 0x36d60000, +0x36d80000, 0x36da0000, 0x36dc0000, 0x36de0000, 0x36e00000, 0x36e20000, +0x36e40000, 0x36e60000, 0x36e80000, 0x36ea0000, 0x36ec0000, 0x36ee0000, +0x36f00000, 0x36f20000, 0x36f40000, 0x36f60000, 0x36f80000, 0x36fa0000, +0x36fc0000, 0x36fe0000, 0x37000000, 0x37010000, 0x37020000, 0x37030000, +0x37040000, 0x37050000, 0x37060000, 0x37070000, 0x37080000, 0x37090000, +0x370a0000, 0x370b0000, 0x370c0000, 0x370d0000, 0x370e0000, 0x370f0000, +0x37100000, 0x37110000, 0x37120000, 0x37130000, 0x37140000, 0x37150000, +0x37160000, 0x37170000, 0x37180000, 0x37190000, 0x371a0000, 0x371b0000, +0x371c0000, 0x371d0000, 0x371e0000, 0x371f0000, 0x37200000, 0x37210000, +0x37220000, 0x37230000, 0x37240000, 0x37250000, 0x37260000, 0x37270000, +0x37280000, 0x37290000, 0x372a0000, 0x372b0000, 0x372c0000, 0x372d0000, +0x372e0000, 0x372f0000, 0x37300000, 0x37310000, 0x37320000, 0x37330000, +0x37340000, 0x37350000, 0x37360000, 0x37370000, 0x37380000, 0x37390000, +0x373a0000, 0x373b0000, 0x373c0000, 0x373d0000, 0x373e0000, 0x373f0000, +0x37400000, 0x37410000, 0x37420000, 0x37430000, 0x37440000, 0x37450000, +0x37460000, 0x37470000, 0x37480000, 0x37490000, 0x374a0000, 0x374b0000, +0x374c0000, 0x374d0000, 0x374e0000, 0x374f0000, 0x37500000, 0x37510000, +0x37520000, 0x37530000, 0x37540000, 0x37550000, 0x37560000, 0x37570000, +0x37580000, 0x37590000, 0x375a0000, 0x375b0000, 0x375c0000, 0x375d0000, +0x375e0000, 0x375f0000, 0x37600000, 0x37610000, 0x37620000, 0x37630000, +0x37640000, 0x37650000, 0x37660000, 0x37670000, 0x37680000, 0x37690000, +0x376a0000, 0x376b0000, 0x376c0000, 0x376d0000, 0x376e0000, 0x376f0000, +0x37700000, 0x37710000, 0x37720000, 0x37730000, 0x37740000, 0x37750000, +0x37760000, 0x37770000, 0x37780000, 0x37790000, 0x377a0000, 0x377b0000, +0x377c0000, 0x377d0000, 0x377e0000, 0x377f0000, 0x37800000, 0x37808000, +0x37810000, 0x37818000, 0x37820000, 0x37828000, 0x37830000, 0x37838000, +0x37840000, 0x37848000, 0x37850000, 0x37858000, 0x37860000, 0x37868000, +0x37870000, 0x37878000, 0x37880000, 0x37888000, 0x37890000, 0x37898000, +0x378a0000, 0x378a8000, 0x378b0000, 0x378b8000, 0x378c0000, 0x378c8000, +0x378d0000, 0x378d8000, 0x378e0000, 0x378e8000, 0x378f0000, 0x378f8000, +0x37900000, 0x37908000, 0x37910000, 0x37918000, 0x37920000, 0x37928000, +0x37930000, 0x37938000, 0x37940000, 0x37948000, 0x37950000, 0x37958000, +0x37960000, 0x37968000, 0x37970000, 0x37978000, 0x37980000, 0x37988000, +0x37990000, 0x37998000, 0x379a0000, 0x379a8000, 0x379b0000, 0x379b8000, +0x379c0000, 0x379c8000, 0x379d0000, 0x379d8000, 0x379e0000, 0x379e8000, +0x379f0000, 0x379f8000, 0x37a00000, 0x37a08000, 0x37a10000, 0x37a18000, +0x37a20000, 0x37a28000, 0x37a30000, 0x37a38000, 0x37a40000, 0x37a48000, +0x37a50000, 0x37a58000, 0x37a60000, 0x37a68000, 0x37a70000, 0x37a78000, +0x37a80000, 0x37a88000, 0x37a90000, 0x37a98000, 0x37aa0000, 0x37aa8000, +0x37ab0000, 0x37ab8000, 0x37ac0000, 0x37ac8000, 0x37ad0000, 0x37ad8000, +0x37ae0000, 0x37ae8000, 0x37af0000, 0x37af8000, 0x37b00000, 0x37b08000, +0x37b10000, 0x37b18000, 0x37b20000, 0x37b28000, 0x37b30000, 0x37b38000, +0x37b40000, 0x37b48000, 0x37b50000, 0x37b58000, 0x37b60000, 0x37b68000, +0x37b70000, 0x37b78000, 0x37b80000, 0x37b88000, 0x37b90000, 0x37b98000, +0x37ba0000, 0x37ba8000, 0x37bb0000, 0x37bb8000, 0x37bc0000, 0x37bc8000, +0x37bd0000, 0x37bd8000, 0x37be0000, 0x37be8000, 0x37bf0000, 0x37bf8000, +0x37c00000, 0x37c08000, 0x37c10000, 0x37c18000, 0x37c20000, 0x37c28000, +0x37c30000, 0x37c38000, 0x37c40000, 0x37c48000, 0x37c50000, 0x37c58000, +0x37c60000, 0x37c68000, 0x37c70000, 0x37c78000, 0x37c80000, 0x37c88000, +0x37c90000, 0x37c98000, 0x37ca0000, 0x37ca8000, 0x37cb0000, 0x37cb8000, +0x37cc0000, 0x37cc8000, 0x37cd0000, 0x37cd8000, 0x37ce0000, 0x37ce8000, +0x37cf0000, 0x37cf8000, 0x37d00000, 0x37d08000, 0x37d10000, 0x37d18000, +0x37d20000, 0x37d28000, 0x37d30000, 0x37d38000, 0x37d40000, 0x37d48000, +0x37d50000, 0x37d58000, 0x37d60000, 0x37d68000, 0x37d70000, 0x37d78000, +0x37d80000, 0x37d88000, 0x37d90000, 0x37d98000, 0x37da0000, 0x37da8000, +0x37db0000, 0x37db8000, 0x37dc0000, 0x37dc8000, 0x37dd0000, 0x37dd8000, +0x37de0000, 0x37de8000, 0x37df0000, 0x37df8000, 0x37e00000, 0x37e08000, +0x37e10000, 0x37e18000, 0x37e20000, 0x37e28000, 0x37e30000, 0x37e38000, +0x37e40000, 0x37e48000, 0x37e50000, 0x37e58000, 0x37e60000, 0x37e68000, +0x37e70000, 0x37e78000, 0x37e80000, 0x37e88000, 0x37e90000, 0x37e98000, +0x37ea0000, 0x37ea8000, 0x37eb0000, 0x37eb8000, 0x37ec0000, 0x37ec8000, +0x37ed0000, 0x37ed8000, 0x37ee0000, 0x37ee8000, 0x37ef0000, 0x37ef8000, +0x37f00000, 0x37f08000, 0x37f10000, 0x37f18000, 0x37f20000, 0x37f28000, +0x37f30000, 0x37f38000, 0x37f40000, 0x37f48000, 0x37f50000, 0x37f58000, +0x37f60000, 0x37f68000, 0x37f70000, 0x37f78000, 0x37f80000, 0x37f88000, +0x37f90000, 0x37f98000, 0x37fa0000, 0x37fa8000, 0x37fb0000, 0x37fb8000, +0x37fc0000, 0x37fc8000, 0x37fd0000, 0x37fd8000, 0x37fe0000, 0x37fe8000, +0x37ff0000, 0x37ff8000, 0x38000000, 0x38004000, 0x38008000, 0x3800c000, +0x38010000, 0x38014000, 0x38018000, 0x3801c000, 0x38020000, 0x38024000, +0x38028000, 0x3802c000, 0x38030000, 0x38034000, 0x38038000, 0x3803c000, +0x38040000, 0x38044000, 0x38048000, 0x3804c000, 0x38050000, 0x38054000, +0x38058000, 0x3805c000, 0x38060000, 0x38064000, 0x38068000, 0x3806c000, +0x38070000, 0x38074000, 0x38078000, 0x3807c000, 0x38080000, 0x38084000, +0x38088000, 0x3808c000, 0x38090000, 0x38094000, 0x38098000, 0x3809c000, +0x380a0000, 0x380a4000, 0x380a8000, 0x380ac000, 0x380b0000, 0x380b4000, +0x380b8000, 0x380bc000, 0x380c0000, 0x380c4000, 0x380c8000, 0x380cc000, +0x380d0000, 0x380d4000, 0x380d8000, 0x380dc000, 0x380e0000, 0x380e4000, +0x380e8000, 0x380ec000, 0x380f0000, 0x380f4000, 0x380f8000, 0x380fc000, +0x38100000, 0x38104000, 0x38108000, 0x3810c000, 0x38110000, 0x38114000, +0x38118000, 0x3811c000, 0x38120000, 0x38124000, 0x38128000, 0x3812c000, +0x38130000, 0x38134000, 0x38138000, 0x3813c000, 0x38140000, 0x38144000, +0x38148000, 0x3814c000, 0x38150000, 0x38154000, 0x38158000, 0x3815c000, +0x38160000, 0x38164000, 0x38168000, 0x3816c000, 0x38170000, 0x38174000, +0x38178000, 0x3817c000, 0x38180000, 0x38184000, 0x38188000, 0x3818c000, +0x38190000, 0x38194000, 0x38198000, 0x3819c000, 0x381a0000, 0x381a4000, +0x381a8000, 0x381ac000, 0x381b0000, 0x381b4000, 0x381b8000, 0x381bc000, +0x381c0000, 0x381c4000, 0x381c8000, 0x381cc000, 0x381d0000, 0x381d4000, +0x381d8000, 0x381dc000, 0x381e0000, 0x381e4000, 0x381e8000, 0x381ec000, +0x381f0000, 0x381f4000, 0x381f8000, 0x381fc000, 0x38200000, 0x38204000, +0x38208000, 0x3820c000, 0x38210000, 0x38214000, 0x38218000, 0x3821c000, +0x38220000, 0x38224000, 0x38228000, 0x3822c000, 0x38230000, 0x38234000, +0x38238000, 0x3823c000, 0x38240000, 0x38244000, 0x38248000, 0x3824c000, +0x38250000, 0x38254000, 0x38258000, 0x3825c000, 0x38260000, 0x38264000, +0x38268000, 0x3826c000, 0x38270000, 0x38274000, 0x38278000, 0x3827c000, +0x38280000, 0x38284000, 0x38288000, 0x3828c000, 0x38290000, 0x38294000, +0x38298000, 0x3829c000, 0x382a0000, 0x382a4000, 0x382a8000, 0x382ac000, +0x382b0000, 0x382b4000, 0x382b8000, 0x382bc000, 0x382c0000, 0x382c4000, +0x382c8000, 0x382cc000, 0x382d0000, 0x382d4000, 0x382d8000, 0x382dc000, +0x382e0000, 0x382e4000, 0x382e8000, 0x382ec000, 0x382f0000, 0x382f4000, +0x382f8000, 0x382fc000, 0x38300000, 0x38304000, 0x38308000, 0x3830c000, +0x38310000, 0x38314000, 0x38318000, 0x3831c000, 0x38320000, 0x38324000, +0x38328000, 0x3832c000, 0x38330000, 0x38334000, 0x38338000, 0x3833c000, +0x38340000, 0x38344000, 0x38348000, 0x3834c000, 0x38350000, 0x38354000, +0x38358000, 0x3835c000, 0x38360000, 0x38364000, 0x38368000, 0x3836c000, +0x38370000, 0x38374000, 0x38378000, 0x3837c000, 0x38380000, 0x38384000, +0x38388000, 0x3838c000, 0x38390000, 0x38394000, 0x38398000, 0x3839c000, +0x383a0000, 0x383a4000, 0x383a8000, 0x383ac000, 0x383b0000, 0x383b4000, +0x383b8000, 0x383bc000, 0x383c0000, 0x383c4000, 0x383c8000, 0x383cc000, +0x383d0000, 0x383d4000, 0x383d8000, 0x383dc000, 0x383e0000, 0x383e4000, +0x383e8000, 0x383ec000, 0x383f0000, 0x383f4000, 0x383f8000, 0x383fc000, +0x38400000, 0x38404000, 0x38408000, 0x3840c000, 0x38410000, 0x38414000, +0x38418000, 0x3841c000, 0x38420000, 0x38424000, 0x38428000, 0x3842c000, +0x38430000, 0x38434000, 0x38438000, 0x3843c000, 0x38440000, 0x38444000, +0x38448000, 0x3844c000, 0x38450000, 0x38454000, 0x38458000, 0x3845c000, +0x38460000, 0x38464000, 0x38468000, 0x3846c000, 0x38470000, 0x38474000, +0x38478000, 0x3847c000, 0x38480000, 0x38484000, 0x38488000, 0x3848c000, +0x38490000, 0x38494000, 0x38498000, 0x3849c000, 0x384a0000, 0x384a4000, +0x384a8000, 0x384ac000, 0x384b0000, 0x384b4000, 0x384b8000, 0x384bc000, +0x384c0000, 0x384c4000, 0x384c8000, 0x384cc000, 0x384d0000, 0x384d4000, +0x384d8000, 0x384dc000, 0x384e0000, 0x384e4000, 0x384e8000, 0x384ec000, +0x384f0000, 0x384f4000, 0x384f8000, 0x384fc000, 0x38500000, 0x38504000, +0x38508000, 0x3850c000, 0x38510000, 0x38514000, 0x38518000, 0x3851c000, +0x38520000, 0x38524000, 0x38528000, 0x3852c000, 0x38530000, 0x38534000, +0x38538000, 0x3853c000, 0x38540000, 0x38544000, 0x38548000, 0x3854c000, +0x38550000, 0x38554000, 0x38558000, 0x3855c000, 0x38560000, 0x38564000, +0x38568000, 0x3856c000, 0x38570000, 0x38574000, 0x38578000, 0x3857c000, +0x38580000, 0x38584000, 0x38588000, 0x3858c000, 0x38590000, 0x38594000, +0x38598000, 0x3859c000, 0x385a0000, 0x385a4000, 0x385a8000, 0x385ac000, +0x385b0000, 0x385b4000, 0x385b8000, 0x385bc000, 0x385c0000, 0x385c4000, +0x385c8000, 0x385cc000, 0x385d0000, 0x385d4000, 0x385d8000, 0x385dc000, +0x385e0000, 0x385e4000, 0x385e8000, 0x385ec000, 0x385f0000, 0x385f4000, +0x385f8000, 0x385fc000, 0x38600000, 0x38604000, 0x38608000, 0x3860c000, +0x38610000, 0x38614000, 0x38618000, 0x3861c000, 0x38620000, 0x38624000, +0x38628000, 0x3862c000, 0x38630000, 0x38634000, 0x38638000, 0x3863c000, +0x38640000, 0x38644000, 0x38648000, 0x3864c000, 0x38650000, 0x38654000, +0x38658000, 0x3865c000, 0x38660000, 0x38664000, 0x38668000, 0x3866c000, +0x38670000, 0x38674000, 0x38678000, 0x3867c000, 0x38680000, 0x38684000, +0x38688000, 0x3868c000, 0x38690000, 0x38694000, 0x38698000, 0x3869c000, +0x386a0000, 0x386a4000, 0x386a8000, 0x386ac000, 0x386b0000, 0x386b4000, +0x386b8000, 0x386bc000, 0x386c0000, 0x386c4000, 0x386c8000, 0x386cc000, +0x386d0000, 0x386d4000, 0x386d8000, 0x386dc000, 0x386e0000, 0x386e4000, +0x386e8000, 0x386ec000, 0x386f0000, 0x386f4000, 0x386f8000, 0x386fc000, +0x38700000, 0x38704000, 0x38708000, 0x3870c000, 0x38710000, 0x38714000, +0x38718000, 0x3871c000, 0x38720000, 0x38724000, 0x38728000, 0x3872c000, +0x38730000, 0x38734000, 0x38738000, 0x3873c000, 0x38740000, 0x38744000, +0x38748000, 0x3874c000, 0x38750000, 0x38754000, 0x38758000, 0x3875c000, +0x38760000, 0x38764000, 0x38768000, 0x3876c000, 0x38770000, 0x38774000, +0x38778000, 0x3877c000, 0x38780000, 0x38784000, 0x38788000, 0x3878c000, +0x38790000, 0x38794000, 0x38798000, 0x3879c000, 0x387a0000, 0x387a4000, +0x387a8000, 0x387ac000, 0x387b0000, 0x387b4000, 0x387b8000, 0x387bc000, +0x387c0000, 0x387c4000, 0x387c8000, 0x387cc000, 0x387d0000, 0x387d4000, +0x387d8000, 0x387dc000, 0x387e0000, 0x387e4000, 0x387e8000, 0x387ec000, +0x387f0000, 0x387f4000, 0x387f8000, 0x387fc000, 0x38000000, 0x38002000, +0x38004000, 0x38006000, 0x38008000, 0x3800a000, 0x3800c000, 0x3800e000, +0x38010000, 0x38012000, 0x38014000, 0x38016000, 0x38018000, 0x3801a000, +0x3801c000, 0x3801e000, 0x38020000, 0x38022000, 0x38024000, 0x38026000, +0x38028000, 0x3802a000, 0x3802c000, 0x3802e000, 0x38030000, 0x38032000, +0x38034000, 0x38036000, 0x38038000, 0x3803a000, 0x3803c000, 0x3803e000, +0x38040000, 0x38042000, 0x38044000, 0x38046000, 0x38048000, 0x3804a000, +0x3804c000, 0x3804e000, 0x38050000, 0x38052000, 0x38054000, 0x38056000, +0x38058000, 0x3805a000, 0x3805c000, 0x3805e000, 0x38060000, 0x38062000, +0x38064000, 0x38066000, 0x38068000, 0x3806a000, 0x3806c000, 0x3806e000, +0x38070000, 0x38072000, 0x38074000, 0x38076000, 0x38078000, 0x3807a000, +0x3807c000, 0x3807e000, 0x38080000, 0x38082000, 0x38084000, 0x38086000, +0x38088000, 0x3808a000, 0x3808c000, 0x3808e000, 0x38090000, 0x38092000, +0x38094000, 0x38096000, 0x38098000, 0x3809a000, 0x3809c000, 0x3809e000, +0x380a0000, 0x380a2000, 0x380a4000, 0x380a6000, 0x380a8000, 0x380aa000, +0x380ac000, 0x380ae000, 0x380b0000, 0x380b2000, 0x380b4000, 0x380b6000, +0x380b8000, 0x380ba000, 0x380bc000, 0x380be000, 0x380c0000, 0x380c2000, +0x380c4000, 0x380c6000, 0x380c8000, 0x380ca000, 0x380cc000, 0x380ce000, +0x380d0000, 0x380d2000, 0x380d4000, 0x380d6000, 0x380d8000, 0x380da000, +0x380dc000, 0x380de000, 0x380e0000, 0x380e2000, 0x380e4000, 0x380e6000, +0x380e8000, 0x380ea000, 0x380ec000, 0x380ee000, 0x380f0000, 0x380f2000, +0x380f4000, 0x380f6000, 0x380f8000, 0x380fa000, 0x380fc000, 0x380fe000, +0x38100000, 0x38102000, 0x38104000, 0x38106000, 0x38108000, 0x3810a000, +0x3810c000, 0x3810e000, 0x38110000, 0x38112000, 0x38114000, 0x38116000, +0x38118000, 0x3811a000, 0x3811c000, 0x3811e000, 0x38120000, 0x38122000, +0x38124000, 0x38126000, 0x38128000, 0x3812a000, 0x3812c000, 0x3812e000, +0x38130000, 0x38132000, 0x38134000, 0x38136000, 0x38138000, 0x3813a000, +0x3813c000, 0x3813e000, 0x38140000, 0x38142000, 0x38144000, 0x38146000, +0x38148000, 0x3814a000, 0x3814c000, 0x3814e000, 0x38150000, 0x38152000, +0x38154000, 0x38156000, 0x38158000, 0x3815a000, 0x3815c000, 0x3815e000, +0x38160000, 0x38162000, 0x38164000, 0x38166000, 0x38168000, 0x3816a000, +0x3816c000, 0x3816e000, 0x38170000, 0x38172000, 0x38174000, 0x38176000, +0x38178000, 0x3817a000, 0x3817c000, 0x3817e000, 0x38180000, 0x38182000, +0x38184000, 0x38186000, 0x38188000, 0x3818a000, 0x3818c000, 0x3818e000, +0x38190000, 0x38192000, 0x38194000, 0x38196000, 0x38198000, 0x3819a000, +0x3819c000, 0x3819e000, 0x381a0000, 0x381a2000, 0x381a4000, 0x381a6000, +0x381a8000, 0x381aa000, 0x381ac000, 0x381ae000, 0x381b0000, 0x381b2000, +0x381b4000, 0x381b6000, 0x381b8000, 0x381ba000, 0x381bc000, 0x381be000, +0x381c0000, 0x381c2000, 0x381c4000, 0x381c6000, 0x381c8000, 0x381ca000, +0x381cc000, 0x381ce000, 0x381d0000, 0x381d2000, 0x381d4000, 0x381d6000, +0x381d8000, 0x381da000, 0x381dc000, 0x381de000, 0x381e0000, 0x381e2000, +0x381e4000, 0x381e6000, 0x381e8000, 0x381ea000, 0x381ec000, 0x381ee000, +0x381f0000, 0x381f2000, 0x381f4000, 0x381f6000, 0x381f8000, 0x381fa000, +0x381fc000, 0x381fe000, 0x38200000, 0x38202000, 0x38204000, 0x38206000, +0x38208000, 0x3820a000, 0x3820c000, 0x3820e000, 0x38210000, 0x38212000, +0x38214000, 0x38216000, 0x38218000, 0x3821a000, 0x3821c000, 0x3821e000, +0x38220000, 0x38222000, 0x38224000, 0x38226000, 0x38228000, 0x3822a000, +0x3822c000, 0x3822e000, 0x38230000, 0x38232000, 0x38234000, 0x38236000, +0x38238000, 0x3823a000, 0x3823c000, 0x3823e000, 0x38240000, 0x38242000, +0x38244000, 0x38246000, 0x38248000, 0x3824a000, 0x3824c000, 0x3824e000, +0x38250000, 0x38252000, 0x38254000, 0x38256000, 0x38258000, 0x3825a000, +0x3825c000, 0x3825e000, 0x38260000, 0x38262000, 0x38264000, 0x38266000, +0x38268000, 0x3826a000, 0x3826c000, 0x3826e000, 0x38270000, 0x38272000, +0x38274000, 0x38276000, 0x38278000, 0x3827a000, 0x3827c000, 0x3827e000, +0x38280000, 0x38282000, 0x38284000, 0x38286000, 0x38288000, 0x3828a000, +0x3828c000, 0x3828e000, 0x38290000, 0x38292000, 0x38294000, 0x38296000, +0x38298000, 0x3829a000, 0x3829c000, 0x3829e000, 0x382a0000, 0x382a2000, +0x382a4000, 0x382a6000, 0x382a8000, 0x382aa000, 0x382ac000, 0x382ae000, +0x382b0000, 0x382b2000, 0x382b4000, 0x382b6000, 0x382b8000, 0x382ba000, +0x382bc000, 0x382be000, 0x382c0000, 0x382c2000, 0x382c4000, 0x382c6000, +0x382c8000, 0x382ca000, 0x382cc000, 0x382ce000, 0x382d0000, 0x382d2000, +0x382d4000, 0x382d6000, 0x382d8000, 0x382da000, 0x382dc000, 0x382de000, +0x382e0000, 0x382e2000, 0x382e4000, 0x382e6000, 0x382e8000, 0x382ea000, +0x382ec000, 0x382ee000, 0x382f0000, 0x382f2000, 0x382f4000, 0x382f6000, +0x382f8000, 0x382fa000, 0x382fc000, 0x382fe000, 0x38300000, 0x38302000, +0x38304000, 0x38306000, 0x38308000, 0x3830a000, 0x3830c000, 0x3830e000, +0x38310000, 0x38312000, 0x38314000, 0x38316000, 0x38318000, 0x3831a000, +0x3831c000, 0x3831e000, 0x38320000, 0x38322000, 0x38324000, 0x38326000, +0x38328000, 0x3832a000, 0x3832c000, 0x3832e000, 0x38330000, 0x38332000, +0x38334000, 0x38336000, 0x38338000, 0x3833a000, 0x3833c000, 0x3833e000, +0x38340000, 0x38342000, 0x38344000, 0x38346000, 0x38348000, 0x3834a000, +0x3834c000, 0x3834e000, 0x38350000, 0x38352000, 0x38354000, 0x38356000, +0x38358000, 0x3835a000, 0x3835c000, 0x3835e000, 0x38360000, 0x38362000, +0x38364000, 0x38366000, 0x38368000, 0x3836a000, 0x3836c000, 0x3836e000, +0x38370000, 0x38372000, 0x38374000, 0x38376000, 0x38378000, 0x3837a000, +0x3837c000, 0x3837e000, 0x38380000, 0x38382000, 0x38384000, 0x38386000, +0x38388000, 0x3838a000, 0x3838c000, 0x3838e000, 0x38390000, 0x38392000, +0x38394000, 0x38396000, 0x38398000, 0x3839a000, 0x3839c000, 0x3839e000, +0x383a0000, 0x383a2000, 0x383a4000, 0x383a6000, 0x383a8000, 0x383aa000, +0x383ac000, 0x383ae000, 0x383b0000, 0x383b2000, 0x383b4000, 0x383b6000, +0x383b8000, 0x383ba000, 0x383bc000, 0x383be000, 0x383c0000, 0x383c2000, +0x383c4000, 0x383c6000, 0x383c8000, 0x383ca000, 0x383cc000, 0x383ce000, +0x383d0000, 0x383d2000, 0x383d4000, 0x383d6000, 0x383d8000, 0x383da000, +0x383dc000, 0x383de000, 0x383e0000, 0x383e2000, 0x383e4000, 0x383e6000, +0x383e8000, 0x383ea000, 0x383ec000, 0x383ee000, 0x383f0000, 0x383f2000, +0x383f4000, 0x383f6000, 0x383f8000, 0x383fa000, 0x383fc000, 0x383fe000, +0x38400000, 0x38402000, 0x38404000, 0x38406000, 0x38408000, 0x3840a000, +0x3840c000, 0x3840e000, 0x38410000, 0x38412000, 0x38414000, 0x38416000, +0x38418000, 0x3841a000, 0x3841c000, 0x3841e000, 0x38420000, 0x38422000, +0x38424000, 0x38426000, 0x38428000, 0x3842a000, 0x3842c000, 0x3842e000, +0x38430000, 0x38432000, 0x38434000, 0x38436000, 0x38438000, 0x3843a000, +0x3843c000, 0x3843e000, 0x38440000, 0x38442000, 0x38444000, 0x38446000, +0x38448000, 0x3844a000, 0x3844c000, 0x3844e000, 0x38450000, 0x38452000, +0x38454000, 0x38456000, 0x38458000, 0x3845a000, 0x3845c000, 0x3845e000, +0x38460000, 0x38462000, 0x38464000, 0x38466000, 0x38468000, 0x3846a000, +0x3846c000, 0x3846e000, 0x38470000, 0x38472000, 0x38474000, 0x38476000, +0x38478000, 0x3847a000, 0x3847c000, 0x3847e000, 0x38480000, 0x38482000, +0x38484000, 0x38486000, 0x38488000, 0x3848a000, 0x3848c000, 0x3848e000, +0x38490000, 0x38492000, 0x38494000, 0x38496000, 0x38498000, 0x3849a000, +0x3849c000, 0x3849e000, 0x384a0000, 0x384a2000, 0x384a4000, 0x384a6000, +0x384a8000, 0x384aa000, 0x384ac000, 0x384ae000, 0x384b0000, 0x384b2000, +0x384b4000, 0x384b6000, 0x384b8000, 0x384ba000, 0x384bc000, 0x384be000, +0x384c0000, 0x384c2000, 0x384c4000, 0x384c6000, 0x384c8000, 0x384ca000, +0x384cc000, 0x384ce000, 0x384d0000, 0x384d2000, 0x384d4000, 0x384d6000, +0x384d8000, 0x384da000, 0x384dc000, 0x384de000, 0x384e0000, 0x384e2000, +0x384e4000, 0x384e6000, 0x384e8000, 0x384ea000, 0x384ec000, 0x384ee000, +0x384f0000, 0x384f2000, 0x384f4000, 0x384f6000, 0x384f8000, 0x384fa000, +0x384fc000, 0x384fe000, 0x38500000, 0x38502000, 0x38504000, 0x38506000, +0x38508000, 0x3850a000, 0x3850c000, 0x3850e000, 0x38510000, 0x38512000, +0x38514000, 0x38516000, 0x38518000, 0x3851a000, 0x3851c000, 0x3851e000, +0x38520000, 0x38522000, 0x38524000, 0x38526000, 0x38528000, 0x3852a000, +0x3852c000, 0x3852e000, 0x38530000, 0x38532000, 0x38534000, 0x38536000, +0x38538000, 0x3853a000, 0x3853c000, 0x3853e000, 0x38540000, 0x38542000, +0x38544000, 0x38546000, 0x38548000, 0x3854a000, 0x3854c000, 0x3854e000, +0x38550000, 0x38552000, 0x38554000, 0x38556000, 0x38558000, 0x3855a000, +0x3855c000, 0x3855e000, 0x38560000, 0x38562000, 0x38564000, 0x38566000, +0x38568000, 0x3856a000, 0x3856c000, 0x3856e000, 0x38570000, 0x38572000, +0x38574000, 0x38576000, 0x38578000, 0x3857a000, 0x3857c000, 0x3857e000, +0x38580000, 0x38582000, 0x38584000, 0x38586000, 0x38588000, 0x3858a000, +0x3858c000, 0x3858e000, 0x38590000, 0x38592000, 0x38594000, 0x38596000, +0x38598000, 0x3859a000, 0x3859c000, 0x3859e000, 0x385a0000, 0x385a2000, +0x385a4000, 0x385a6000, 0x385a8000, 0x385aa000, 0x385ac000, 0x385ae000, +0x385b0000, 0x385b2000, 0x385b4000, 0x385b6000, 0x385b8000, 0x385ba000, +0x385bc000, 0x385be000, 0x385c0000, 0x385c2000, 0x385c4000, 0x385c6000, +0x385c8000, 0x385ca000, 0x385cc000, 0x385ce000, 0x385d0000, 0x385d2000, +0x385d4000, 0x385d6000, 0x385d8000, 0x385da000, 0x385dc000, 0x385de000, +0x385e0000, 0x385e2000, 0x385e4000, 0x385e6000, 0x385e8000, 0x385ea000, +0x385ec000, 0x385ee000, 0x385f0000, 0x385f2000, 0x385f4000, 0x385f6000, +0x385f8000, 0x385fa000, 0x385fc000, 0x385fe000, 0x38600000, 0x38602000, +0x38604000, 0x38606000, 0x38608000, 0x3860a000, 0x3860c000, 0x3860e000, +0x38610000, 0x38612000, 0x38614000, 0x38616000, 0x38618000, 0x3861a000, +0x3861c000, 0x3861e000, 0x38620000, 0x38622000, 0x38624000, 0x38626000, +0x38628000, 0x3862a000, 0x3862c000, 0x3862e000, 0x38630000, 0x38632000, +0x38634000, 0x38636000, 0x38638000, 0x3863a000, 0x3863c000, 0x3863e000, +0x38640000, 0x38642000, 0x38644000, 0x38646000, 0x38648000, 0x3864a000, +0x3864c000, 0x3864e000, 0x38650000, 0x38652000, 0x38654000, 0x38656000, +0x38658000, 0x3865a000, 0x3865c000, 0x3865e000, 0x38660000, 0x38662000, +0x38664000, 0x38666000, 0x38668000, 0x3866a000, 0x3866c000, 0x3866e000, +0x38670000, 0x38672000, 0x38674000, 0x38676000, 0x38678000, 0x3867a000, +0x3867c000, 0x3867e000, 0x38680000, 0x38682000, 0x38684000, 0x38686000, +0x38688000, 0x3868a000, 0x3868c000, 0x3868e000, 0x38690000, 0x38692000, +0x38694000, 0x38696000, 0x38698000, 0x3869a000, 0x3869c000, 0x3869e000, +0x386a0000, 0x386a2000, 0x386a4000, 0x386a6000, 0x386a8000, 0x386aa000, +0x386ac000, 0x386ae000, 0x386b0000, 0x386b2000, 0x386b4000, 0x386b6000, +0x386b8000, 0x386ba000, 0x386bc000, 0x386be000, 0x386c0000, 0x386c2000, +0x386c4000, 0x386c6000, 0x386c8000, 0x386ca000, 0x386cc000, 0x386ce000, +0x386d0000, 0x386d2000, 0x386d4000, 0x386d6000, 0x386d8000, 0x386da000, +0x386dc000, 0x386de000, 0x386e0000, 0x386e2000, 0x386e4000, 0x386e6000, +0x386e8000, 0x386ea000, 0x386ec000, 0x386ee000, 0x386f0000, 0x386f2000, +0x386f4000, 0x386f6000, 0x386f8000, 0x386fa000, 0x386fc000, 0x386fe000, +0x38700000, 0x38702000, 0x38704000, 0x38706000, 0x38708000, 0x3870a000, +0x3870c000, 0x3870e000, 0x38710000, 0x38712000, 0x38714000, 0x38716000, +0x38718000, 0x3871a000, 0x3871c000, 0x3871e000, 0x38720000, 0x38722000, +0x38724000, 0x38726000, 0x38728000, 0x3872a000, 0x3872c000, 0x3872e000, +0x38730000, 0x38732000, 0x38734000, 0x38736000, 0x38738000, 0x3873a000, +0x3873c000, 0x3873e000, 0x38740000, 0x38742000, 0x38744000, 0x38746000, +0x38748000, 0x3874a000, 0x3874c000, 0x3874e000, 0x38750000, 0x38752000, +0x38754000, 0x38756000, 0x38758000, 0x3875a000, 0x3875c000, 0x3875e000, +0x38760000, 0x38762000, 0x38764000, 0x38766000, 0x38768000, 0x3876a000, +0x3876c000, 0x3876e000, 0x38770000, 0x38772000, 0x38774000, 0x38776000, +0x38778000, 0x3877a000, 0x3877c000, 0x3877e000, 0x38780000, 0x38782000, +0x38784000, 0x38786000, 0x38788000, 0x3878a000, 0x3878c000, 0x3878e000, +0x38790000, 0x38792000, 0x38794000, 0x38796000, 0x38798000, 0x3879a000, +0x3879c000, 0x3879e000, 0x387a0000, 0x387a2000, 0x387a4000, 0x387a6000, +0x387a8000, 0x387aa000, 0x387ac000, 0x387ae000, 0x387b0000, 0x387b2000, +0x387b4000, 0x387b6000, 0x387b8000, 0x387ba000, 0x387bc000, 0x387be000, +0x387c0000, 0x387c2000, 0x387c4000, 0x387c6000, 0x387c8000, 0x387ca000, +0x387cc000, 0x387ce000, 0x387d0000, 0x387d2000, 0x387d4000, 0x387d6000, +0x387d8000, 0x387da000, 0x387dc000, 0x387de000, 0x387e0000, 0x387e2000, +0x387e4000, 0x387e6000, 0x387e8000, 0x387ea000, 0x387ec000, 0x387ee000, +0x387f0000, 0x387f2000, 0x387f4000, 0x387f6000, 0x387f8000, 0x387fa000, +0x387fc000, 0x387fe000 +}; + +static cmsUInt16Number Offset[64] = { +0x0000, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, +0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, +0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, +0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, +0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, +0x0400, 0x0400, 0x0000, 0x0400, 0x0400, 0x0400, +0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, +0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, +0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, +0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, +0x0400, 0x0400, 0x0400, 0x0400 +}; + +static cmsUInt32Number Exponent[64] = { +0x00000000, 0x00800000, 0x01000000, 0x01800000, 0x02000000, 0x02800000, +0x03000000, 0x03800000, 0x04000000, 0x04800000, 0x05000000, 0x05800000, +0x06000000, 0x06800000, 0x07000000, 0x07800000, 0x08000000, 0x08800000, +0x09000000, 0x09800000, 0x0a000000, 0x0a800000, 0x0b000000, 0x0b800000, +0x0c000000, 0x0c800000, 0x0d000000, 0x0d800000, 0x0e000000, 0x0e800000, +0x0f000000, 0x47800000, 0x80000000, 0x80800000, 0x81000000, 0x81800000, +0x82000000, 0x82800000, 0x83000000, 0x83800000, 0x84000000, 0x84800000, +0x85000000, 0x85800000, 0x86000000, 0x86800000, 0x87000000, 0x87800000, +0x88000000, 0x88800000, 0x89000000, 0x89800000, 0x8a000000, 0x8a800000, +0x8b000000, 0x8b800000, 0x8c000000, 0x8c800000, 0x8d000000, 0x8d800000, +0x8e000000, 0x8e800000, 0x8f000000, 0xc7800000 +}; + +static cmsUInt16Number Base[512] = { +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, +0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x0c00, 0x1000, 0x1400, 0x1800, 0x1c00, +0x2000, 0x2400, 0x2800, 0x2c00, 0x3000, 0x3400, 0x3800, 0x3c00, 0x4000, 0x4400, +0x4800, 0x4c00, 0x5000, 0x5400, 0x5800, 0x5c00, 0x6000, 0x6400, 0x6800, 0x6c00, +0x7000, 0x7400, 0x7800, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, +0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, +0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, +0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, +0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, +0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, +0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, +0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, +0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, +0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, +0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, +0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x8000, 0x8000, 0x8000, 0x8000, +0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, +0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, +0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, +0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, +0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, +0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, +0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, +0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, +0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, +0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8001, +0x8002, 0x8004, 0x8008, 0x8010, 0x8020, 0x8040, 0x8080, 0x8100, 0x8200, 0x8400, +0x8800, 0x8c00, 0x9000, 0x9400, 0x9800, 0x9c00, 0xa000, 0xa400, 0xa800, 0xac00, +0xb000, 0xb400, 0xb800, 0xbc00, 0xc000, 0xc400, 0xc800, 0xcc00, 0xd000, 0xd400, +0xd800, 0xdc00, 0xe000, 0xe400, 0xe800, 0xec00, 0xf000, 0xf400, 0xf800, 0xfc00, +0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, +0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, +0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, +0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, +0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, +0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, +0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, +0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, +0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, +0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, +0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, +0xfc00, 0xfc00 +}; + +static cmsUInt8Number Shift[512] = { +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x17, +0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0d, 0x0d, 0x0d, +0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, +0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0d, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, +0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, +0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, +0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x0d +}; + +cmsFloat32Number _cmsHalf2Float(cmsUInt16Number h) +{ + union { + cmsFloat32Number flt; + cmsUInt32Number num; + } out; + + int n = h >> 10; + + out.num = Mantissa[ (h & 0x3ff) + Offset[ n ] ] + Exponent[ n ]; + return out.flt; +} + +cmsUInt16Number _cmsFloat2Half(cmsFloat32Number flt) +{ + union { + cmsFloat32Number flt; + cmsUInt32Number num; + } in; + + cmsUInt32Number n, j; + + in.flt = flt; + n = in.num; + j = (n >> 23) & 0x1ff; + + return (cmsUInt16Number) ((cmsUInt32Number) Base[ j ] + (( n & 0x007fffff) >> Shift[ j ])); +} + +#endif diff --git a/jni/lcms2-2.5/src/cmsintrp.c b/jni/lcms2-2.5/src/cmsintrp.c new file mode 100644 index 00000000..ea33cc6c --- /dev/null +++ b/jni/lcms2-2.5/src/cmsintrp.c @@ -0,0 +1,1493 @@ +//--------------------------------------------------------------------------------- +// +// Little Color Management System +// Copyright (c) 1998-2012 Marti Maria Saguer +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//--------------------------------------------------------------------------------- +// + +#include "lcms2_internal.h" + +// This module incorporates several interpolation routines, for 1 to 8 channels on input and +// up to 65535 channels on output. The user may change those by using the interpolation plug-in + +// Interpolation routines by default +static cmsInterpFunction DefaultInterpolatorsFactory(cmsUInt32Number nInputChannels, cmsUInt32Number nOutputChannels, cmsUInt32Number dwFlags); + +// This is the default factory +static cmsInterpFnFactory Interpolators = DefaultInterpolatorsFactory; + + +// Main plug-in entry +cmsBool _cmsRegisterInterpPlugin(cmsPluginBase* Data) +{ + cmsPluginInterpolation* Plugin = (cmsPluginInterpolation*) Data; + + if (Data == NULL) { + + Interpolators = DefaultInterpolatorsFactory; + return TRUE; + } + + // Set replacement functions + Interpolators = Plugin ->InterpolatorsFactory; + return TRUE; +} + + +// Set the interpolation method +cmsBool _cmsSetInterpolationRoutine(cmsInterpParams* p) +{ + // Invoke factory, possibly in the Plug-in + p ->Interpolation = Interpolators(p -> nInputs, p ->nOutputs, p ->dwFlags); + + // If unsupported by the plug-in, go for the LittleCMS default. + // If happens only if an extern plug-in is being used + if (p ->Interpolation.Lerp16 == NULL) + p ->Interpolation = DefaultInterpolatorsFactory(p ->nInputs, p ->nOutputs, p ->dwFlags); + + // Check for valid interpolator (we just check one member of the union) + if (p ->Interpolation.Lerp16 == NULL) { + return FALSE; + } + return TRUE; +} + + +// This function precalculates as many parameters as possible to speed up the interpolation. +cmsInterpParams* _cmsComputeInterpParamsEx(cmsContext ContextID, + const cmsUInt32Number nSamples[], + int InputChan, int OutputChan, + const void *Table, + cmsUInt32Number dwFlags) +{ + cmsInterpParams* p; + int i; + + // Check for maximum inputs + if (InputChan > MAX_INPUT_DIMENSIONS) { + cmsSignalError(ContextID, cmsERROR_RANGE, "Too many input channels (%d channels, max=%d)", InputChan, MAX_INPUT_DIMENSIONS); + return NULL; + } + + // Creates an empty object + p = (cmsInterpParams*) _cmsMallocZero(ContextID, sizeof(cmsInterpParams)); + if (p == NULL) return NULL; + + // Keep original parameters + p -> dwFlags = dwFlags; + p -> nInputs = InputChan; + p -> nOutputs = OutputChan; + p ->Table = Table; + p ->ContextID = ContextID; + + // Fill samples per input direction and domain (which is number of nodes minus one) + for (i=0; i < InputChan; i++) { + + p -> nSamples[i] = nSamples[i]; + p -> Domain[i] = nSamples[i] - 1; + } + + // Compute factors to apply to each component to index the grid array + p -> opta[0] = p -> nOutputs; + for (i=1; i < InputChan; i++) + p ->opta[i] = p ->opta[i-1] * nSamples[InputChan-i]; + + + if (!_cmsSetInterpolationRoutine(p)) { + cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported interpolation (%d->%d channels)", InputChan, OutputChan); + _cmsFree(ContextID, p); + return NULL; + } + + // All seems ok + return p; +} + + +// This one is a wrapper on the anterior, but assuming all directions have same number of nodes +cmsInterpParams* _cmsComputeInterpParams(cmsContext ContextID, int nSamples, int InputChan, int OutputChan, const void* Table, cmsUInt32Number dwFlags) +{ + int i; + cmsUInt32Number Samples[MAX_INPUT_DIMENSIONS]; + + // Fill the auxiliar array + for (i=0; i < MAX_INPUT_DIMENSIONS; i++) + Samples[i] = nSamples; + + // Call the extended function + return _cmsComputeInterpParamsEx(ContextID, Samples, InputChan, OutputChan, Table, dwFlags); +} + + +// Free all associated memory +void _cmsFreeInterpParams(cmsInterpParams* p) +{ + if (p != NULL) _cmsFree(p ->ContextID, p); +} + + +// Inline fixed point interpolation +cmsINLINE cmsUInt16Number LinearInterp(cmsS15Fixed16Number a, cmsS15Fixed16Number l, cmsS15Fixed16Number h) +{ + cmsUInt32Number dif = (cmsUInt32Number) (h - l) * a + 0x8000; + dif = (dif >> 16) + l; + return (cmsUInt16Number) (dif); +} + + +// Linear interpolation (Fixed-point optimized) +static +void LinLerp1D(register const cmsUInt16Number Value[], + register cmsUInt16Number Output[], + register const cmsInterpParams* p) +{ + cmsUInt16Number y1, y0; + int cell0, rest; + int val3; + const cmsUInt16Number* LutTable = (cmsUInt16Number*) p ->Table; + + // if last value... + if (Value[0] == 0xffff) { + + Output[0] = LutTable[p -> Domain[0]]; + return; + } + + val3 = p -> Domain[0] * Value[0]; + val3 = _cmsToFixedDomain(val3); // To fixed 15.16 + + cell0 = FIXED_TO_INT(val3); // Cell is 16 MSB bits + rest = FIXED_REST_TO_INT(val3); // Rest is 16 LSB bits + + y0 = LutTable[cell0]; + y1 = LutTable[cell0+1]; + + + Output[0] = LinearInterp(rest, y0, y1); +} + + +// Floating-point version of 1D interpolation +static +void LinLerp1Dfloat(const cmsFloat32Number Value[], + cmsFloat32Number Output[], + const cmsInterpParams* p) +{ + cmsFloat32Number y1, y0; + cmsFloat32Number val2, rest; + int cell0, cell1; + const cmsFloat32Number* LutTable = (cmsFloat32Number*) p ->Table; + + // if last value... + if (Value[0] == 1.0) { + Output[0] = LutTable[p -> Domain[0]]; + return; + } + + val2 = p -> Domain[0] * Value[0]; + + cell0 = (int) floor(val2); + cell1 = (int) ceil(val2); + + // Rest is 16 LSB bits + rest = val2 - cell0; + + y0 = LutTable[cell0] ; + y1 = LutTable[cell1] ; + + Output[0] = y0 + (y1 - y0) * rest; +} + + + +// Eval gray LUT having only one input channel +static +void Eval1Input(register const cmsUInt16Number Input[], + register cmsUInt16Number Output[], + register const cmsInterpParams* p16) +{ + cmsS15Fixed16Number fk; + cmsS15Fixed16Number k0, k1, rk, K0, K1; + int v; + cmsUInt32Number OutChan; + const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table; + + v = Input[0] * p16 -> Domain[0]; + fk = _cmsToFixedDomain(v); + + k0 = FIXED_TO_INT(fk); + rk = (cmsUInt16Number) FIXED_REST_TO_INT(fk); + + k1 = k0 + (Input[0] != 0xFFFFU ? 1 : 0); + + K0 = p16 -> opta[0] * k0; + K1 = p16 -> opta[0] * k1; + + for (OutChan=0; OutChan < p16->nOutputs; OutChan++) { + + Output[OutChan] = LinearInterp(rk, LutTable[K0+OutChan], LutTable[K1+OutChan]); + } +} + + + +// Eval gray LUT having only one input channel +static +void Eval1InputFloat(const cmsFloat32Number Value[], + cmsFloat32Number Output[], + const cmsInterpParams* p) +{ + cmsFloat32Number y1, y0; + cmsFloat32Number val2, rest; + int cell0, cell1; + cmsUInt32Number OutChan; + const cmsFloat32Number* LutTable = (cmsFloat32Number*) p ->Table; + + // if last value... + if (Value[0] == 1.0) { + Output[0] = LutTable[p -> Domain[0]]; + return; + } + + val2 = p -> Domain[0] * Value[0]; + + cell0 = (int) floor(val2); + cell1 = (int) ceil(val2); + + // Rest is 16 LSB bits + rest = val2 - cell0; + + cell0 *= p -> opta[0]; + cell1 *= p -> opta[0]; + + for (OutChan=0; OutChan < p->nOutputs; OutChan++) { + + y0 = LutTable[cell0 + OutChan] ; + y1 = LutTable[cell1 + OutChan] ; + + Output[OutChan] = y0 + (y1 - y0) * rest; + } +} + +// Bilinear interpolation (16 bits) - cmsFloat32Number version +static +void BilinearInterpFloat(const cmsFloat32Number Input[], + cmsFloat32Number Output[], + const cmsInterpParams* p) + +{ +# define LERP(a,l,h) (cmsFloat32Number) ((l)+(((h)-(l))*(a))) +# define DENS(i,j) (LutTable[(i)+(j)+OutChan]) + + const cmsFloat32Number* LutTable = (cmsFloat32Number*) p ->Table; + cmsFloat32Number px, py; + int x0, y0, + X0, Y0, X1, Y1; + int TotalOut, OutChan; + cmsFloat32Number fx, fy, + d00, d01, d10, d11, + dx0, dx1, + dxy; + + TotalOut = p -> nOutputs; + px = Input[0] * p->Domain[0]; + py = Input[1] * p->Domain[1]; + + x0 = (int) _cmsQuickFloor(px); fx = px - (cmsFloat32Number) x0; + y0 = (int) _cmsQuickFloor(py); fy = py - (cmsFloat32Number) y0; + + X0 = p -> opta[1] * x0; + X1 = X0 + (Input[0] >= 1.0 ? 0 : p->opta[1]); + + Y0 = p -> opta[0] * y0; + Y1 = Y0 + (Input[1] >= 1.0 ? 0 : p->opta[0]); + + for (OutChan = 0; OutChan < TotalOut; OutChan++) { + + d00 = DENS(X0, Y0); + d01 = DENS(X0, Y1); + d10 = DENS(X1, Y0); + d11 = DENS(X1, Y1); + + dx0 = LERP(fx, d00, d10); + dx1 = LERP(fx, d01, d11); + + dxy = LERP(fy, dx0, dx1); + + Output[OutChan] = dxy; + } + + +# undef LERP +# undef DENS +} + +// Bilinear interpolation (16 bits) - optimized version +static +void BilinearInterp16(register const cmsUInt16Number Input[], + register cmsUInt16Number Output[], + register const cmsInterpParams* p) + +{ +#define DENS(i,j) (LutTable[(i)+(j)+OutChan]) +#define LERP(a,l,h) (cmsUInt16Number) (l + ROUND_FIXED_TO_INT(((h-l)*a))) + + const cmsUInt16Number* LutTable = (cmsUInt16Number*) p ->Table; + int OutChan, TotalOut; + cmsS15Fixed16Number fx, fy; + register int rx, ry; + int x0, y0; + register int X0, X1, Y0, Y1; + int d00, d01, d10, d11, + dx0, dx1, + dxy; + + TotalOut = p -> nOutputs; + + fx = _cmsToFixedDomain((int) Input[0] * p -> Domain[0]); + x0 = FIXED_TO_INT(fx); + rx = FIXED_REST_TO_INT(fx); // Rest in 0..1.0 domain + + + fy = _cmsToFixedDomain((int) Input[1] * p -> Domain[1]); + y0 = FIXED_TO_INT(fy); + ry = FIXED_REST_TO_INT(fy); + + + X0 = p -> opta[1] * x0; + X1 = X0 + (Input[0] == 0xFFFFU ? 0 : p->opta[1]); + + Y0 = p -> opta[0] * y0; + Y1 = Y0 + (Input[1] == 0xFFFFU ? 0 : p->opta[0]); + + for (OutChan = 0; OutChan < TotalOut; OutChan++) { + + d00 = DENS(X0, Y0); + d01 = DENS(X0, Y1); + d10 = DENS(X1, Y0); + d11 = DENS(X1, Y1); + + dx0 = LERP(rx, d00, d10); + dx1 = LERP(rx, d01, d11); + + dxy = LERP(ry, dx0, dx1); + + Output[OutChan] = (cmsUInt16Number) dxy; + } + + +# undef LERP +# undef DENS +} + + +// Trilinear interpolation (16 bits) - cmsFloat32Number version +static +void TrilinearInterpFloat(const cmsFloat32Number Input[], + cmsFloat32Number Output[], + const cmsInterpParams* p) + +{ +# define LERP(a,l,h) (cmsFloat32Number) ((l)+(((h)-(l))*(a))) +# define DENS(i,j,k) (LutTable[(i)+(j)+(k)+OutChan]) + + const cmsFloat32Number* LutTable = (cmsFloat32Number*) p ->Table; + cmsFloat32Number px, py, pz; + int x0, y0, z0, + X0, Y0, Z0, X1, Y1, Z1; + int TotalOut, OutChan; + cmsFloat32Number fx, fy, fz, + d000, d001, d010, d011, + d100, d101, d110, d111, + dx00, dx01, dx10, dx11, + dxy0, dxy1, dxyz; + + TotalOut = p -> nOutputs; + + // We need some clipping here + px = Input[0]; + py = Input[1]; + pz = Input[2]; + + if (px < 0) px = 0; + if (px > 1) px = 1; + if (py < 0) py = 0; + if (py > 1) py = 1; + if (pz < 0) pz = 0; + if (pz > 1) pz = 1; + + px *= p->Domain[0]; + py *= p->Domain[1]; + pz *= p->Domain[2]; + + x0 = (int) _cmsQuickFloor(px); fx = px - (cmsFloat32Number) x0; + y0 = (int) _cmsQuickFloor(py); fy = py - (cmsFloat32Number) y0; + z0 = (int) _cmsQuickFloor(pz); fz = pz - (cmsFloat32Number) z0; + + X0 = p -> opta[2] * x0; + X1 = X0 + (Input[0] >= 1.0 ? 0 : p->opta[2]); + + Y0 = p -> opta[1] * y0; + Y1 = Y0 + (Input[1] >= 1.0 ? 0 : p->opta[1]); + + Z0 = p -> opta[0] * z0; + Z1 = Z0 + (Input[2] >= 1.0 ? 0 : p->opta[0]); + + for (OutChan = 0; OutChan < TotalOut; OutChan++) { + + d000 = DENS(X0, Y0, Z0); + d001 = DENS(X0, Y0, Z1); + d010 = DENS(X0, Y1, Z0); + d011 = DENS(X0, Y1, Z1); + + d100 = DENS(X1, Y0, Z0); + d101 = DENS(X1, Y0, Z1); + d110 = DENS(X1, Y1, Z0); + d111 = DENS(X1, Y1, Z1); + + + dx00 = LERP(fx, d000, d100); + dx01 = LERP(fx, d001, d101); + dx10 = LERP(fx, d010, d110); + dx11 = LERP(fx, d011, d111); + + dxy0 = LERP(fy, dx00, dx10); + dxy1 = LERP(fy, dx01, dx11); + + dxyz = LERP(fz, dxy0, dxy1); + + Output[OutChan] = dxyz; + } + + +# undef LERP +# undef DENS +} + +// Trilinear interpolation (16 bits) - optimized version +static +void TrilinearInterp16(register const cmsUInt16Number Input[], + register cmsUInt16Number Output[], + register const cmsInterpParams* p) + +{ +#define DENS(i,j,k) (LutTable[(i)+(j)+(k)+OutChan]) +#define LERP(a,l,h) (cmsUInt16Number) (l + ROUND_FIXED_TO_INT(((h-l)*a))) + + const cmsUInt16Number* LutTable = (cmsUInt16Number*) p ->Table; + int OutChan, TotalOut; + cmsS15Fixed16Number fx, fy, fz; + register int rx, ry, rz; + int x0, y0, z0; + register int X0, X1, Y0, Y1, Z0, Z1; + int d000, d001, d010, d011, + d100, d101, d110, d111, + dx00, dx01, dx10, dx11, + dxy0, dxy1, dxyz; + + TotalOut = p -> nOutputs; + + fx = _cmsToFixedDomain((int) Input[0] * p -> Domain[0]); + x0 = FIXED_TO_INT(fx); + rx = FIXED_REST_TO_INT(fx); // Rest in 0..1.0 domain + + + fy = _cmsToFixedDomain((int) Input[1] * p -> Domain[1]); + y0 = FIXED_TO_INT(fy); + ry = FIXED_REST_TO_INT(fy); + + fz = _cmsToFixedDomain((int) Input[2] * p -> Domain[2]); + z0 = FIXED_TO_INT(fz); + rz = FIXED_REST_TO_INT(fz); + + + X0 = p -> opta[2] * x0; + X1 = X0 + (Input[0] == 0xFFFFU ? 0 : p->opta[2]); + + Y0 = p -> opta[1] * y0; + Y1 = Y0 + (Input[1] == 0xFFFFU ? 0 : p->opta[1]); + + Z0 = p -> opta[0] * z0; + Z1 = Z0 + (Input[2] == 0xFFFFU ? 0 : p->opta[0]); + + for (OutChan = 0; OutChan < TotalOut; OutChan++) { + + d000 = DENS(X0, Y0, Z0); + d001 = DENS(X0, Y0, Z1); + d010 = DENS(X0, Y1, Z0); + d011 = DENS(X0, Y1, Z1); + + d100 = DENS(X1, Y0, Z0); + d101 = DENS(X1, Y0, Z1); + d110 = DENS(X1, Y1, Z0); + d111 = DENS(X1, Y1, Z1); + + + dx00 = LERP(rx, d000, d100); + dx01 = LERP(rx, d001, d101); + dx10 = LERP(rx, d010, d110); + dx11 = LERP(rx, d011, d111); + + dxy0 = LERP(ry, dx00, dx10); + dxy1 = LERP(ry, dx01, dx11); + + dxyz = LERP(rz, dxy0, dxy1); + + Output[OutChan] = (cmsUInt16Number) dxyz; + } + + +# undef LERP +# undef DENS +} + + +// Tetrahedral interpolation, using Sakamoto algorithm. +#define DENS(i,j,k) (LutTable[(i)+(j)+(k)+OutChan]) +static +void TetrahedralInterpFloat(const cmsFloat32Number Input[], + cmsFloat32Number Output[], + const cmsInterpParams* p) +{ + const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table; + cmsFloat32Number px, py, pz; + int x0, y0, z0, + X0, Y0, Z0, X1, Y1, Z1; + cmsFloat32Number rx, ry, rz; + cmsFloat32Number c0, c1=0, c2=0, c3=0; + int OutChan, TotalOut; + + TotalOut = p -> nOutputs; + + // We need some clipping here + px = Input[0]; + py = Input[1]; + pz = Input[2]; + + if (px < 0) px = 0; + if (px > 1) px = 1; + if (py < 0) py = 0; + if (py > 1) py = 1; + if (pz < 0) pz = 0; + if (pz > 1) pz = 1; + + px *= p->Domain[0]; + py *= p->Domain[1]; + pz *= p->Domain[2]; + + x0 = (int) _cmsQuickFloor(px); rx = (px - (cmsFloat32Number) x0); + y0 = (int) _cmsQuickFloor(py); ry = (py - (cmsFloat32Number) y0); + z0 = (int) _cmsQuickFloor(pz); rz = (pz - (cmsFloat32Number) z0); + + + X0 = p -> opta[2] * x0; + X1 = X0 + (Input[0] >= 1.0 ? 0 : p->opta[2]); + + Y0 = p -> opta[1] * y0; + Y1 = Y0 + (Input[1] >= 1.0 ? 0 : p->opta[1]); + + Z0 = p -> opta[0] * z0; + Z1 = Z0 + (Input[2] >= 1.0 ? 0 : p->opta[0]); + + for (OutChan=0; OutChan < TotalOut; OutChan++) { + + // These are the 6 Tetrahedral + + c0 = DENS(X0, Y0, Z0); + + if (rx >= ry && ry >= rz) { + + c1 = DENS(X1, Y0, Z0) - c0; + c2 = DENS(X1, Y1, Z0) - DENS(X1, Y0, Z0); + c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0); + + } + else + if (rx >= rz && rz >= ry) { + + c1 = DENS(X1, Y0, Z0) - c0; + c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1); + c3 = DENS(X1, Y0, Z1) - DENS(X1, Y0, Z0); + + } + else + if (rz >= rx && rx >= ry) { + + c1 = DENS(X1, Y0, Z1) - DENS(X0, Y0, Z1); + c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1); + c3 = DENS(X0, Y0, Z1) - c0; + + } + else + if (ry >= rx && rx >= rz) { + + c1 = DENS(X1, Y1, Z0) - DENS(X0, Y1, Z0); + c2 = DENS(X0, Y1, Z0) - c0; + c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0); + + } + else + if (ry >= rz && rz >= rx) { + + c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1); + c2 = DENS(X0, Y1, Z0) - c0; + c3 = DENS(X0, Y1, Z1) - DENS(X0, Y1, Z0); + + } + else + if (rz >= ry && ry >= rx) { + + c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1); + c2 = DENS(X0, Y1, Z1) - DENS(X0, Y0, Z1); + c3 = DENS(X0, Y0, Z1) - c0; + + } + else { + c1 = c2 = c3 = 0; + } + + Output[OutChan] = c0 + c1 * rx + c2 * ry + c3 * rz; + } + +} + +#undef DENS + + + + +static +void TetrahedralInterp16(register const cmsUInt16Number Input[], + register cmsUInt16Number Output[], + register const cmsInterpParams* p) +{ + const cmsUInt16Number* LutTable = (cmsUInt16Number*) p -> Table; + cmsS15Fixed16Number fx, fy, fz; + cmsS15Fixed16Number rx, ry, rz; + int x0, y0, z0; + cmsS15Fixed16Number c0, c1, c2, c3, Rest; + cmsS15Fixed16Number X0, X1, Y0, Y1, Z0, Z1; + cmsUInt32Number TotalOut = p -> nOutputs; + + fx = _cmsToFixedDomain((int) Input[0] * p -> Domain[0]); + fy = _cmsToFixedDomain((int) Input[1] * p -> Domain[1]); + fz = _cmsToFixedDomain((int) Input[2] * p -> Domain[2]); + + x0 = FIXED_TO_INT(fx); + y0 = FIXED_TO_INT(fy); + z0 = FIXED_TO_INT(fz); + + rx = FIXED_REST_TO_INT(fx); + ry = FIXED_REST_TO_INT(fy); + rz = FIXED_REST_TO_INT(fz); + + X0 = p -> opta[2] * x0; + X1 = (Input[0] == 0xFFFFU ? 0 : p->opta[2]); + + Y0 = p -> opta[1] * y0; + Y1 = (Input[1] == 0xFFFFU ? 0 : p->opta[1]); + + Z0 = p -> opta[0] * z0; + Z1 = (Input[2] == 0xFFFFU ? 0 : p->opta[0]); + + LutTable = &LutTable[X0+Y0+Z0]; + + // Output should be computed as x = ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest)) + // which expands as: x = (Rest + ((Rest+0x7fff)/0xFFFF) + 0x8000)>>16 + // This can be replaced by: t = Rest+0x8001, x = (t + (t>>16))>>16 + // at the cost of being off by one at 7fff and 17ffe. + + if (rx >= ry) { + if (ry >= rz) { + Y1 += X1; + Z1 += Y1; + for (; TotalOut; TotalOut--) { + c1 = LutTable[X1]; + c2 = LutTable[Y1]; + c3 = LutTable[Z1]; + c0 = *LutTable++; + c3 -= c2; + c2 -= c1; + c1 -= c0; + Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001; + *Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16); + } + } else if (rz >= rx) { + X1 += Z1; + Y1 += X1; + for (; TotalOut; TotalOut--) { + c1 = LutTable[X1]; + c2 = LutTable[Y1]; + c3 = LutTable[Z1]; + c0 = *LutTable++; + c2 -= c1; + c1 -= c3; + c3 -= c0; + Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001; + *Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16); + } + } else { + Z1 += X1; + Y1 += Z1; + for (; TotalOut; TotalOut--) { + c1 = LutTable[X1]; + c2 = LutTable[Y1]; + c3 = LutTable[Z1]; + c0 = *LutTable++; + c2 -= c3; + c3 -= c1; + c1 -= c0; + Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001; + *Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16); + } + } + } else { + if (rx >= rz) { + X1 += Y1; + Z1 += X1; + for (; TotalOut; TotalOut--) { + c1 = LutTable[X1]; + c2 = LutTable[Y1]; + c3 = LutTable[Z1]; + c0 = *LutTable++; + c3 -= c1; + c1 -= c2; + c2 -= c0; + Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001; + *Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16); + } + } else if (ry >= rz) { + Z1 += Y1; + X1 += Z1; + for (; TotalOut; TotalOut--) { + c1 = LutTable[X1]; + c2 = LutTable[Y1]; + c3 = LutTable[Z1]; + c0 = *LutTable++; + c1 -= c3; + c3 -= c2; + c2 -= c0; + Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001; + *Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16); + } + } else { + Y1 += Z1; + X1 += Y1; + for (; TotalOut; TotalOut--) { + c1 = LutTable[X1]; + c2 = LutTable[Y1]; + c3 = LutTable[Z1]; + c0 = *LutTable++; + c1 -= c2; + c2 -= c3; + c3 -= c0; + Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001; + *Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16); + } + } + } +} + + +#define DENS(i,j,k) (LutTable[(i)+(j)+(k)+OutChan]) +static +void Eval4Inputs(register const cmsUInt16Number Input[], + register cmsUInt16Number Output[], + register const cmsInterpParams* p16) +{ + const cmsUInt16Number* LutTable; + cmsS15Fixed16Number fk; + cmsS15Fixed16Number k0, rk; + int K0, K1; + cmsS15Fixed16Number fx, fy, fz; + cmsS15Fixed16Number rx, ry, rz; + int x0, y0, z0; + cmsS15Fixed16Number X0, X1, Y0, Y1, Z0, Z1; + cmsUInt32Number i; + cmsS15Fixed16Number c0, c1, c2, c3, Rest; + cmsUInt32Number OutChan; + cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS]; + + + fk = _cmsToFixedDomain((int) Input[0] * p16 -> Domain[0]); + fx = _cmsToFixedDomain((int) Input[1] * p16 -> Domain[1]); + fy = _cmsToFixedDomain((int) Input[2] * p16 -> Domain[2]); + fz = _cmsToFixedDomain((int) Input[3] * p16 -> Domain[3]); + + k0 = FIXED_TO_INT(fk); + x0 = FIXED_TO_INT(fx); + y0 = FIXED_TO_INT(fy); + z0 = FIXED_TO_INT(fz); + + rk = FIXED_REST_TO_INT(fk); + rx = FIXED_REST_TO_INT(fx); + ry = FIXED_REST_TO_INT(fy); + rz = FIXED_REST_TO_INT(fz); + + K0 = p16 -> opta[3] * k0; + K1 = K0 + (Input[0] == 0xFFFFU ? 0 : p16->opta[3]); + + X0 = p16 -> opta[2] * x0; + X1 = X0 + (Input[1] == 0xFFFFU ? 0 : p16->opta[2]); + + Y0 = p16 -> opta[1] * y0; + Y1 = Y0 + (Input[2] == 0xFFFFU ? 0 : p16->opta[1]); + + Z0 = p16 -> opta[0] * z0; + Z1 = Z0 + (Input[3] == 0xFFFFU ? 0 : p16->opta[0]); + + LutTable = (cmsUInt16Number*) p16 -> Table; + LutTable += K0; + + for (OutChan=0; OutChan < p16 -> nOutputs; OutChan++) { + + c0 = DENS(X0, Y0, Z0); + + if (rx >= ry && ry >= rz) { + + c1 = DENS(X1, Y0, Z0) - c0; + c2 = DENS(X1, Y1, Z0) - DENS(X1, Y0, Z0); + c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0); + + } + else + if (rx >= rz && rz >= ry) { + + c1 = DENS(X1, Y0, Z0) - c0; + c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1); + c3 = DENS(X1, Y0, Z1) - DENS(X1, Y0, Z0); + + } + else + if (rz >= rx && rx >= ry) { + + c1 = DENS(X1, Y0, Z1) - DENS(X0, Y0, Z1); + c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1); + c3 = DENS(X0, Y0, Z1) - c0; + + } + else + if (ry >= rx && rx >= rz) { + + c1 = DENS(X1, Y1, Z0) - DENS(X0, Y1, Z0); + c2 = DENS(X0, Y1, Z0) - c0; + c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0); + + } + else + if (ry >= rz && rz >= rx) { + + c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1); + c2 = DENS(X0, Y1, Z0) - c0; + c3 = DENS(X0, Y1, Z1) - DENS(X0, Y1, Z0); + + } + else + if (rz >= ry && ry >= rx) { + + c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1); + c2 = DENS(X0, Y1, Z1) - DENS(X0, Y0, Z1); + c3 = DENS(X0, Y0, Z1) - c0; + + } + else { + c1 = c2 = c3 = 0; + } + + Rest = c1 * rx + c2 * ry + c3 * rz; + + Tmp1[OutChan] = (cmsUInt16Number) c0 + ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest)); + } + + + LutTable = (cmsUInt16Number*) p16 -> Table; + LutTable += K1; + + for (OutChan=0; OutChan < p16 -> nOutputs; OutChan++) { + + c0 = DENS(X0, Y0, Z0); + + if (rx >= ry && ry >= rz) { + + c1 = DENS(X1, Y0, Z0) - c0; + c2 = DENS(X1, Y1, Z0) - DENS(X1, Y0, Z0); + c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0); + + } + else + if (rx >= rz && rz >= ry) { + + c1 = DENS(X1, Y0, Z0) - c0; + c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1); + c3 = DENS(X1, Y0, Z1) - DENS(X1, Y0, Z0); + + } + else + if (rz >= rx && rx >= ry) { + + c1 = DENS(X1, Y0, Z1) - DENS(X0, Y0, Z1); + c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1); + c3 = DENS(X0, Y0, Z1) - c0; + + } + else + if (ry >= rx && rx >= rz) { + + c1 = DENS(X1, Y1, Z0) - DENS(X0, Y1, Z0); + c2 = DENS(X0, Y1, Z0) - c0; + c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0); + + } + else + if (ry >= rz && rz >= rx) { + + c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1); + c2 = DENS(X0, Y1, Z0) - c0; + c3 = DENS(X0, Y1, Z1) - DENS(X0, Y1, Z0); + + } + else + if (rz >= ry && ry >= rx) { + + c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1); + c2 = DENS(X0, Y1, Z1) - DENS(X0, Y0, Z1); + c3 = DENS(X0, Y0, Z1) - c0; + + } + else { + c1 = c2 = c3 = 0; + } + + Rest = c1 * rx + c2 * ry + c3 * rz; + + Tmp2[OutChan] = (cmsUInt16Number) c0 + ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest)); + } + + + + for (i=0; i < p16 -> nOutputs; i++) { + Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]); + } +} +#undef DENS + + +// For more that 3 inputs (i.e., CMYK) +// evaluate two 3-dimensional interpolations and then linearly interpolate between them. + + +static +void Eval4InputsFloat(const cmsFloat32Number Input[], + cmsFloat32Number Output[], + const cmsInterpParams* p) +{ + const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table; + cmsFloat32Number rest; + cmsFloat32Number pk; + int k0, K0, K1; + const cmsFloat32Number* T; + cmsUInt32Number i; + cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS]; + cmsInterpParams p1; + + + pk = Input[0] * p->Domain[0]; + k0 = _cmsQuickFloor(pk); + rest = pk - (cmsFloat32Number) k0; + + K0 = p -> opta[3] * k0; + K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[3]); + + p1 = *p; + memmove(&p1.Domain[0], &p ->Domain[1], 3*sizeof(cmsUInt32Number)); + + T = LutTable + K0; + p1.Table = T; + + TetrahedralInterpFloat(Input + 1, Tmp1, &p1); + + T = LutTable + K1; + p1.Table = T; + TetrahedralInterpFloat(Input + 1, Tmp2, &p1); + + for (i=0; i < p -> nOutputs; i++) + { + cmsFloat32Number y0 = Tmp1[i]; + cmsFloat32Number y1 = Tmp2[i]; + + Output[i] = y0 + (y1 - y0) * rest; + } +} + + +static +void Eval5Inputs(register const cmsUInt16Number Input[], + register cmsUInt16Number Output[], + + register const cmsInterpParams* p16) +{ + const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table; + cmsS15Fixed16Number fk; + cmsS15Fixed16Number k0, rk; + int K0, K1; + const cmsUInt16Number* T; + cmsUInt32Number i; + cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS]; + cmsInterpParams p1; + + + fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]); + k0 = FIXED_TO_INT(fk); + rk = FIXED_REST_TO_INT(fk); + + K0 = p16 -> opta[4] * k0; + K1 = p16 -> opta[4] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0)); + + p1 = *p16; + memmove(&p1.Domain[0], &p16 ->Domain[1], 4*sizeof(cmsUInt32Number)); + + T = LutTable + K0; + p1.Table = T; + + Eval4Inputs(Input + 1, Tmp1, &p1); + + T = LutTable + K1; + p1.Table = T; + + Eval4Inputs(Input + 1, Tmp2, &p1); + + for (i=0; i < p16 -> nOutputs; i++) { + + Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]); + } + +} + + +static +void Eval5InputsFloat(const cmsFloat32Number Input[], + cmsFloat32Number Output[], + const cmsInterpParams* p) +{ + const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table; + cmsFloat32Number rest; + cmsFloat32Number pk; + int k0, K0, K1; + const cmsFloat32Number* T; + cmsUInt32Number i; + cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS]; + cmsInterpParams p1; + + pk = Input[0] * p->Domain[0]; + k0 = _cmsQuickFloor(pk); + rest = pk - (cmsFloat32Number) k0; + + K0 = p -> opta[4] * k0; + K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[4]); + + p1 = *p; + memmove(&p1.Domain[0], &p ->Domain[1], 4*sizeof(cmsUInt32Number)); + + T = LutTable + K0; + p1.Table = T; + + Eval4InputsFloat(Input + 1, Tmp1, &p1); + + T = LutTable + K1; + p1.Table = T; + + Eval4InputsFloat(Input + 1, Tmp2, &p1); + + for (i=0; i < p -> nOutputs; i++) { + + cmsFloat32Number y0 = Tmp1[i]; + cmsFloat32Number y1 = Tmp2[i]; + + Output[i] = y0 + (y1 - y0) * rest; + } +} + + + +static +void Eval6Inputs(register const cmsUInt16Number Input[], + register cmsUInt16Number Output[], + register const cmsInterpParams* p16) +{ + const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table; + cmsS15Fixed16Number fk; + cmsS15Fixed16Number k0, rk; + int K0, K1; + const cmsUInt16Number* T; + cmsUInt32Number i; + cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS]; + cmsInterpParams p1; + + fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]); + k0 = FIXED_TO_INT(fk); + rk = FIXED_REST_TO_INT(fk); + + K0 = p16 -> opta[5] * k0; + K1 = p16 -> opta[5] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0)); + + p1 = *p16; + memmove(&p1.Domain[0], &p16 ->Domain[1], 5*sizeof(cmsUInt32Number)); + + T = LutTable + K0; + p1.Table = T; + + Eval5Inputs(Input + 1, Tmp1, &p1); + + T = LutTable + K1; + p1.Table = T; + + Eval5Inputs(Input + 1, Tmp2, &p1); + + for (i=0; i < p16 -> nOutputs; i++) { + + Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]); + } + +} + + +static +void Eval6InputsFloat(const cmsFloat32Number Input[], + cmsFloat32Number Output[], + const cmsInterpParams* p) +{ + const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table; + cmsFloat32Number rest; + cmsFloat32Number pk; + int k0, K0, K1; + const cmsFloat32Number* T; + cmsUInt32Number i; + cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS]; + cmsInterpParams p1; + + pk = Input[0] * p->Domain[0]; + k0 = _cmsQuickFloor(pk); + rest = pk - (cmsFloat32Number) k0; + + K0 = p -> opta[5] * k0; + K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[5]); + + p1 = *p; + memmove(&p1.Domain[0], &p ->Domain[1], 5*sizeof(cmsUInt32Number)); + + T = LutTable + K0; + p1.Table = T; + + Eval5InputsFloat(Input + 1, Tmp1, &p1); + + T = LutTable + K1; + p1.Table = T; + + Eval5InputsFloat(Input + 1, Tmp2, &p1); + + for (i=0; i < p -> nOutputs; i++) { + + cmsFloat32Number y0 = Tmp1[i]; + cmsFloat32Number y1 = Tmp2[i]; + + Output[i] = y0 + (y1 - y0) * rest; + } +} + + +static +void Eval7Inputs(register const cmsUInt16Number Input[], + register cmsUInt16Number Output[], + register const cmsInterpParams* p16) +{ + const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table; + cmsS15Fixed16Number fk; + cmsS15Fixed16Number k0, rk; + int K0, K1; + const cmsUInt16Number* T; + cmsUInt32Number i; + cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS]; + cmsInterpParams p1; + + + fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]); + k0 = FIXED_TO_INT(fk); + rk = FIXED_REST_TO_INT(fk); + + K0 = p16 -> opta[6] * k0; + K1 = p16 -> opta[6] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0)); + + p1 = *p16; + memmove(&p1.Domain[0], &p16 ->Domain[1], 6*sizeof(cmsUInt32Number)); + + T = LutTable + K0; + p1.Table = T; + + Eval6Inputs(Input + 1, Tmp1, &p1); + + T = LutTable + K1; + p1.Table = T; + + Eval6Inputs(Input + 1, Tmp2, &p1); + + for (i=0; i < p16 -> nOutputs; i++) { + Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]); + } +} + + +static +void Eval7InputsFloat(const cmsFloat32Number Input[], + cmsFloat32Number Output[], + const cmsInterpParams* p) +{ + const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table; + cmsFloat32Number rest; + cmsFloat32Number pk; + int k0, K0, K1; + const cmsFloat32Number* T; + cmsUInt32Number i; + cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS]; + cmsInterpParams p1; + + pk = Input[0] * p->Domain[0]; + k0 = _cmsQuickFloor(pk); + rest = pk - (cmsFloat32Number) k0; + + K0 = p -> opta[6] * k0; + K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[6]); + + p1 = *p; + memmove(&p1.Domain[0], &p ->Domain[1], 6*sizeof(cmsUInt32Number)); + + T = LutTable + K0; + p1.Table = T; + + Eval6InputsFloat(Input + 1, Tmp1, &p1); + + T = LutTable + K1; + p1.Table = T; + + Eval6InputsFloat(Input + 1, Tmp2, &p1); + + + for (i=0; i < p -> nOutputs; i++) { + + cmsFloat32Number y0 = Tmp1[i]; + cmsFloat32Number y1 = Tmp2[i]; + + Output[i] = y0 + (y1 - y0) * rest; + + } +} + +static +void Eval8Inputs(register const cmsUInt16Number Input[], + register cmsUInt16Number Output[], + register const cmsInterpParams* p16) +{ + const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table; + cmsS15Fixed16Number fk; + cmsS15Fixed16Number k0, rk; + int K0, K1; + const cmsUInt16Number* T; + cmsUInt32Number i; + cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS]; + cmsInterpParams p1; + + fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]); + k0 = FIXED_TO_INT(fk); + rk = FIXED_REST_TO_INT(fk); + + K0 = p16 -> opta[7] * k0; + K1 = p16 -> opta[7] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0)); + + p1 = *p16; + memmove(&p1.Domain[0], &p16 ->Domain[1], 7*sizeof(cmsUInt32Number)); + + T = LutTable + K0; + p1.Table = T; + + Eval7Inputs(Input + 1, Tmp1, &p1); + + T = LutTable + K1; + p1.Table = T; + Eval7Inputs(Input + 1, Tmp2, &p1); + + for (i=0; i < p16 -> nOutputs; i++) { + Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]); + } +} + + + +static +void Eval8InputsFloat(const cmsFloat32Number Input[], + cmsFloat32Number Output[], + const cmsInterpParams* p) +{ + const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table; + cmsFloat32Number rest; + cmsFloat32Number pk; + int k0, K0, K1; + const cmsFloat32Number* T; + cmsUInt32Number i; + cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS]; + cmsInterpParams p1; + + pk = Input[0] * p->Domain[0]; + k0 = _cmsQuickFloor(pk); + rest = pk - (cmsFloat32Number) k0; + + K0 = p -> opta[7] * k0; + K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[7]); + + p1 = *p; + memmove(&p1.Domain[0], &p ->Domain[1], 7*sizeof(cmsUInt32Number)); + + T = LutTable + K0; + p1.Table = T; + + Eval7InputsFloat(Input + 1, Tmp1, &p1); + + T = LutTable + K1; + p1.Table = T; + + Eval7InputsFloat(Input + 1, Tmp2, &p1); + + + for (i=0; i < p -> nOutputs; i++) { + + cmsFloat32Number y0 = Tmp1[i]; + cmsFloat32Number y1 = Tmp2[i]; + + Output[i] = y0 + (y1 - y0) * rest; + } +} + +// The default factory +static +cmsInterpFunction DefaultInterpolatorsFactory(cmsUInt32Number nInputChannels, cmsUInt32Number nOutputChannels, cmsUInt32Number dwFlags) +{ + + cmsInterpFunction Interpolation; + cmsBool IsFloat = (dwFlags & CMS_LERP_FLAGS_FLOAT); + cmsBool IsTrilinear = (dwFlags & CMS_LERP_FLAGS_TRILINEAR); + + memset(&Interpolation, 0, sizeof(Interpolation)); + + // Safety check + if (nInputChannels >= 4 && nOutputChannels >= MAX_STAGE_CHANNELS) + return Interpolation; + + switch (nInputChannels) { + + case 1: // Gray LUT / linear + + if (nOutputChannels == 1) { + + if (IsFloat) + Interpolation.LerpFloat = LinLerp1Dfloat; + else + Interpolation.Lerp16 = LinLerp1D; + + } + else { + + if (IsFloat) + Interpolation.LerpFloat = Eval1InputFloat; + else + Interpolation.Lerp16 = Eval1Input; + } + break; + + case 2: // Duotone + if (IsFloat) + Interpolation.LerpFloat = BilinearInterpFloat; + else + Interpolation.Lerp16 = BilinearInterp16; + break; + + case 3: // RGB et al + + if (IsTrilinear) { + + if (IsFloat) + Interpolation.LerpFloat = TrilinearInterpFloat; + else + Interpolation.Lerp16 = TrilinearInterp16; + } + else { + + if (IsFloat) + Interpolation.LerpFloat = TetrahedralInterpFloat; + else { + + Interpolation.Lerp16 = TetrahedralInterp16; + } + } + break; + + case 4: // CMYK lut + + if (IsFloat) + Interpolation.LerpFloat = Eval4InputsFloat; + else + Interpolation.Lerp16 = Eval4Inputs; + break; + + case 5: // 5 Inks + if (IsFloat) + Interpolation.LerpFloat = Eval5InputsFloat; + else + Interpolation.Lerp16 = Eval5Inputs; + break; + + case 6: // 6 Inks + if (IsFloat) + Interpolation.LerpFloat = Eval6InputsFloat; + else + Interpolation.Lerp16 = Eval6Inputs; + break; + + case 7: // 7 inks + if (IsFloat) + Interpolation.LerpFloat = Eval7InputsFloat; + else + Interpolation.Lerp16 = Eval7Inputs; + break; + + case 8: // 8 inks + if (IsFloat) + Interpolation.LerpFloat = Eval8InputsFloat; + else + Interpolation.Lerp16 = Eval8Inputs; + break; + + break; + + default: + Interpolation.Lerp16 = NULL; + } + + return Interpolation; +} diff --git a/jni/lcms2-2.5/src/cmsio0.c b/jni/lcms2-2.5/src/cmsio0.c new file mode 100644 index 00000000..b7aea729 --- /dev/null +++ b/jni/lcms2-2.5/src/cmsio0.c @@ -0,0 +1,1767 @@ +//--------------------------------------------------------------------------------- +// +// Little Color Management System +// Copyright (c) 1998-2012 Marti Maria Saguer +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//--------------------------------------------------------------------------------- +// + +#include "lcms2_internal.h" + +// Generic I/O, tag dictionary management, profile struct + +// IOhandlers are abstractions used by littleCMS to read from whatever file, stream, +// memory block or any storage. Each IOhandler provides implementations for read, +// write, seek and tell functions. LittleCMS code deals with IO across those objects. +// In this way, is easier to add support for new storage media. + +// NULL stream, for taking care of used space ------------------------------------- + +// NULL IOhandler basically does nothing but keep track on how many bytes have been +// written. This is handy when creating profiles, where the file size is needed in the +// header. Then, whole profile is serialized across NULL IOhandler and a second pass +// writes the bytes to the pertinent IOhandler. + +typedef struct { + cmsUInt32Number Pointer; // Points to current location +} FILENULL; + +static +cmsUInt32Number NULLRead(cmsIOHANDLER* iohandler, void *Buffer, cmsUInt32Number size, cmsUInt32Number count) +{ + FILENULL* ResData = (FILENULL*) iohandler ->stream; + + cmsUInt32Number len = size * count; + ResData -> Pointer += len; + return count; + + cmsUNUSED_PARAMETER(Buffer); +} + +static +cmsBool NULLSeek(cmsIOHANDLER* iohandler, cmsUInt32Number offset) +{ + FILENULL* ResData = (FILENULL*) iohandler ->stream; + + ResData ->Pointer = offset; + return TRUE; +} + +static +cmsUInt32Number NULLTell(cmsIOHANDLER* iohandler) +{ + FILENULL* ResData = (FILENULL*) iohandler ->stream; + return ResData -> Pointer; +} + +static +cmsBool NULLWrite(cmsIOHANDLER* iohandler, cmsUInt32Number size, const void *Ptr) +{ + FILENULL* ResData = (FILENULL*) iohandler ->stream; + + ResData ->Pointer += size; + if (ResData ->Pointer > iohandler->UsedSpace) + iohandler->UsedSpace = ResData ->Pointer; + + return TRUE; + + cmsUNUSED_PARAMETER(Ptr); +} + +static +cmsBool NULLClose(cmsIOHANDLER* iohandler) +{ + FILENULL* ResData = (FILENULL*) iohandler ->stream; + + _cmsFree(iohandler ->ContextID, ResData); + _cmsFree(iohandler ->ContextID, iohandler); + return TRUE; +} + +// The NULL IOhandler creator +cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromNULL(cmsContext ContextID) +{ + struct _cms_io_handler* iohandler = NULL; + FILENULL* fm = NULL; + + iohandler = (struct _cms_io_handler*) _cmsMallocZero(ContextID, sizeof(struct _cms_io_handler)); + if (iohandler == NULL) return NULL; + + fm = (FILENULL*) _cmsMallocZero(ContextID, sizeof(FILENULL)); + if (fm == NULL) goto Error; + + fm ->Pointer = 0; + + iohandler ->ContextID = ContextID; + iohandler ->stream = (void*) fm; + iohandler ->UsedSpace = 0; + iohandler ->ReportedSize = 0; + iohandler ->PhysicalFile[0] = 0; + + iohandler ->Read = NULLRead; + iohandler ->Seek = NULLSeek; + iohandler ->Close = NULLClose; + iohandler ->Tell = NULLTell; + iohandler ->Write = NULLWrite; + + return iohandler; + +Error: + if (iohandler) _cmsFree(ContextID, iohandler); + return NULL; + +} + + +// Memory-based stream -------------------------------------------------------------- + +// Those functions implements an iohandler which takes a block of memory as storage medium. + +typedef struct { + cmsUInt8Number* Block; // Points to allocated memory + cmsUInt32Number Size; // Size of allocated memory + cmsUInt32Number Pointer; // Points to current location + int FreeBlockOnClose; // As title + +} FILEMEM; + +static +cmsUInt32Number MemoryRead(struct _cms_io_handler* iohandler, void *Buffer, cmsUInt32Number size, cmsUInt32Number count) +{ + FILEMEM* ResData = (FILEMEM*) iohandler ->stream; + cmsUInt8Number* Ptr; + cmsUInt32Number len = size * count; + + if (ResData -> Pointer + len > ResData -> Size){ + + len = (ResData -> Size - ResData -> Pointer); + cmsSignalError(iohandler ->ContextID, cmsERROR_READ, "Read from memory error. Got %d bytes, block should be of %d bytes", len, count * size); + return 0; + } + + Ptr = ResData -> Block; + Ptr += ResData -> Pointer; + memmove(Buffer, Ptr, len); + ResData -> Pointer += len; + + return count; +} + +// SEEK_CUR is assumed +static +cmsBool MemorySeek(struct _cms_io_handler* iohandler, cmsUInt32Number offset) +{ + FILEMEM* ResData = (FILEMEM*) iohandler ->stream; + + if (offset > ResData ->Size) { + cmsSignalError(iohandler ->ContextID, cmsERROR_SEEK, "Too few data; probably corrupted profile"); + return FALSE; + } + + ResData ->Pointer = offset; + return TRUE; +} + +// Tell for memory +static +cmsUInt32Number MemoryTell(struct _cms_io_handler* iohandler) +{ + FILEMEM* ResData = (FILEMEM*) iohandler ->stream; + + if (ResData == NULL) return 0; + return ResData -> Pointer; +} + + +// Writes data to memory, also keeps used space for further reference. +static +cmsBool MemoryWrite(struct _cms_io_handler* iohandler, cmsUInt32Number size, const void *Ptr) +{ + FILEMEM* ResData = (FILEMEM*) iohandler ->stream; + + if (ResData == NULL) return FALSE; // Housekeeping + + // Check for available space. Clip. + if (iohandler ->UsedSpace + size > ResData->Size) { + size = ResData ->Size - iohandler ->UsedSpace; + } + + if (size == 0) return TRUE; // Write zero bytes is ok, but does nothing + + memmove(ResData ->Block + ResData ->Pointer, Ptr, size); + ResData ->Pointer += size; + iohandler->UsedSpace += size; + + if (ResData ->Pointer > iohandler->UsedSpace) + iohandler->UsedSpace = ResData ->Pointer; + + return TRUE; +} + + +static +cmsBool MemoryClose(struct _cms_io_handler* iohandler) +{ + FILEMEM* ResData = (FILEMEM*) iohandler ->stream; + + if (ResData ->FreeBlockOnClose) { + + if (ResData ->Block) _cmsFree(iohandler ->ContextID, ResData ->Block); + } + + _cmsFree(iohandler ->ContextID, ResData); + _cmsFree(iohandler ->ContextID, iohandler); + + return TRUE; +} + +// Create a iohandler for memory block. AccessMode=='r' assumes the iohandler is going to read, and makes +// a copy of the memory block for letting user to free the memory after invoking open profile. In write +// mode ("w"), Buffere points to the begin of memory block to be written. +cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromMem(cmsContext ContextID, void *Buffer, cmsUInt32Number size, const char* AccessMode) +{ + cmsIOHANDLER* iohandler = NULL; + FILEMEM* fm = NULL; + + _cmsAssert(AccessMode != NULL); + + iohandler = (cmsIOHANDLER*) _cmsMallocZero(ContextID, sizeof(cmsIOHANDLER)); + if (iohandler == NULL) return NULL; + + switch (*AccessMode) { + + case 'r': + fm = (FILEMEM*) _cmsMallocZero(ContextID, sizeof(FILEMEM)); + if (fm == NULL) goto Error; + + if (Buffer == NULL) { + cmsSignalError(ContextID, cmsERROR_READ, "Couldn't read profile from NULL pointer"); + goto Error; + } + + fm ->Block = (cmsUInt8Number*) _cmsMalloc(ContextID, size); + if (fm ->Block == NULL) { + + _cmsFree(ContextID, fm); + _cmsFree(ContextID, iohandler); + cmsSignalError(ContextID, cmsERROR_READ, "Couldn't allocate %ld bytes for profile", size); + return NULL; + } + + + memmove(fm->Block, Buffer, size); + fm ->FreeBlockOnClose = TRUE; + fm ->Size = size; + fm ->Pointer = 0; + iohandler -> ReportedSize = size; + break; + + case 'w': + fm = (FILEMEM*) _cmsMallocZero(ContextID, sizeof(FILEMEM)); + if (fm == NULL) goto Error; + + fm ->Block = (cmsUInt8Number*) Buffer; + fm ->FreeBlockOnClose = FALSE; + fm ->Size = size; + fm ->Pointer = 0; + iohandler -> ReportedSize = 0; + break; + + default: + cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown access mode '%c'", *AccessMode); + return NULL; + } + + iohandler ->ContextID = ContextID; + iohandler ->stream = (void*) fm; + iohandler ->UsedSpace = 0; + iohandler ->PhysicalFile[0] = 0; + + iohandler ->Read = MemoryRead; + iohandler ->Seek = MemorySeek; + iohandler ->Close = MemoryClose; + iohandler ->Tell = MemoryTell; + iohandler ->Write = MemoryWrite; + + return iohandler; + +Error: + if (fm) _cmsFree(ContextID, fm); + if (iohandler) _cmsFree(ContextID, iohandler); + return NULL; +} + +// File-based stream ------------------------------------------------------- + +// Read count elements of size bytes each. Return number of elements read +static +cmsUInt32Number FileRead(cmsIOHANDLER* iohandler, void *Buffer, cmsUInt32Number size, cmsUInt32Number count) +{ + cmsUInt32Number nReaded = (cmsUInt32Number) fread(Buffer, size, count, (FILE*) iohandler->stream); + + if (nReaded != count) { + cmsSignalError(iohandler ->ContextID, cmsERROR_FILE, "Read error. Got %d bytes, block should be of %d bytes", nReaded * size, count * size); + return 0; + } + + return nReaded; +} + +// Postion file pointer in the file +static +cmsBool FileSeek(cmsIOHANDLER* iohandler, cmsUInt32Number offset) +{ + if (fseek((FILE*) iohandler ->stream, (long) offset, SEEK_SET) != 0) { + + cmsSignalError(iohandler ->ContextID, cmsERROR_FILE, "Seek error; probably corrupted file"); + return FALSE; + } + + return TRUE; +} + +// Returns file pointer position +static +cmsUInt32Number FileTell(cmsIOHANDLER* iohandler) +{ + return ftell((FILE*)iohandler ->stream); +} + +// Writes data to stream, also keeps used space for further reference. Returns TRUE on success, FALSE on error +static +cmsBool FileWrite(cmsIOHANDLER* iohandler, cmsUInt32Number size, const void* Buffer) +{ + if (size == 0) return TRUE; // We allow to write 0 bytes, but nothing is written + + iohandler->UsedSpace += size; + return (fwrite(Buffer, size, 1, (FILE*) iohandler->stream) == 1); +} + +// Closes the file +static +cmsBool FileClose(cmsIOHANDLER* iohandler) +{ + if (fclose((FILE*) iohandler ->stream) != 0) return FALSE; + _cmsFree(iohandler ->ContextID, iohandler); + return TRUE; +} + +// Create a iohandler for disk based files. +cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromFile(cmsContext ContextID, const char* FileName, const char* AccessMode) +{ + cmsIOHANDLER* iohandler = NULL; + FILE* fm = NULL; + + _cmsAssert(FileName != NULL); + _cmsAssert(AccessMode != NULL); + + iohandler = (cmsIOHANDLER*) _cmsMallocZero(ContextID, sizeof(cmsIOHANDLER)); + if (iohandler == NULL) return NULL; + + switch (*AccessMode) { + + case 'r': + fm = fopen(FileName, "rb"); + if (fm == NULL) { + _cmsFree(ContextID, iohandler); + cmsSignalError(ContextID, cmsERROR_FILE, "File '%s' not found", FileName); + return NULL; + } + iohandler -> ReportedSize = cmsfilelength(fm); + break; + + case 'w': + fm = fopen(FileName, "wb"); + if (fm == NULL) { + _cmsFree(ContextID, iohandler); + cmsSignalError(ContextID, cmsERROR_FILE, "Couldn't create '%s'", FileName); + return NULL; + } + iohandler -> ReportedSize = 0; + break; + + default: + _cmsFree(ContextID, iohandler); + cmsSignalError(ContextID, cmsERROR_FILE, "Unknown access mode '%c'", *AccessMode); + return NULL; + } + + iohandler ->ContextID = ContextID; + iohandler ->stream = (void*) fm; + iohandler ->UsedSpace = 0; + + // Keep track of the original file + strncpy(iohandler -> PhysicalFile, FileName, sizeof(iohandler -> PhysicalFile)-1); + iohandler -> PhysicalFile[sizeof(iohandler -> PhysicalFile)-1] = 0; + + iohandler ->Read = FileRead; + iohandler ->Seek = FileSeek; + iohandler ->Close = FileClose; + iohandler ->Tell = FileTell; + iohandler ->Write = FileWrite; + + return iohandler; +} + +// Create a iohandler for stream based files +cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromStream(cmsContext ContextID, FILE* Stream) +{ + cmsIOHANDLER* iohandler = NULL; + + iohandler = (cmsIOHANDLER*) _cmsMallocZero(ContextID, sizeof(cmsIOHANDLER)); + if (iohandler == NULL) return NULL; + + iohandler -> ContextID = ContextID; + iohandler -> stream = (void*) Stream; + iohandler -> UsedSpace = 0; + iohandler -> ReportedSize = cmsfilelength(Stream); + iohandler -> PhysicalFile[0] = 0; + + iohandler ->Read = FileRead; + iohandler ->Seek = FileSeek; + iohandler ->Close = FileClose; + iohandler ->Tell = FileTell; + iohandler ->Write = FileWrite; + + return iohandler; +} + + + +// Close an open IO handler +cmsBool CMSEXPORT cmsCloseIOhandler(cmsIOHANDLER* io) +{ + return io -> Close(io); +} + +// ------------------------------------------------------------------------------------------------------- + +// Creates an empty structure holding all required parameters +cmsHPROFILE CMSEXPORT cmsCreateProfilePlaceholder(cmsContext ContextID) +{ + time_t now = time(NULL); + _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) _cmsMallocZero(ContextID, sizeof(_cmsICCPROFILE)); + if (Icc == NULL) return NULL; + + Icc ->ContextID = ContextID; + + // Set it to empty + Icc -> TagCount = 0; + + // Set default version + Icc ->Version = 0x02100000; + + // Set creation date/time + memmove(&Icc ->Created, gmtime(&now), sizeof(Icc ->Created)); + + // Return the handle + return (cmsHPROFILE) Icc; +} + +cmsContext CMSEXPORT cmsGetProfileContextID(cmsHPROFILE hProfile) +{ + _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; + + if (Icc == NULL) return NULL; + return Icc -> ContextID; +} + + +// Return the number of tags +cmsInt32Number CMSEXPORT cmsGetTagCount(cmsHPROFILE hProfile) +{ + _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; + if (Icc == NULL) return -1; + + return Icc->TagCount; +} + +// Return the tag signature of a given tag number +cmsTagSignature CMSEXPORT cmsGetTagSignature(cmsHPROFILE hProfile, cmsUInt32Number n) +{ + _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; + + if (n > Icc->TagCount) return (cmsTagSignature) 0; // Mark as not available + if (n >= MAX_TABLE_TAG) return (cmsTagSignature) 0; // As double check + + return Icc ->TagNames[n]; +} + + +static +int SearchOneTag(_cmsICCPROFILE* Profile, cmsTagSignature sig) +{ + cmsUInt32Number i; + + for (i=0; i < Profile -> TagCount; i++) { + + if (sig == Profile -> TagNames[i]) + return i; + } + + return -1; +} + +// Search for a specific tag in tag dictionary. Returns position or -1 if tag not found. +// If followlinks is turned on, then the position of the linked tag is returned +int _cmsSearchTag(_cmsICCPROFILE* Icc, cmsTagSignature sig, cmsBool lFollowLinks) +{ + int n; + cmsTagSignature LinkedSig; + + do { + + // Search for given tag in ICC profile directory + n = SearchOneTag(Icc, sig); + if (n < 0) + return -1; // Not found + + if (!lFollowLinks) + return n; // Found, don't follow links + + // Is this a linked tag? + LinkedSig = Icc ->TagLinked[n]; + + // Yes, follow link + if (LinkedSig != (cmsTagSignature) 0) { + sig = LinkedSig; + } + + } while (LinkedSig != (cmsTagSignature) 0); + + return n; +} + + +// Create a new tag entry + +static +cmsBool _cmsNewTag(_cmsICCPROFILE* Icc, cmsTagSignature sig, int* NewPos) +{ + int i; + + // Search for the tag + i = _cmsSearchTag(Icc, sig, FALSE); + + // Now let's do it easy. If the tag has been already written, that's an error + if (i >= 0) { + cmsSignalError(Icc ->ContextID, cmsERROR_ALREADY_DEFINED, "Tag '%x' already exists", sig); + return FALSE; + } + else { + + // New one + + if (Icc -> TagCount >= MAX_TABLE_TAG) { + cmsSignalError(Icc ->ContextID, cmsERROR_RANGE, "Too many tags (%d)", MAX_TABLE_TAG); + return FALSE; + } + + *NewPos = Icc ->TagCount; + Icc -> TagCount++; + } + + return TRUE; +} + + +// Check existance +cmsBool CMSEXPORT cmsIsTag(cmsHPROFILE hProfile, cmsTagSignature sig) +{ + _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) (void*) hProfile; + return _cmsSearchTag(Icc, sig, FALSE) >= 0; +} + + +// Read profile header and validate it +cmsBool _cmsReadHeader(_cmsICCPROFILE* Icc) +{ + cmsTagEntry Tag; + cmsICCHeader Header; + cmsUInt32Number i, j; + cmsUInt32Number HeaderSize; + cmsIOHANDLER* io = Icc ->IOhandler; + cmsUInt32Number TagCount; + + + // Read the header + if (io -> Read(io, &Header, sizeof(cmsICCHeader), 1) != 1) { + return FALSE; + } + + // Validate file as an ICC profile + if (_cmsAdjustEndianess32(Header.magic) != cmsMagicNumber) { + cmsSignalError(Icc ->ContextID, cmsERROR_BAD_SIGNATURE, "not an ICC profile, invalid signature"); + return FALSE; + } + + // Adjust endianess of the used parameters + Icc -> DeviceClass = (cmsProfileClassSignature) _cmsAdjustEndianess32(Header.deviceClass); + Icc -> ColorSpace = (cmsColorSpaceSignature) _cmsAdjustEndianess32(Header.colorSpace); + Icc -> PCS = (cmsColorSpaceSignature) _cmsAdjustEndianess32(Header.pcs); + + Icc -> RenderingIntent = _cmsAdjustEndianess32(Header.renderingIntent); + Icc -> flags = _cmsAdjustEndianess32(Header.flags); + Icc -> manufacturer = _cmsAdjustEndianess32(Header.manufacturer); + Icc -> model = _cmsAdjustEndianess32(Header.model); + Icc -> creator = _cmsAdjustEndianess32(Header.creator); + + _cmsAdjustEndianess64(&Icc -> attributes, &Header.attributes); + Icc -> Version = _cmsAdjustEndianess32(Header.version); + + // Get size as reported in header + HeaderSize = _cmsAdjustEndianess32(Header.size); + + // Make sure HeaderSize is lower than profile size + if (HeaderSize >= Icc ->IOhandler ->ReportedSize) + HeaderSize = Icc ->IOhandler ->ReportedSize; + + + // Get creation date/time + _cmsDecodeDateTimeNumber(&Header.date, &Icc ->Created); + + // The profile ID are 32 raw bytes + memmove(Icc ->ProfileID.ID32, Header.profileID.ID32, 16); + + + // Read tag directory + if (!_cmsReadUInt32Number(io, &TagCount)) return FALSE; + if (TagCount > MAX_TABLE_TAG) { + + cmsSignalError(Icc ->ContextID, cmsERROR_RANGE, "Too many tags (%d)", TagCount); + return FALSE; + } + + + // Read tag directory + Icc -> TagCount = 0; + for (i=0; i < TagCount; i++) { + + if (!_cmsReadUInt32Number(io, (cmsUInt32Number *) &Tag.sig)) return FALSE; + if (!_cmsReadUInt32Number(io, &Tag.offset)) return FALSE; + if (!_cmsReadUInt32Number(io, &Tag.size)) return FALSE; + + // Perform some sanity check. Offset + size should fall inside file. + if (Tag.offset + Tag.size > HeaderSize || + Tag.offset + Tag.size < Tag.offset) + continue; + + Icc -> TagNames[Icc ->TagCount] = Tag.sig; + Icc -> TagOffsets[Icc ->TagCount] = Tag.offset; + Icc -> TagSizes[Icc ->TagCount] = Tag.size; + + // Search for links + for (j=0; j < Icc ->TagCount; j++) { + + if ((Icc ->TagOffsets[j] == Tag.offset) && + (Icc ->TagSizes[j] == Tag.size)) { + + Icc ->TagLinked[Icc ->TagCount] = Icc ->TagNames[j]; + } + + } + + Icc ->TagCount++; + } + + return TRUE; +} + +// Saves profile header +cmsBool _cmsWriteHeader(_cmsICCPROFILE* Icc, cmsUInt32Number UsedSpace) +{ + cmsICCHeader Header; + cmsUInt32Number i; + cmsTagEntry Tag; + cmsInt32Number Count = 0; + + Header.size = _cmsAdjustEndianess32(UsedSpace); + Header.cmmId = _cmsAdjustEndianess32(lcmsSignature); + Header.version = _cmsAdjustEndianess32(Icc ->Version); + + Header.deviceClass = (cmsProfileClassSignature) _cmsAdjustEndianess32(Icc -> DeviceClass); + Header.colorSpace = (cmsColorSpaceSignature) _cmsAdjustEndianess32(Icc -> ColorSpace); + Header.pcs = (cmsColorSpaceSignature) _cmsAdjustEndianess32(Icc -> PCS); + + // NOTE: in v4 Timestamp must be in UTC rather than in local time + _cmsEncodeDateTimeNumber(&Header.date, &Icc ->Created); + + Header.magic = _cmsAdjustEndianess32(cmsMagicNumber); + +#ifdef CMS_IS_WINDOWS_ + Header.platform = (cmsPlatformSignature) _cmsAdjustEndianess32(cmsSigMicrosoft); +#else + Header.platform = (cmsPlatformSignature) _cmsAdjustEndianess32(cmsSigMacintosh); +#endif + + Header.flags = _cmsAdjustEndianess32(Icc -> flags); + Header.manufacturer = _cmsAdjustEndianess32(Icc -> manufacturer); + Header.model = _cmsAdjustEndianess32(Icc -> model); + + _cmsAdjustEndianess64(&Header.attributes, &Icc -> attributes); + + // Rendering intent in the header (for embedded profiles) + Header.renderingIntent = _cmsAdjustEndianess32(Icc -> RenderingIntent); + + // Illuminant is always D50 + Header.illuminant.X = _cmsAdjustEndianess32(_cmsDoubleTo15Fixed16(cmsD50_XYZ()->X)); + Header.illuminant.Y = _cmsAdjustEndianess32(_cmsDoubleTo15Fixed16(cmsD50_XYZ()->Y)); + Header.illuminant.Z = _cmsAdjustEndianess32(_cmsDoubleTo15Fixed16(cmsD50_XYZ()->Z)); + + // Created by LittleCMS (that's me!) + Header.creator = _cmsAdjustEndianess32(lcmsSignature); + + memset(&Header.reserved, 0, sizeof(Header.reserved)); + + // Set profile ID. Endianess is always big endian + memmove(&Header.profileID, &Icc ->ProfileID, 16); + + // Dump the header + if (!Icc -> IOhandler->Write(Icc->IOhandler, sizeof(cmsICCHeader), &Header)) return FALSE; + + // Saves Tag directory + + // Get true count + for (i=0; i < Icc -> TagCount; i++) { + if (Icc ->TagNames[i] != 0) + Count++; + } + + // Store number of tags + if (!_cmsWriteUInt32Number(Icc ->IOhandler, Count)) return FALSE; + + for (i=0; i < Icc -> TagCount; i++) { + + if (Icc ->TagNames[i] == 0) continue; // It is just a placeholder + + Tag.sig = (cmsTagSignature) _cmsAdjustEndianess32((cmsInt32Number) Icc -> TagNames[i]); + Tag.offset = _cmsAdjustEndianess32((cmsInt32Number) Icc -> TagOffsets[i]); + Tag.size = _cmsAdjustEndianess32((cmsInt32Number) Icc -> TagSizes[i]); + + if (!Icc ->IOhandler -> Write(Icc-> IOhandler, sizeof(cmsTagEntry), &Tag)) return FALSE; + } + + return TRUE; +} + +// ----------------------------------------------------------------------- Set/Get several struct members + + +cmsUInt32Number CMSEXPORT cmsGetHeaderRenderingIntent(cmsHPROFILE hProfile) +{ + _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; + return Icc -> RenderingIntent; +} + +void CMSEXPORT cmsSetHeaderRenderingIntent(cmsHPROFILE hProfile, cmsUInt32Number RenderingIntent) +{ + _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; + Icc -> RenderingIntent = RenderingIntent; +} + +cmsUInt32Number CMSEXPORT cmsGetHeaderFlags(cmsHPROFILE hProfile) +{ + _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; + return (cmsUInt32Number) Icc -> flags; +} + +void CMSEXPORT cmsSetHeaderFlags(cmsHPROFILE hProfile, cmsUInt32Number Flags) +{ + _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; + Icc -> flags = (cmsUInt32Number) Flags; +} + +cmsUInt32Number CMSEXPORT cmsGetHeaderManufacturer(cmsHPROFILE hProfile) +{ + _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; + return Icc ->manufacturer; +} + +void CMSEXPORT cmsSetHeaderManufacturer(cmsHPROFILE hProfile, cmsUInt32Number manufacturer) +{ + _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; + Icc -> manufacturer = manufacturer; +} + +cmsUInt32Number CMSEXPORT cmsGetHeaderCreator(cmsHPROFILE hProfile) +{ + _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; + return Icc ->creator; +} + +cmsUInt32Number CMSEXPORT cmsGetHeaderModel(cmsHPROFILE hProfile) +{ + _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; + return Icc ->model; +} + +void CMSEXPORT cmsSetHeaderModel(cmsHPROFILE hProfile, cmsUInt32Number model) +{ + _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; + Icc -> model = model; +} + +void CMSEXPORT cmsGetHeaderAttributes(cmsHPROFILE hProfile, cmsUInt64Number* Flags) +{ + _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; + memmove(Flags, &Icc -> attributes, sizeof(cmsUInt64Number)); +} + +void CMSEXPORT cmsSetHeaderAttributes(cmsHPROFILE hProfile, cmsUInt64Number Flags) +{ + _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; + memmove(&Icc -> attributes, &Flags, sizeof(cmsUInt64Number)); +} + +void CMSEXPORT cmsGetHeaderProfileID(cmsHPROFILE hProfile, cmsUInt8Number* ProfileID) +{ + _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; + memmove(ProfileID, Icc ->ProfileID.ID8, 16); +} + +void CMSEXPORT cmsSetHeaderProfileID(cmsHPROFILE hProfile, cmsUInt8Number* ProfileID) +{ + _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; + memmove(&Icc -> ProfileID, ProfileID, 16); +} + +cmsBool CMSEXPORT cmsGetHeaderCreationDateTime(cmsHPROFILE hProfile, struct tm *Dest) +{ + _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; + memmove(Dest, &Icc ->Created, sizeof(struct tm)); + return TRUE; +} + +cmsColorSpaceSignature CMSEXPORT cmsGetPCS(cmsHPROFILE hProfile) +{ + _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; + return Icc -> PCS; +} + +void CMSEXPORT cmsSetPCS(cmsHPROFILE hProfile, cmsColorSpaceSignature pcs) +{ + _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; + Icc -> PCS = pcs; +} + +cmsColorSpaceSignature CMSEXPORT cmsGetColorSpace(cmsHPROFILE hProfile) +{ + _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; + return Icc -> ColorSpace; +} + +void CMSEXPORT cmsSetColorSpace(cmsHPROFILE hProfile, cmsColorSpaceSignature sig) +{ + _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; + Icc -> ColorSpace = sig; +} + +cmsProfileClassSignature CMSEXPORT cmsGetDeviceClass(cmsHPROFILE hProfile) +{ + _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; + return Icc -> DeviceClass; +} + +void CMSEXPORT cmsSetDeviceClass(cmsHPROFILE hProfile, cmsProfileClassSignature sig) +{ + _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; + Icc -> DeviceClass = sig; +} + +cmsUInt32Number CMSEXPORT cmsGetEncodedICCversion(cmsHPROFILE hProfile) +{ + _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; + return Icc -> Version; +} + +void CMSEXPORT cmsSetEncodedICCversion(cmsHPROFILE hProfile, cmsUInt32Number Version) +{ + _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; + Icc -> Version = Version; +} + +// Get an hexadecimal number with same digits as v +static +cmsUInt32Number BaseToBase(cmsUInt32Number in, int BaseIn, int BaseOut) +{ + char Buff[100]; + int i, len; + cmsUInt32Number out; + + for (len=0; in > 0 && len < 100; len++) { + + Buff[len] = (char) (in % BaseIn); + in /= BaseIn; + } + + for (i=len-1, out=0; i >= 0; --i) { + out = out * BaseOut + Buff[i]; + } + + return out; +} + +void CMSEXPORT cmsSetProfileVersion(cmsHPROFILE hProfile, cmsFloat64Number Version) +{ + _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; + + // 4.2 -> 0x4200000 + + Icc -> Version = BaseToBase((cmsUInt32Number) floor(Version * 100.0), 10, 16) << 16; +} + +cmsFloat64Number CMSEXPORT cmsGetProfileVersion(cmsHPROFILE hProfile) +{ + _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; + cmsUInt32Number n = Icc -> Version >> 16; + + return BaseToBase(n, 16, 10) / 100.0; +} +// -------------------------------------------------------------------------------------------------------------- + + +// Create profile from IOhandler +cmsHPROFILE CMSEXPORT cmsOpenProfileFromIOhandlerTHR(cmsContext ContextID, cmsIOHANDLER* io) +{ + _cmsICCPROFILE* NewIcc; + cmsHPROFILE hEmpty = cmsCreateProfilePlaceholder(ContextID); + + if (hEmpty == NULL) return NULL; + + NewIcc = (_cmsICCPROFILE*) hEmpty; + + NewIcc ->IOhandler = io; + if (!_cmsReadHeader(NewIcc)) goto Error; + return hEmpty; + +Error: + cmsCloseProfile(hEmpty); + return NULL; +} + +// Create profile from disk file +cmsHPROFILE CMSEXPORT cmsOpenProfileFromFileTHR(cmsContext ContextID, const char *lpFileName, const char *sAccess) +{ + _cmsICCPROFILE* NewIcc; + cmsHPROFILE hEmpty = cmsCreateProfilePlaceholder(ContextID); + + if (hEmpty == NULL) return NULL; + + NewIcc = (_cmsICCPROFILE*) hEmpty; + + NewIcc ->IOhandler = cmsOpenIOhandlerFromFile(ContextID, lpFileName, sAccess); + if (NewIcc ->IOhandler == NULL) goto Error; + + if (*sAccess == 'W' || *sAccess == 'w') { + + NewIcc -> IsWrite = TRUE; + + return hEmpty; + } + + if (!_cmsReadHeader(NewIcc)) goto Error; + return hEmpty; + +Error: + cmsCloseProfile(hEmpty); + return NULL; +} + + +cmsHPROFILE CMSEXPORT cmsOpenProfileFromFile(const char *ICCProfile, const char *sAccess) +{ + return cmsOpenProfileFromFileTHR(NULL, ICCProfile, sAccess); +} + + +cmsHPROFILE CMSEXPORT cmsOpenProfileFromStreamTHR(cmsContext ContextID, FILE* ICCProfile, const char *sAccess) +{ + _cmsICCPROFILE* NewIcc; + cmsHPROFILE hEmpty = cmsCreateProfilePlaceholder(ContextID); + + if (hEmpty == NULL) return NULL; + + NewIcc = (_cmsICCPROFILE*) hEmpty; + + NewIcc ->IOhandler = cmsOpenIOhandlerFromStream(ContextID, ICCProfile); + if (NewIcc ->IOhandler == NULL) goto Error; + + if (*sAccess == 'w') { + + NewIcc -> IsWrite = TRUE; + return hEmpty; + } + + if (!_cmsReadHeader(NewIcc)) goto Error; + return hEmpty; + +Error: + cmsCloseProfile(hEmpty); + return NULL; + +} + +cmsHPROFILE CMSEXPORT cmsOpenProfileFromStream(FILE* ICCProfile, const char *sAccess) +{ + return cmsOpenProfileFromStreamTHR(NULL, ICCProfile, sAccess); +} + + +// Open from memory block +cmsHPROFILE CMSEXPORT cmsOpenProfileFromMemTHR(cmsContext ContextID, const void* MemPtr, cmsUInt32Number dwSize) +{ + _cmsICCPROFILE* NewIcc; + cmsHPROFILE hEmpty; + + hEmpty = cmsCreateProfilePlaceholder(ContextID); + if (hEmpty == NULL) return NULL; + + NewIcc = (_cmsICCPROFILE*) hEmpty; + + // Ok, in this case const void* is casted to void* just because open IO handler + // shares read and writting modes. Don't abuse this feature! + NewIcc ->IOhandler = cmsOpenIOhandlerFromMem(ContextID, (void*) MemPtr, dwSize, "r"); + if (NewIcc ->IOhandler == NULL) goto Error; + + if (!_cmsReadHeader(NewIcc)) goto Error; + + return hEmpty; + +Error: + cmsCloseProfile(hEmpty); + return NULL; +} + +cmsHPROFILE CMSEXPORT cmsOpenProfileFromMem(const void* MemPtr, cmsUInt32Number dwSize) +{ + return cmsOpenProfileFromMemTHR(NULL, MemPtr, dwSize); +} + + + +// Dump tag contents. If the profile is being modified, untouched tags are copied from FileOrig +static +cmsBool SaveTags(_cmsICCPROFILE* Icc, _cmsICCPROFILE* FileOrig) +{ + cmsUInt8Number* Data; + cmsUInt32Number i; + cmsUInt32Number Begin; + cmsIOHANDLER* io = Icc ->IOhandler; + cmsTagDescriptor* TagDescriptor; + cmsTagTypeSignature TypeBase; + cmsTagTypeSignature Type; + cmsTagTypeHandler* TypeHandler; + cmsFloat64Number Version = cmsGetProfileVersion((cmsHPROFILE) Icc); + cmsTagTypeHandler LocalTypeHandler; + + for (i=0; i < Icc -> TagCount; i++) { + + if (Icc ->TagNames[i] == 0) continue; + + // Linked tags are not written + if (Icc ->TagLinked[i] != (cmsTagSignature) 0) continue; + + Icc -> TagOffsets[i] = Begin = io ->UsedSpace; + + Data = (cmsUInt8Number*) Icc -> TagPtrs[i]; + + if (!Data) { + + // Reach here if we are copying a tag from a disk-based ICC profile which has not been modified by user. + // In this case a blind copy of the block data is performed + if (FileOrig != NULL && Icc -> TagOffsets[i]) { + + cmsUInt32Number TagSize = FileOrig -> TagSizes[i]; + cmsUInt32Number TagOffset = FileOrig -> TagOffsets[i]; + void* Mem; + + if (!FileOrig ->IOhandler->Seek(FileOrig ->IOhandler, TagOffset)) return FALSE; + + Mem = _cmsMalloc(Icc ->ContextID, TagSize); + if (Mem == NULL) return FALSE; + + if (FileOrig ->IOhandler->Read(FileOrig->IOhandler, Mem, TagSize, 1) != 1) return FALSE; + if (!io ->Write(io, TagSize, Mem)) return FALSE; + _cmsFree(Icc ->ContextID, Mem); + + Icc -> TagSizes[i] = (io ->UsedSpace - Begin); + + + // Align to 32 bit boundary. + if (! _cmsWriteAlignment(io)) + return FALSE; + } + + continue; + } + + + // Should this tag be saved as RAW? If so, tagsizes should be specified in advance (no further cooking is done) + if (Icc ->TagSaveAsRaw[i]) { + + if (io -> Write(io, Icc ->TagSizes[i], Data) != 1) return FALSE; + } + else { + + // Search for support on this tag + TagDescriptor = _cmsGetTagDescriptor(Icc -> TagNames[i]); + if (TagDescriptor == NULL) continue; // Unsupported, ignore it + + if (TagDescriptor ->DecideType != NULL) { + + Type = TagDescriptor ->DecideType(Version, Data); + } + else { + + Type = TagDescriptor ->SupportedTypes[0]; + } + + TypeHandler = _cmsGetTagTypeHandler(Type); + + if (TypeHandler == NULL) { + cmsSignalError(Icc ->ContextID, cmsERROR_INTERNAL, "(Internal) no handler for tag %x", Icc -> TagNames[i]); + continue; + } + + TypeBase = TypeHandler ->Signature; + if (!_cmsWriteTypeBase(io, TypeBase)) + return FALSE; + + LocalTypeHandler = *TypeHandler; + LocalTypeHandler.ContextID = Icc ->ContextID; + LocalTypeHandler.ICCVersion = Icc ->Version; + if (!LocalTypeHandler.WritePtr(&LocalTypeHandler, io, Data, TagDescriptor ->ElemCount)) { + + char String[5]; + + _cmsTagSignature2String(String, (cmsTagSignature) TypeBase); + cmsSignalError(Icc ->ContextID, cmsERROR_WRITE, "Couldn't write type '%s'", String); + return FALSE; + } + } + + + Icc -> TagSizes[i] = (io ->UsedSpace - Begin); + + // Align to 32 bit boundary. + if (! _cmsWriteAlignment(io)) + return FALSE; + } + + + return TRUE; +} + + +// Fill the offset and size fields for all linked tags +static +cmsBool SetLinks( _cmsICCPROFILE* Icc) +{ + cmsUInt32Number i; + + for (i=0; i < Icc -> TagCount; i++) { + + cmsTagSignature lnk = Icc ->TagLinked[i]; + if (lnk != (cmsTagSignature) 0) { + + int j = _cmsSearchTag(Icc, lnk, FALSE); + if (j >= 0) { + + Icc ->TagOffsets[i] = Icc ->TagOffsets[j]; + Icc ->TagSizes[i] = Icc ->TagSizes[j]; + } + + } + } + + return TRUE; +} + +// Low-level save to IOHANDLER. It returns the number of bytes used to +// store the profile, or zero on error. io may be NULL and in this case +// no data is written--only sizes are calculated +cmsUInt32Number CMSEXPORT cmsSaveProfileToIOhandler(cmsHPROFILE hProfile, cmsIOHANDLER* io) +{ + _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; + _cmsICCPROFILE Keep; + cmsIOHANDLER* PrevIO; + cmsUInt32Number UsedSpace; + cmsContext ContextID; + + memmove(&Keep, Icc, sizeof(_cmsICCPROFILE)); + + ContextID = cmsGetProfileContextID(hProfile); + PrevIO = Icc ->IOhandler = cmsOpenIOhandlerFromNULL(ContextID); + if (PrevIO == NULL) return 0; + + // Pass #1 does compute offsets + + if (!_cmsWriteHeader(Icc, 0)) return 0; + if (!SaveTags(Icc, &Keep)) return 0; + + UsedSpace = PrevIO ->UsedSpace; + + // Pass #2 does save to iohandler + + if (io != NULL) { + Icc ->IOhandler = io; + if (!SetLinks(Icc)) goto CleanUp; + if (!_cmsWriteHeader(Icc, UsedSpace)) goto CleanUp; + if (!SaveTags(Icc, &Keep)) goto CleanUp; + } + + memmove(Icc, &Keep, sizeof(_cmsICCPROFILE)); + if (!cmsCloseIOhandler(PrevIO)) return 0; + + return UsedSpace; + + +CleanUp: + cmsCloseIOhandler(PrevIO); + memmove(Icc, &Keep, sizeof(_cmsICCPROFILE)); + return 0; +} + + +// Low-level save to disk. +cmsBool CMSEXPORT cmsSaveProfileToFile(cmsHPROFILE hProfile, const char* FileName) +{ + cmsContext ContextID = cmsGetProfileContextID(hProfile); + cmsIOHANDLER* io = cmsOpenIOhandlerFromFile(ContextID, FileName, "w"); + cmsBool rc; + + if (io == NULL) return FALSE; + + rc = (cmsSaveProfileToIOhandler(hProfile, io) != 0); + rc &= cmsCloseIOhandler(io); + + if (rc == FALSE) { // remove() is C99 per 7.19.4.1 + remove(FileName); // We have to IGNORE return value in this case + } + return rc; +} + +// Same as anterior, but for streams +cmsBool CMSEXPORT cmsSaveProfileToStream(cmsHPROFILE hProfile, FILE* Stream) +{ + cmsBool rc; + cmsContext ContextID = cmsGetProfileContextID(hProfile); + cmsIOHANDLER* io = cmsOpenIOhandlerFromStream(ContextID, Stream); + + if (io == NULL) return FALSE; + + rc = (cmsSaveProfileToIOhandler(hProfile, io) != 0); + rc &= cmsCloseIOhandler(io); + + return rc; +} + + +// Same as anterior, but for memory blocks. In this case, a NULL as MemPtr means calculate needed space only +cmsBool CMSEXPORT cmsSaveProfileToMem(cmsHPROFILE hProfile, void *MemPtr, cmsUInt32Number* BytesNeeded) +{ + cmsBool rc; + cmsIOHANDLER* io; + cmsContext ContextID = cmsGetProfileContextID(hProfile); + + // Should we just calculate the needed space? + if (MemPtr == NULL) { + + *BytesNeeded = cmsSaveProfileToIOhandler(hProfile, NULL); + return TRUE; + } + + // That is a real write operation + io = cmsOpenIOhandlerFromMem(ContextID, MemPtr, *BytesNeeded, "w"); + if (io == NULL) return FALSE; + + rc = (cmsSaveProfileToIOhandler(hProfile, io) != 0); + rc &= cmsCloseIOhandler(io); + + return rc; +} + + + +// Closes a profile freeing any involved resources +cmsBool CMSEXPORT cmsCloseProfile(cmsHPROFILE hProfile) +{ + _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; + cmsBool rc = TRUE; + cmsUInt32Number i; + + if (!Icc) return FALSE; + + // Was open in write mode? + if (Icc ->IsWrite) { + + Icc ->IsWrite = FALSE; // Assure no further writting + rc &= cmsSaveProfileToFile(hProfile, Icc ->IOhandler->PhysicalFile); + } + + for (i=0; i < Icc -> TagCount; i++) { + + if (Icc -> TagPtrs[i]) { + + cmsTagTypeHandler* TypeHandler = Icc ->TagTypeHandlers[i]; + + if (TypeHandler != NULL) { + cmsTagTypeHandler LocalTypeHandler = *TypeHandler; + + LocalTypeHandler.ContextID = Icc ->ContextID; // As an additional parameters + LocalTypeHandler.ICCVersion = Icc ->Version; + LocalTypeHandler.FreePtr(&LocalTypeHandler, Icc -> TagPtrs[i]); + } + else + _cmsFree(Icc ->ContextID, Icc ->TagPtrs[i]); + } + } + + if (Icc ->IOhandler != NULL) { + rc &= cmsCloseIOhandler(Icc->IOhandler); + } + + _cmsFree(Icc ->ContextID, Icc); // Free placeholder memory + + return rc; +} + + +// ------------------------------------------------------------------------------------------------------------------- + + +// Returns TRUE if a given tag is supported by a plug-in +static +cmsBool IsTypeSupported(cmsTagDescriptor* TagDescriptor, cmsTagTypeSignature Type) +{ + cmsUInt32Number i, nMaxTypes; + + nMaxTypes = TagDescriptor->nSupportedTypes; + if (nMaxTypes >= MAX_TYPES_IN_LCMS_PLUGIN) + nMaxTypes = MAX_TYPES_IN_LCMS_PLUGIN; + + for (i=0; i < nMaxTypes; i++) { + if (Type == TagDescriptor ->SupportedTypes[i]) return TRUE; + } + + return FALSE; +} + + +// That's the main read function +void* CMSEXPORT cmsReadTag(cmsHPROFILE hProfile, cmsTagSignature sig) +{ + _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; + cmsIOHANDLER* io = Icc ->IOhandler; + cmsTagTypeHandler* TypeHandler; + cmsTagTypeHandler LocalTypeHandler; + cmsTagDescriptor* TagDescriptor; + cmsTagTypeSignature BaseType; + cmsUInt32Number Offset, TagSize; + cmsUInt32Number ElemCount; + int n; + + n = _cmsSearchTag(Icc, sig, TRUE); + if (n < 0) return NULL; // Not found, return NULL + + + // If the element is already in memory, return the pointer + if (Icc -> TagPtrs[n]) { + + if (Icc ->TagSaveAsRaw[n]) return NULL; // We don't support read raw tags as cooked + return Icc -> TagPtrs[n]; + } + + // We need to read it. Get the offset and size to the file + Offset = Icc -> TagOffsets[n]; + TagSize = Icc -> TagSizes[n]; + + // Seek to its location + if (!io -> Seek(io, Offset)) + return NULL; + + // Search for support on this tag + TagDescriptor = _cmsGetTagDescriptor(sig); + if (TagDescriptor == NULL) return NULL; // Unsupported. + + // if supported, get type and check if in list + BaseType = _cmsReadTypeBase(io); + if (BaseType == 0) return NULL; + + if (!IsTypeSupported(TagDescriptor, BaseType)) return NULL; + + TagSize -= 8; // Alredy read by the type base logic + + // Get type handler + TypeHandler = _cmsGetTagTypeHandler(BaseType); + if (TypeHandler == NULL) return NULL; + LocalTypeHandler = *TypeHandler; + + + // Read the tag + Icc -> TagTypeHandlers[n] = TypeHandler; + + LocalTypeHandler.ContextID = Icc ->ContextID; + LocalTypeHandler.ICCVersion = Icc ->Version; + Icc -> TagPtrs[n] = LocalTypeHandler.ReadPtr(&LocalTypeHandler, io, &ElemCount, TagSize); + + // The tag type is supported, but something wrong happend and we cannot read the tag. + // let know the user about this (although it is just a warning) + if (Icc -> TagPtrs[n] == NULL) { + + char String[5]; + + _cmsTagSignature2String(String, sig); + cmsSignalError(Icc ->ContextID, cmsERROR_CORRUPTION_DETECTED, "Corrupted tag '%s'", String); + return NULL; + } + + // This is a weird error that may be a symptom of something more serious, the number of + // stored item is actually less than the number of required elements. + if (ElemCount < TagDescriptor ->ElemCount) { + + char String[5]; + + _cmsTagSignature2String(String, sig); + cmsSignalError(Icc ->ContextID, cmsERROR_CORRUPTION_DETECTED, "'%s' Inconsistent number of items: expected %d, got %d", + String, TagDescriptor ->ElemCount, ElemCount); + } + + + // Return the data + return Icc -> TagPtrs[n]; +} + + +// Get true type of data +cmsTagTypeSignature _cmsGetTagTrueType(cmsHPROFILE hProfile, cmsTagSignature sig) +{ + _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; + cmsTagTypeHandler* TypeHandler; + int n; + + // Search for given tag in ICC profile directory + n = _cmsSearchTag(Icc, sig, TRUE); + if (n < 0) return (cmsTagTypeSignature) 0; // Not found, return NULL + + // Get the handler. The true type is there + TypeHandler = Icc -> TagTypeHandlers[n]; + return TypeHandler ->Signature; +} + + +// Write a single tag. This just keeps track of the tak into a list of "to be written". If the tag is already +// in that list, the previous version is deleted. +cmsBool CMSEXPORT cmsWriteTag(cmsHPROFILE hProfile, cmsTagSignature sig, const void* data) +{ + _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; + cmsTagTypeHandler* TypeHandler = NULL; + cmsTagTypeHandler LocalTypeHandler; + cmsTagDescriptor* TagDescriptor = NULL; + cmsTagTypeSignature Type; + int i; + cmsFloat64Number Version; + char TypeString[5], SigString[5]; + + + if (data == NULL) { + + i = _cmsSearchTag(Icc, sig, FALSE); + if (i >= 0) + Icc ->TagNames[i] = (cmsTagSignature) 0; + // Unsupported by now, reserved for future ampliations (delete) + return FALSE; + } + + i = _cmsSearchTag(Icc, sig, FALSE); + if (i >=0) { + + if (Icc -> TagPtrs[i] != NULL) { + + // Already exists. Free previous version + if (Icc ->TagSaveAsRaw[i]) { + _cmsFree(Icc ->ContextID, Icc ->TagPtrs[i]); + } + else { + TypeHandler = Icc ->TagTypeHandlers[i]; + + if (TypeHandler != NULL) { + + LocalTypeHandler = *TypeHandler; + LocalTypeHandler.ContextID = Icc ->ContextID; // As an additional parameter + LocalTypeHandler.ICCVersion = Icc ->Version; + LocalTypeHandler.FreePtr(&LocalTypeHandler, Icc -> TagPtrs[i]); + } + } + } + } + else { + // New one + i = Icc -> TagCount; + + if (i >= MAX_TABLE_TAG) { + cmsSignalError(Icc ->ContextID, cmsERROR_RANGE, "Too many tags (%d)", MAX_TABLE_TAG); + return FALSE; + } + + Icc -> TagCount++; + } + + // This is not raw + Icc ->TagSaveAsRaw[i] = FALSE; + + // This is not a link + Icc ->TagLinked[i] = (cmsTagSignature) 0; + + // Get information about the TAG. + TagDescriptor = _cmsGetTagDescriptor(sig); + if (TagDescriptor == NULL){ + cmsSignalError(Icc ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported tag '%x'", sig); + return FALSE; + } + + + // Now we need to know which type to use. It depends on the version. + Version = cmsGetProfileVersion(hProfile); + + if (TagDescriptor ->DecideType != NULL) { + + // Let the tag descriptor to decide the type base on depending on + // the data. This is useful for example on parametric curves, where + // curves specified by a table cannot be saved as parametric and needs + // to be casted to single v2-curves, even on v4 profiles. + + Type = TagDescriptor ->DecideType(Version, data); + } + else { + + + Type = TagDescriptor ->SupportedTypes[0]; + } + + // Does the tag support this type? + if (!IsTypeSupported(TagDescriptor, Type)) { + + _cmsTagSignature2String(TypeString, (cmsTagSignature) Type); + _cmsTagSignature2String(SigString, sig); + + cmsSignalError(Icc ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported type '%s' for tag '%s'", TypeString, SigString); + return FALSE; + } + + // Does we have a handler for this type? + TypeHandler = _cmsGetTagTypeHandler(Type); + if (TypeHandler == NULL) { + + _cmsTagSignature2String(TypeString, (cmsTagSignature) Type); + _cmsTagSignature2String(SigString, sig); + + cmsSignalError(Icc ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported type '%s' for tag '%s'", TypeString, SigString); + return FALSE; // Should never happen + } + + + // Fill fields on icc structure + Icc ->TagTypeHandlers[i] = TypeHandler; + Icc ->TagNames[i] = sig; + Icc ->TagSizes[i] = 0; + Icc ->TagOffsets[i] = 0; + + LocalTypeHandler = *TypeHandler; + LocalTypeHandler.ContextID = Icc ->ContextID; + LocalTypeHandler.ICCVersion = Icc ->Version; + Icc ->TagPtrs[i] = LocalTypeHandler.DupPtr(&LocalTypeHandler, data, TagDescriptor ->ElemCount); + + if (Icc ->TagPtrs[i] == NULL) { + + _cmsTagSignature2String(TypeString, (cmsTagSignature) Type); + _cmsTagSignature2String(SigString, sig); + cmsSignalError(Icc ->ContextID, cmsERROR_CORRUPTION_DETECTED, "Malformed struct in type '%s' for tag '%s'", TypeString, SigString); + + return FALSE; + } + + return TRUE; +} + +// Read and write raw data. The only way those function would work and keep consistence with normal read and write +// is to do an additional step of serialization. That means, readRaw would issue a normal read and then convert the obtained +// data to raw bytes by using the "write" serialization logic. And vice-versa. I know this may end in situations where +// raw data written does not exactly correspond with the raw data proposed to cmsWriteRaw data, but this approach allows +// to write a tag as raw data and the read it as handled. + +cmsInt32Number CMSEXPORT cmsReadRawTag(cmsHPROFILE hProfile, cmsTagSignature sig, void* data, cmsUInt32Number BufferSize) +{ + _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; + void *Object; + int i; + cmsIOHANDLER* MemIO; + cmsTagTypeHandler* TypeHandler = NULL; + cmsTagTypeHandler LocalTypeHandler; + cmsTagDescriptor* TagDescriptor = NULL; + cmsUInt32Number rc; + cmsUInt32Number Offset, TagSize; + + // Search for given tag in ICC profile directory + i = _cmsSearchTag(Icc, sig, TRUE); + if (i < 0) return 0; // Not found, return 0 + + // It is already read? + if (Icc -> TagPtrs[i] == NULL) { + + // No yet, get original position + Offset = Icc ->TagOffsets[i]; + TagSize = Icc ->TagSizes[i]; + + // read the data directly, don't keep copy + if (data != NULL) { + + if (BufferSize < TagSize) + TagSize = BufferSize; + + if (!Icc ->IOhandler ->Seek(Icc ->IOhandler, Offset)) return 0; + if (!Icc ->IOhandler ->Read(Icc ->IOhandler, data, 1, TagSize)) return 0; + + return TagSize; + } + + return Icc ->TagSizes[i]; + } + + // The data has been already read, or written. But wait!, maybe the user choosed to save as + // raw data. In this case, return the raw data directly + if (Icc ->TagSaveAsRaw[i]) { + + if (data != NULL) { + + TagSize = Icc ->TagSizes[i]; + if (BufferSize < TagSize) + TagSize = BufferSize; + + memmove(data, Icc ->TagPtrs[i], TagSize); + + return TagSize; + } + + return Icc ->TagSizes[i]; + } + + // Already readed, or previously set by cmsWriteTag(). We need to serialize that + // data to raw in order to maintain consistency. + Object = cmsReadTag(hProfile, sig); + if (Object == NULL) return 0; + + // Now we need to serialize to a memory block: just use a memory iohandler + + if (data == NULL) { + MemIO = cmsOpenIOhandlerFromNULL(cmsGetProfileContextID(hProfile)); + } else{ + MemIO = cmsOpenIOhandlerFromMem(cmsGetProfileContextID(hProfile), data, BufferSize, "w"); + } + if (MemIO == NULL) return 0; + + // Obtain type handling for the tag + TypeHandler = Icc ->TagTypeHandlers[i]; + TagDescriptor = _cmsGetTagDescriptor(sig); + if (TagDescriptor == NULL) { + cmsCloseIOhandler(MemIO); + return 0; + } + + // FIXME: No handling for TypeHandler == NULL here? + // Serialize + LocalTypeHandler = *TypeHandler; + LocalTypeHandler.ContextID = Icc ->ContextID; + LocalTypeHandler.ICCVersion = Icc ->Version; + + if (!_cmsWriteTypeBase(MemIO, TypeHandler ->Signature)) { + cmsCloseIOhandler(MemIO); + return 0; + } + + if (!LocalTypeHandler.WritePtr(&LocalTypeHandler, MemIO, Object, TagDescriptor ->ElemCount)) { + cmsCloseIOhandler(MemIO); + return 0; + } + + // Get Size and close + rc = MemIO ->Tell(MemIO); + cmsCloseIOhandler(MemIO); // Ignore return code this time + + return rc; +} + +// Similar to the anterior. This function allows to write directly to the ICC profile any data, without +// checking anything. As a rule, mixing Raw with cooked doesn't work, so writting a tag as raw and then reading +// it as cooked without serializing does result into an error. If that is wha you want, you will need to dump +// the profile to memry or disk and then reopen it. +cmsBool CMSEXPORT cmsWriteRawTag(cmsHPROFILE hProfile, cmsTagSignature sig, const void* data, cmsUInt32Number Size) +{ + _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; + int i; + + if (!_cmsNewTag(Icc, sig, &i)) return FALSE; + + // Mark the tag as being written as RAW + Icc ->TagSaveAsRaw[i] = TRUE; + Icc ->TagNames[i] = sig; + Icc ->TagLinked[i] = (cmsTagSignature) 0; + + // Keep a copy of the block + Icc ->TagPtrs[i] = _cmsDupMem(Icc ->ContextID, data, Size); + Icc ->TagSizes[i] = Size; + + return TRUE; +} + +// Using this function you can collapse several tag entries to the same block in the profile +cmsBool CMSEXPORT cmsLinkTag(cmsHPROFILE hProfile, cmsTagSignature sig, cmsTagSignature dest) +{ + _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; + int i; + + if (!_cmsNewTag(Icc, sig, &i)) return FALSE; + + // Keep necessary information + Icc ->TagSaveAsRaw[i] = FALSE; + Icc ->TagNames[i] = sig; + Icc ->TagLinked[i] = dest; + + Icc ->TagPtrs[i] = NULL; + Icc ->TagSizes[i] = 0; + Icc ->TagOffsets[i] = 0; + + return TRUE; +} + + +// Returns the tag linked to sig, in the case two tags are sharing same resource +cmsTagSignature CMSEXPORT cmsTagLinkedTo(cmsHPROFILE hProfile, cmsTagSignature sig) +{ + _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; + int i; + + // Search for given tag in ICC profile directory + i = _cmsSearchTag(Icc, sig, FALSE); + if (i < 0) return (cmsTagSignature) 0; // Not found, return 0 + + return Icc -> TagLinked[i]; +} diff --git a/jni/lcms2-2.5/src/cmsio1.c b/jni/lcms2-2.5/src/cmsio1.c new file mode 100644 index 00000000..71f49106 --- /dev/null +++ b/jni/lcms2-2.5/src/cmsio1.c @@ -0,0 +1,1006 @@ +//--------------------------------------------------------------------------------- +// +// Little Color Management System +// Copyright (c) 1998-2012 Marti Maria Saguer +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//--------------------------------------------------------------------------------- +// + +#include "lcms2_internal.h" + +// Read tags using low-level functions, provides necessary glue code to adapt versions, etc. + +// LUT tags +static const cmsTagSignature Device2PCS16[] = {cmsSigAToB0Tag, // Perceptual + cmsSigAToB1Tag, // Relative colorimetric + cmsSigAToB2Tag, // Saturation + cmsSigAToB1Tag }; // Absolute colorimetric + +static const cmsTagSignature Device2PCSFloat[] = {cmsSigDToB0Tag, // Perceptual + cmsSigDToB1Tag, // Relative colorimetric + cmsSigDToB2Tag, // Saturation + cmsSigDToB3Tag }; // Absolute colorimetric + +static const cmsTagSignature PCS2Device16[] = {cmsSigBToA0Tag, // Perceptual + cmsSigBToA1Tag, // Relative colorimetric + cmsSigBToA2Tag, // Saturation + cmsSigBToA1Tag }; // Absolute colorimetric + +static const cmsTagSignature PCS2DeviceFloat[] = {cmsSigBToD0Tag, // Perceptual + cmsSigBToD1Tag, // Relative colorimetric + cmsSigBToD2Tag, // Saturation + cmsSigBToD3Tag }; // Absolute colorimetric + + +// Factors to convert from 1.15 fixed point to 0..1.0 range and vice-versa +#define InpAdj (1.0/MAX_ENCODEABLE_XYZ) // (65536.0/(65535.0*2.0)) +#define OutpAdj (MAX_ENCODEABLE_XYZ) // ((2.0*65535.0)/65536.0) + +// Several resources for gray conversions. +static const cmsFloat64Number GrayInputMatrix[] = { (InpAdj*cmsD50X), (InpAdj*cmsD50Y), (InpAdj*cmsD50Z) }; +static const cmsFloat64Number OneToThreeInputMatrix[] = { 1, 1, 1 }; +static const cmsFloat64Number PickYMatrix[] = { 0, (OutpAdj*cmsD50Y), 0 }; +static const cmsFloat64Number PickLstarMatrix[] = { 1, 0, 0 }; + +// Get a media white point fixing some issues found in certain old profiles +cmsBool _cmsReadMediaWhitePoint(cmsCIEXYZ* Dest, cmsHPROFILE hProfile) +{ + cmsCIEXYZ* Tag; + + _cmsAssert(Dest != NULL); + + Tag = (cmsCIEXYZ*) cmsReadTag(hProfile, cmsSigMediaWhitePointTag); + + // If no wp, take D50 + if (Tag == NULL) { + *Dest = *cmsD50_XYZ(); + return TRUE; + } + + // V2 display profiles should give D50 + if (cmsGetEncodedICCversion(hProfile) < 0x4000000) { + + if (cmsGetDeviceClass(hProfile) == cmsSigDisplayClass) { + *Dest = *cmsD50_XYZ(); + return TRUE; + } + } + + // All seems ok + *Dest = *Tag; + return TRUE; +} + + +// Chromatic adaptation matrix. Fix some issues as well +cmsBool _cmsReadCHAD(cmsMAT3* Dest, cmsHPROFILE hProfile) +{ + cmsMAT3* Tag; + + _cmsAssert(Dest != NULL); + + Tag = (cmsMAT3*) cmsReadTag(hProfile, cmsSigChromaticAdaptationTag); + + if (Tag != NULL) { + *Dest = *Tag; + return TRUE; + } + + // No CHAD available, default it to identity + _cmsMAT3identity(Dest); + + // V2 display profiles should give D50 + if (cmsGetEncodedICCversion(hProfile) < 0x4000000) { + + if (cmsGetDeviceClass(hProfile) == cmsSigDisplayClass) { + + cmsCIEXYZ* White = (cmsCIEXYZ*) cmsReadTag(hProfile, cmsSigMediaWhitePointTag); + + if (White == NULL) { + + _cmsMAT3identity(Dest); + return TRUE; + } + + return _cmsAdaptationMatrix(Dest, NULL, White, cmsD50_XYZ()); + } + } + + return TRUE; +} + + +// Auxiliar, read colorants as a MAT3 structure. Used by any function that needs a matrix-shaper +static +cmsBool ReadICCMatrixRGB2XYZ(cmsMAT3* r, cmsHPROFILE hProfile) +{ + cmsCIEXYZ *PtrRed, *PtrGreen, *PtrBlue; + + _cmsAssert(r != NULL); + + PtrRed = (cmsCIEXYZ *) cmsReadTag(hProfile, cmsSigRedColorantTag); + PtrGreen = (cmsCIEXYZ *) cmsReadTag(hProfile, cmsSigGreenColorantTag); + PtrBlue = (cmsCIEXYZ *) cmsReadTag(hProfile, cmsSigBlueColorantTag); + + if (PtrRed == NULL || PtrGreen == NULL || PtrBlue == NULL) + return FALSE; + + _cmsVEC3init(&r -> v[0], PtrRed -> X, PtrGreen -> X, PtrBlue -> X); + _cmsVEC3init(&r -> v[1], PtrRed -> Y, PtrGreen -> Y, PtrBlue -> Y); + _cmsVEC3init(&r -> v[2], PtrRed -> Z, PtrGreen -> Z, PtrBlue -> Z); + + return TRUE; +} + + +// Gray input pipeline +static +cmsPipeline* BuildGrayInputMatrixPipeline(cmsHPROFILE hProfile) +{ + cmsToneCurve *GrayTRC; + cmsPipeline* Lut; + cmsContext ContextID = cmsGetProfileContextID(hProfile); + + GrayTRC = (cmsToneCurve *) cmsReadTag(hProfile, cmsSigGrayTRCTag); + if (GrayTRC == NULL) return NULL; + + Lut = cmsPipelineAlloc(ContextID, 1, 3); + if (Lut == NULL) + goto Error; + + if (cmsGetPCS(hProfile) == cmsSigLabData) { + + // In this case we implement the profile as an identity matrix plus 3 tone curves + cmsUInt16Number Zero[2] = { 0x8080, 0x8080 }; + cmsToneCurve* EmptyTab; + cmsToneCurve* LabCurves[3]; + + EmptyTab = cmsBuildTabulatedToneCurve16(ContextID, 2, Zero); + + if (EmptyTab == NULL) + goto Error; + + LabCurves[0] = GrayTRC; + LabCurves[1] = EmptyTab; + LabCurves[2] = EmptyTab; + + if (!cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 3, 1, OneToThreeInputMatrix, NULL)) || + !cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 3, LabCurves))) { + cmsFreeToneCurve(EmptyTab); + goto Error; + } + + cmsFreeToneCurve(EmptyTab); + + } + else { + + if (!cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 1, &GrayTRC)) || + !cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 3, 1, GrayInputMatrix, NULL))) + goto Error; + } + + return Lut; + +Error: + cmsFreeToneCurve(GrayTRC); + cmsPipelineFree(Lut); + return NULL; +} + +// RGB Matrix shaper +static +cmsPipeline* BuildRGBInputMatrixShaper(cmsHPROFILE hProfile) +{ + cmsPipeline* Lut; + cmsMAT3 Mat; + cmsToneCurve *Shapes[3]; + cmsContext ContextID = cmsGetProfileContextID(hProfile); + int i, j; + + if (!ReadICCMatrixRGB2XYZ(&Mat, hProfile)) return NULL; + + // XYZ PCS in encoded in 1.15 format, and the matrix output comes in 0..0xffff range, so + // we need to adjust the output by a factor of (0x10000/0xffff) to put data in + // a 1.16 range, and then a >> 1 to obtain 1.15. The total factor is (65536.0)/(65535.0*2) + + for (i=0; i < 3; i++) + for (j=0; j < 3; j++) + Mat.v[i].n[j] *= InpAdj; + + + Shapes[0] = (cmsToneCurve *) cmsReadTag(hProfile, cmsSigRedTRCTag); + Shapes[1] = (cmsToneCurve *) cmsReadTag(hProfile, cmsSigGreenTRCTag); + Shapes[2] = (cmsToneCurve *) cmsReadTag(hProfile, cmsSigBlueTRCTag); + + if (!Shapes[0] || !Shapes[1] || !Shapes[2]) + return NULL; + + Lut = cmsPipelineAlloc(ContextID, 3, 3); + if (Lut != NULL) { + + if (!cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 3, Shapes)) || + !cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 3, 3, (cmsFloat64Number*) &Mat, NULL))) + goto Error; + + // Note that it is certainly possible a single profile would have a LUT based + // tag for output working in lab and a matrix-shaper for the fallback cases. + // This is not allowed by the spec, but this code is tolerant to those cases + if (cmsGetPCS(hProfile) == cmsSigLabData) { + + if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocXYZ2Lab(ContextID))) + goto Error; + } + + } + + return Lut; + +Error: + cmsPipelineFree(Lut); + return NULL; +} + + + +// Read the DToAX tag, adjusting the encoding of Lab or XYZ if neded +static +cmsPipeline* _cmsReadFloatInputTag(cmsHPROFILE hProfile, cmsTagSignature tagFloat) +{ + cmsContext ContextID = cmsGetProfileContextID(hProfile); + cmsPipeline* Lut = cmsPipelineDup((cmsPipeline*) cmsReadTag(hProfile, tagFloat)); + cmsColorSpaceSignature spc = cmsGetColorSpace(hProfile); + cmsColorSpaceSignature PCS = cmsGetPCS(hProfile); + + if (Lut == NULL) return NULL; + + // input and output of transform are in lcms 0..1 encoding. If XYZ or Lab spaces are used, + // these need to be normalized into the appropriate ranges (Lab = 100,0,0, XYZ=1.0,1.0,1.0) + if ( spc == cmsSigLabData) + { + if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToLabFloat(ContextID))) + goto Error; + } + else if (spc == cmsSigXYZData) + { + if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToXyzFloat(ContextID))) + goto Error; + } + + if ( PCS == cmsSigLabData) + { + if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromLabFloat(ContextID))) + goto Error; + } + else if( PCS == cmsSigXYZData) + { + if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromXyzFloat(ContextID))) + goto Error; + } + + return Lut; + +Error: + cmsPipelineFree(Lut); + return NULL; +} + + +// Read and create a BRAND NEW MPE LUT from a given profile. All stuff dependent of version, etc +// is adjusted here in order to create a LUT that takes care of all those details +cmsPipeline* _cmsReadInputLUT(cmsHPROFILE hProfile, int Intent) +{ + cmsTagTypeSignature OriginalType; + cmsTagSignature tag16 = Device2PCS16[Intent]; + cmsTagSignature tagFloat = Device2PCSFloat[Intent]; + cmsContext ContextID = cmsGetProfileContextID(hProfile); + + // On named color, take the appropiate tag + if (cmsGetDeviceClass(hProfile) == cmsSigNamedColorClass) { + + cmsPipeline* Lut; + cmsNAMEDCOLORLIST* nc = (cmsNAMEDCOLORLIST*) cmsReadTag(hProfile, cmsSigNamedColor2Tag); + + if (nc == NULL) return NULL; + + Lut = cmsPipelineAlloc(ContextID, 0, 0); + if (Lut == NULL) { + cmsFreeNamedColorList(nc); + return NULL; + } + + if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocNamedColor(nc, TRUE)) || + !cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID))) { + cmsPipelineFree(Lut); + return NULL; + } + return Lut; + } + + if (cmsIsTag(hProfile, tagFloat)) { // Float tag takes precedence + + // Floating point LUT are always V4, but the encoding range is no + // longer 0..1.0, so we need to add an stage depending on the color space + return _cmsReadFloatInputTag(hProfile, tagFloat); + } + + // Revert to perceptual if no tag is found + if (!cmsIsTag(hProfile, tag16)) { + tag16 = Device2PCS16[0]; + } + + if (cmsIsTag(hProfile, tag16)) { // Is there any LUT-Based table? + + // Check profile version and LUT type. Do the necessary adjustments if needed + + // First read the tag + cmsPipeline* Lut = (cmsPipeline*) cmsReadTag(hProfile, tag16); + if (Lut == NULL) return NULL; + + // After reading it, we have now info about the original type + OriginalType = _cmsGetTagTrueType(hProfile, tag16); + + // The profile owns the Lut, so we need to copy it + Lut = cmsPipelineDup(Lut); + + // We need to adjust data only for Lab16 on output + if (OriginalType != cmsSigLut16Type || cmsGetPCS(hProfile) != cmsSigLabData) + return Lut; + + // If the input is Lab, add also a conversion at the begin + if (cmsGetColorSpace(hProfile) == cmsSigLabData && + !cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocLabV4ToV2(ContextID))) + goto Error; + + // Add a matrix for conversion V2 to V4 Lab PCS + if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID))) + goto Error; + + return Lut; +Error: + cmsPipelineFree(Lut); + return NULL; + } + + // Lut was not found, try to create a matrix-shaper + + // Check if this is a grayscale profile. + if (cmsGetColorSpace(hProfile) == cmsSigGrayData) { + + // if so, build appropiate conversion tables. + // The tables are the PCS iluminant, scaled across GrayTRC + return BuildGrayInputMatrixPipeline(hProfile); + } + + // Not gray, create a normal matrix-shaper + return BuildRGBInputMatrixShaper(hProfile); +} + +// --------------------------------------------------------------------------------------------------------------- + +// Gray output pipeline. +// XYZ -> Gray or Lab -> Gray. Since we only know the GrayTRC, we need to do some assumptions. Gray component will be +// given by Y on XYZ PCS and by L* on Lab PCS, Both across inverse TRC curve. +// The complete pipeline on XYZ is Matrix[3:1] -> Tone curve and in Lab Matrix[3:1] -> Tone Curve as well. + +static +cmsPipeline* BuildGrayOutputPipeline(cmsHPROFILE hProfile) +{ + cmsToneCurve *GrayTRC, *RevGrayTRC; + cmsPipeline* Lut; + cmsContext ContextID = cmsGetProfileContextID(hProfile); + + GrayTRC = (cmsToneCurve *) cmsReadTag(hProfile, cmsSigGrayTRCTag); + if (GrayTRC == NULL) return NULL; + + RevGrayTRC = cmsReverseToneCurve(GrayTRC); + if (RevGrayTRC == NULL) return NULL; + + Lut = cmsPipelineAlloc(ContextID, 3, 1); + if (Lut == NULL) { + cmsFreeToneCurve(RevGrayTRC); + return NULL; + } + + if (cmsGetPCS(hProfile) == cmsSigLabData) { + + if (!cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 1, 3, PickLstarMatrix, NULL))) + goto Error; + } + else { + if (!cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 1, 3, PickYMatrix, NULL))) + goto Error; + } + + if (!cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 1, &RevGrayTRC))) + goto Error; + + cmsFreeToneCurve(RevGrayTRC); + return Lut; + +Error: + cmsFreeToneCurve(RevGrayTRC); + cmsPipelineFree(Lut); + return NULL; +} + + +static +cmsPipeline* BuildRGBOutputMatrixShaper(cmsHPROFILE hProfile) +{ + cmsPipeline* Lut; + cmsToneCurve *Shapes[3], *InvShapes[3]; + cmsMAT3 Mat, Inv; + int i, j; + cmsContext ContextID = cmsGetProfileContextID(hProfile); + + if (!ReadICCMatrixRGB2XYZ(&Mat, hProfile)) + return NULL; + + if (!_cmsMAT3inverse(&Mat, &Inv)) + return NULL; + + // XYZ PCS in encoded in 1.15 format, and the matrix input should come in 0..0xffff range, so + // we need to adjust the input by a << 1 to obtain a 1.16 fixed and then by a factor of + // (0xffff/0x10000) to put data in 0..0xffff range. Total factor is (2.0*65535.0)/65536.0; + + for (i=0; i < 3; i++) + for (j=0; j < 3; j++) + Inv.v[i].n[j] *= OutpAdj; + + Shapes[0] = (cmsToneCurve *) cmsReadTag(hProfile, cmsSigRedTRCTag); + Shapes[1] = (cmsToneCurve *) cmsReadTag(hProfile, cmsSigGreenTRCTag); + Shapes[2] = (cmsToneCurve *) cmsReadTag(hProfile, cmsSigBlueTRCTag); + + if (!Shapes[0] || !Shapes[1] || !Shapes[2]) + return NULL; + + InvShapes[0] = cmsReverseToneCurve(Shapes[0]); + InvShapes[1] = cmsReverseToneCurve(Shapes[1]); + InvShapes[2] = cmsReverseToneCurve(Shapes[2]); + + if (!InvShapes[0] || !InvShapes[1] || !InvShapes[2]) { + return NULL; + } + + Lut = cmsPipelineAlloc(ContextID, 3, 3); + if (Lut != NULL) { + + // Note that it is certainly possible a single profile would have a LUT based + // tag for output working in lab and a matrix-shaper for the fallback cases. + // This is not allowed by the spec, but this code is tolerant to those cases + if (cmsGetPCS(hProfile) == cmsSigLabData) { + + if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLab2XYZ(ContextID))) + goto Error; + } + + if (!cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 3, 3, (cmsFloat64Number*) &Inv, NULL)) || + !cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 3, InvShapes))) + goto Error; + } + + cmsFreeToneCurveTriple(InvShapes); + return Lut; +Error: + cmsFreeToneCurveTriple(InvShapes); + cmsPipelineFree(Lut); + return NULL; +} + + +// Change CLUT interpolation to trilinear +static +void ChangeInterpolationToTrilinear(cmsPipeline* Lut) +{ + cmsStage* Stage; + + for (Stage = cmsPipelineGetPtrToFirstStage(Lut); + Stage != NULL; + Stage = cmsStageNext(Stage)) { + + if (cmsStageType(Stage) == cmsSigCLutElemType) { + + _cmsStageCLutData* CLUT = (_cmsStageCLutData*) Stage ->Data; + + CLUT ->Params->dwFlags |= CMS_LERP_FLAGS_TRILINEAR; + _cmsSetInterpolationRoutine(CLUT ->Params); + } + } +} + + +// Read the DToAX tag, adjusting the encoding of Lab or XYZ if neded +static +cmsPipeline* _cmsReadFloatOutputTag(cmsHPROFILE hProfile, cmsTagSignature tagFloat) +{ + cmsContext ContextID = cmsGetProfileContextID(hProfile); + cmsPipeline* Lut = cmsPipelineDup((cmsPipeline*) cmsReadTag(hProfile, tagFloat)); + cmsColorSpaceSignature PCS = cmsGetPCS(hProfile); + cmsColorSpaceSignature dataSpace = cmsGetColorSpace(hProfile); + + if (Lut == NULL) return NULL; + + // If PCS is Lab or XYZ, the floating point tag is accepting data in the space encoding, + // and since the formatter has already accomodated to 0..1.0, we should undo this change + if ( PCS == cmsSigLabData) + { + if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToLabFloat(ContextID))) + goto Error; + } + else + if (PCS == cmsSigXYZData) + { + if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToXyzFloat(ContextID))) + goto Error; + } + + // the output can be Lab or XYZ, in which case normalisation is needed on the end of the pipeline + if ( dataSpace == cmsSigLabData) + { + if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromLabFloat(ContextID))) + goto Error; + } + else if (dataSpace == cmsSigXYZData) + { + if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromXyzFloat(ContextID))) + goto Error; + } + + return Lut; + +Error: + cmsPipelineFree(Lut); + return NULL; +} + +// Create an output MPE LUT from agiven profile. Version mismatches are handled here +cmsPipeline* _cmsReadOutputLUT(cmsHPROFILE hProfile, int Intent) +{ + cmsTagTypeSignature OriginalType; + cmsTagSignature tag16 = PCS2Device16[Intent]; + cmsTagSignature tagFloat = PCS2DeviceFloat[Intent]; + cmsContext ContextID = cmsGetProfileContextID(hProfile); + + if (cmsIsTag(hProfile, tagFloat)) { // Float tag takes precedence + + // Floating point LUT are always V4 + return _cmsReadFloatOutputTag(hProfile, tagFloat); + } + + // Revert to perceptual if no tag is found + if (!cmsIsTag(hProfile, tag16)) { + tag16 = PCS2Device16[0]; + } + + if (cmsIsTag(hProfile, tag16)) { // Is there any LUT-Based table? + + // Check profile version and LUT type. Do the necessary adjustments if needed + + // First read the tag + cmsPipeline* Lut = (cmsPipeline*) cmsReadTag(hProfile, tag16); + if (Lut == NULL) return NULL; + + // After reading it, we have info about the original type + OriginalType = _cmsGetTagTrueType(hProfile, tag16); + + // The profile owns the Lut, so we need to copy it + Lut = cmsPipelineDup(Lut); + if (Lut == NULL) return NULL; + + // Now it is time for a controversial stuff. I found that for 3D LUTS using + // Lab used as indexer space, trilinear interpolation should be used + if (cmsGetPCS(hProfile) == cmsSigLabData) + ChangeInterpolationToTrilinear(Lut); + + // We need to adjust data only for Lab and Lut16 type + if (OriginalType != cmsSigLut16Type || cmsGetPCS(hProfile) != cmsSigLabData) + return Lut; + + // Add a matrix for conversion V4 to V2 Lab PCS + if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocLabV4ToV2(ContextID))) + goto Error; + + // If the output is Lab, add also a conversion at the end + if (cmsGetColorSpace(hProfile) == cmsSigLabData) + if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID))) + goto Error; + + return Lut; +Error: + cmsPipelineFree(Lut); + return NULL; + } + + // Lut not found, try to create a matrix-shaper + + // Check if this is a grayscale profile. + if (cmsGetColorSpace(hProfile) == cmsSigGrayData) { + + // if so, build appropiate conversion tables. + // The tables are the PCS iluminant, scaled across GrayTRC + return BuildGrayOutputPipeline(hProfile); + } + + // Not gray, create a normal matrix-shaper, which only operates in XYZ space + return BuildRGBOutputMatrixShaper(hProfile); +} + +// --------------------------------------------------------------------------------------------------------------- + +// Read the AToD0 tag, adjusting the encoding of Lab or XYZ if neded +static +cmsPipeline* _cmsReadFloatDevicelinkTag(cmsHPROFILE hProfile, cmsTagSignature tagFloat) +{ + cmsContext ContextID = cmsGetProfileContextID(hProfile); + cmsPipeline* Lut = cmsPipelineDup((cmsPipeline*) cmsReadTag(hProfile, tagFloat)); + cmsColorSpaceSignature PCS = cmsGetPCS(hProfile); + cmsColorSpaceSignature spc = cmsGetColorSpace(hProfile); + + if (Lut == NULL) return NULL; + + if (spc == cmsSigLabData) + { + if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToLabFloat(ContextID))) + goto Error; + } + else + if (spc == cmsSigXYZData) + { + if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToXyzFloat(ContextID))) + goto Error; + } + + if (PCS == cmsSigLabData) + { + if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromLabFloat(ContextID))) + goto Error; + } + else + if (PCS == cmsSigXYZData) + { + if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromXyzFloat(ContextID))) + goto Error; + } + + return Lut; +Error: + cmsPipelineFree(Lut); + return NULL; +} + +// This one includes abstract profiles as well. Matrix-shaper cannot be obtained on that device class. The +// tag name here may default to AToB0 +cmsPipeline* _cmsReadDevicelinkLUT(cmsHPROFILE hProfile, int Intent) +{ + cmsPipeline* Lut; + cmsTagTypeSignature OriginalType; + cmsTagSignature tag16 = Device2PCS16[Intent]; + cmsTagSignature tagFloat = Device2PCSFloat[Intent]; + cmsContext ContextID = cmsGetProfileContextID(hProfile); + + + // On named color, take the appropiate tag + if (cmsGetDeviceClass(hProfile) == cmsSigNamedColorClass) { + + cmsNAMEDCOLORLIST* nc = (cmsNAMEDCOLORLIST*) cmsReadTag(hProfile, cmsSigNamedColor2Tag); + + if (nc == NULL) return NULL; + + Lut = cmsPipelineAlloc(ContextID, 0, 0); + if (Lut == NULL) + goto Error; + + if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocNamedColor(nc, FALSE))) + goto Error; + + if (cmsGetColorSpace(hProfile) == cmsSigLabData) + if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID))) + goto Error; + + return Lut; +Error: + cmsPipelineFree(Lut); + cmsFreeNamedColorList(nc); + return NULL; + } + + if (cmsIsTag(hProfile, tagFloat)) { // Float tag takes precedence + + // Floating point LUT are always V + return _cmsReadFloatDevicelinkTag(hProfile, tagFloat); + } + + tagFloat = Device2PCSFloat[0]; + if (cmsIsTag(hProfile, tagFloat)) { + + return cmsPipelineDup((cmsPipeline*) cmsReadTag(hProfile, tagFloat)); + } + + if (!cmsIsTag(hProfile, tag16)) { // Is there any LUT-Based table? + + tag16 = Device2PCS16[0]; + if (!cmsIsTag(hProfile, tag16)) return NULL; + } + + // Check profile version and LUT type. Do the necessary adjustments if needed + + // Read the tag + Lut = (cmsPipeline*) cmsReadTag(hProfile, tag16); + if (Lut == NULL) return NULL; + + // The profile owns the Lut, so we need to copy it + Lut = cmsPipelineDup(Lut); + if (Lut == NULL) return NULL; + + // Now it is time for a controversial stuff. I found that for 3D LUTS using + // Lab used as indexer space, trilinear interpolation should be used + if (cmsGetColorSpace(hProfile) == cmsSigLabData) + ChangeInterpolationToTrilinear(Lut); + + // After reading it, we have info about the original type + OriginalType = _cmsGetTagTrueType(hProfile, tag16); + + // We need to adjust data for Lab16 on output + if (OriginalType != cmsSigLut16Type) return Lut; + + // Here it is possible to get Lab on both sides + + if (cmsGetPCS(hProfile) == cmsSigLabData) { + if(!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocLabV4ToV2(ContextID))) + goto Error2; + } + + if (cmsGetColorSpace(hProfile) == cmsSigLabData) { + if(!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID))) + goto Error2; + } + + return Lut; + +Error2: + cmsPipelineFree(Lut); + return NULL; +} + +// --------------------------------------------------------------------------------------------------------------- + +// Returns TRUE if the profile is implemented as matrix-shaper +cmsBool CMSEXPORT cmsIsMatrixShaper(cmsHPROFILE hProfile) +{ + switch (cmsGetColorSpace(hProfile)) { + + case cmsSigGrayData: + + return cmsIsTag(hProfile, cmsSigGrayTRCTag); + + case cmsSigRgbData: + + return (cmsIsTag(hProfile, cmsSigRedColorantTag) && + cmsIsTag(hProfile, cmsSigGreenColorantTag) && + cmsIsTag(hProfile, cmsSigBlueColorantTag) && + cmsIsTag(hProfile, cmsSigRedTRCTag) && + cmsIsTag(hProfile, cmsSigGreenTRCTag) && + cmsIsTag(hProfile, cmsSigBlueTRCTag)); + + default: + + return FALSE; + } +} + +// Returns TRUE if the intent is implemented as CLUT +cmsBool CMSEXPORT cmsIsCLUT(cmsHPROFILE hProfile, cmsUInt32Number Intent, cmsUInt32Number UsedDirection) +{ + const cmsTagSignature* TagTable; + + // For devicelinks, the supported intent is that one stated in the header + if (cmsGetDeviceClass(hProfile) == cmsSigLinkClass) { + return (cmsGetHeaderRenderingIntent(hProfile) == Intent); + } + + switch (UsedDirection) { + + case LCMS_USED_AS_INPUT: TagTable = Device2PCS16; break; + case LCMS_USED_AS_OUTPUT:TagTable = PCS2Device16; break; + + // For proofing, we need rel. colorimetric in output. Let's do some recursion + case LCMS_USED_AS_PROOF: + return cmsIsIntentSupported(hProfile, Intent, LCMS_USED_AS_INPUT) && + cmsIsIntentSupported(hProfile, INTENT_RELATIVE_COLORIMETRIC, LCMS_USED_AS_OUTPUT); + + default: + cmsSignalError(cmsGetProfileContextID(hProfile), cmsERROR_RANGE, "Unexpected direction (%d)", UsedDirection); + return FALSE; + } + + return cmsIsTag(hProfile, TagTable[Intent]); + +} + + +// Return info about supported intents +cmsBool CMSEXPORT cmsIsIntentSupported(cmsHPROFILE hProfile, + cmsUInt32Number Intent, cmsUInt32Number UsedDirection) +{ + + if (cmsIsCLUT(hProfile, Intent, UsedDirection)) return TRUE; + + // Is there any matrix-shaper? If so, the intent is supported. This is a bit odd, since V2 matrix shaper + // does not fully support relative colorimetric because they cannot deal with non-zero black points, but + // many profiles claims that, and this is certainly not true for V4 profiles. Lets answer "yes" no matter + // the accuracy would be less than optimal in rel.col and v2 case. + + return cmsIsMatrixShaper(hProfile); +} + + +// --------------------------------------------------------------------------------------------------------------- + +// Read both, profile sequence description and profile sequence id if present. Then combine both to +// create qa unique structure holding both. Shame on ICC to store things in such complicated way. +cmsSEQ* _cmsReadProfileSequence(cmsHPROFILE hProfile) +{ + cmsSEQ* ProfileSeq; + cmsSEQ* ProfileId; + cmsSEQ* NewSeq; + cmsUInt32Number i; + + // Take profile sequence description first + ProfileSeq = (cmsSEQ*) cmsReadTag(hProfile, cmsSigProfileSequenceDescTag); + + // Take profile sequence ID + ProfileId = (cmsSEQ*) cmsReadTag(hProfile, cmsSigProfileSequenceIdTag); + + if (ProfileSeq == NULL && ProfileId == NULL) return NULL; + + if (ProfileSeq == NULL) return cmsDupProfileSequenceDescription(ProfileId); + if (ProfileId == NULL) return cmsDupProfileSequenceDescription(ProfileSeq); + + // We have to mix both together. For that they must agree + if (ProfileSeq ->n != ProfileId ->n) return cmsDupProfileSequenceDescription(ProfileSeq); + + NewSeq = cmsDupProfileSequenceDescription(ProfileSeq); + + // Ok, proceed to the mixing + if (NewSeq != NULL) { + for (i=0; i < ProfileSeq ->n; i++) { + + memmove(&NewSeq ->seq[i].ProfileID, &ProfileId ->seq[i].ProfileID, sizeof(cmsProfileID)); + NewSeq ->seq[i].Description = cmsMLUdup(ProfileId ->seq[i].Description); + } + } + return NewSeq; +} + +// Dump the contents of profile sequence in both tags (if v4 available) +cmsBool _cmsWriteProfileSequence(cmsHPROFILE hProfile, const cmsSEQ* seq) +{ + if (!cmsWriteTag(hProfile, cmsSigProfileSequenceDescTag, seq)) return FALSE; + + if (cmsGetProfileVersion(hProfile) >= 4.0) { + + if (!cmsWriteTag(hProfile, cmsSigProfileSequenceIdTag, seq)) return FALSE; + } + + return TRUE; +} + + +// Auxiliar, read and duplicate a MLU if found. +static +cmsMLU* GetMLUFromProfile(cmsHPROFILE h, cmsTagSignature sig) +{ + cmsMLU* mlu = (cmsMLU*) cmsReadTag(h, sig); + if (mlu == NULL) return NULL; + + return cmsMLUdup(mlu); +} + +// Create a sequence description out of an array of profiles +cmsSEQ* _cmsCompileProfileSequence(cmsContext ContextID, cmsUInt32Number nProfiles, cmsHPROFILE hProfiles[]) +{ + cmsUInt32Number i; + cmsSEQ* seq = cmsAllocProfileSequenceDescription(ContextID, nProfiles); + + if (seq == NULL) return NULL; + + for (i=0; i < nProfiles; i++) { + + cmsPSEQDESC* ps = &seq ->seq[i]; + cmsHPROFILE h = hProfiles[i]; + cmsTechnologySignature* techpt; + + cmsGetHeaderAttributes(h, &ps ->attributes); + cmsGetHeaderProfileID(h, ps ->ProfileID.ID8); + ps ->deviceMfg = cmsGetHeaderManufacturer(h); + ps ->deviceModel = cmsGetHeaderModel(h); + + techpt = (cmsTechnologySignature*) cmsReadTag(h, cmsSigTechnologyTag); + if (techpt == NULL) + ps ->technology = (cmsTechnologySignature) 0; + else + ps ->technology = *techpt; + + ps ->Manufacturer = GetMLUFromProfile(h, cmsSigDeviceMfgDescTag); + ps ->Model = GetMLUFromProfile(h, cmsSigDeviceModelDescTag); + ps ->Description = GetMLUFromProfile(h, cmsSigProfileDescriptionTag); + + } + + return seq; +} + +// ------------------------------------------------------------------------------------------------------------------- + + +static +const cmsMLU* GetInfo(cmsHPROFILE hProfile, cmsInfoType Info) +{ + cmsTagSignature sig; + + switch (Info) { + + case cmsInfoDescription: + sig = cmsSigProfileDescriptionTag; + break; + + case cmsInfoManufacturer: + sig = cmsSigDeviceMfgDescTag; + break; + + case cmsInfoModel: + sig = cmsSigDeviceModelDescTag; + break; + + case cmsInfoCopyright: + sig = cmsSigCopyrightTag; + break; + + default: return NULL; + } + + + return (cmsMLU*) cmsReadTag(hProfile, sig); +} + + + +cmsUInt32Number CMSEXPORT cmsGetProfileInfo(cmsHPROFILE hProfile, cmsInfoType Info, + const char LanguageCode[3], const char CountryCode[3], + wchar_t* Buffer, cmsUInt32Number BufferSize) +{ + const cmsMLU* mlu = GetInfo(hProfile, Info); + if (mlu == NULL) return 0; + + return cmsMLUgetWide(mlu, LanguageCode, CountryCode, Buffer, BufferSize); +} + + +cmsUInt32Number CMSEXPORT cmsGetProfileInfoASCII(cmsHPROFILE hProfile, cmsInfoType Info, + const char LanguageCode[3], const char CountryCode[3], + char* Buffer, cmsUInt32Number BufferSize) +{ + const cmsMLU* mlu = GetInfo(hProfile, Info); + if (mlu == NULL) return 0; + + return cmsMLUgetASCII(mlu, LanguageCode, CountryCode, Buffer, BufferSize); +} diff --git a/jni/lcms2-2.5/src/cmslut.c b/jni/lcms2-2.5/src/cmslut.c new file mode 100644 index 00000000..c491662b --- /dev/null +++ b/jni/lcms2-2.5/src/cmslut.c @@ -0,0 +1,1795 @@ +//--------------------------------------------------------------------------------- +// +// Little Color Management System +// Copyright (c) 1998-2012 Marti Maria Saguer +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//--------------------------------------------------------------------------------- +// + +#include "lcms2_internal.h" + + +// Allocates an empty multi profile element +cmsStage* CMSEXPORT _cmsStageAllocPlaceholder(cmsContext ContextID, + cmsStageSignature Type, + cmsUInt32Number InputChannels, + cmsUInt32Number OutputChannels, + _cmsStageEvalFn EvalPtr, + _cmsStageDupElemFn DupElemPtr, + _cmsStageFreeElemFn FreePtr, + void* Data) +{ + cmsStage* ph = (cmsStage*) _cmsMallocZero(ContextID, sizeof(cmsStage)); + + if (ph == NULL) return NULL; + + + ph ->ContextID = ContextID; + + ph ->Type = Type; + ph ->Implements = Type; // By default, no clue on what is implementing + + ph ->InputChannels = InputChannels; + ph ->OutputChannels = OutputChannels; + ph ->EvalPtr = EvalPtr; + ph ->DupElemPtr = DupElemPtr; + ph ->FreePtr = FreePtr; + ph ->Data = Data; + + return ph; +} + + +static +void EvaluateIdentity(const cmsFloat32Number In[], + cmsFloat32Number Out[], + const cmsStage *mpe) +{ + memmove(Out, In, mpe ->InputChannels * sizeof(cmsFloat32Number)); +} + + +cmsStage* CMSEXPORT cmsStageAllocIdentity(cmsContext ContextID, cmsUInt32Number nChannels) +{ + return _cmsStageAllocPlaceholder(ContextID, + cmsSigIdentityElemType, + nChannels, nChannels, + EvaluateIdentity, + NULL, + NULL, + NULL); + } + +// Conversion functions. From floating point to 16 bits +static +void FromFloatTo16(const cmsFloat32Number In[], cmsUInt16Number Out[], cmsUInt32Number n) +{ + cmsUInt32Number i; + + for (i=0; i < n; i++) { + Out[i] = _cmsQuickSaturateWord(In[i] * 65535.0); + } +} + +// From 16 bits to floating point +static +void From16ToFloat(const cmsUInt16Number In[], cmsFloat32Number Out[], cmsUInt32Number n) +{ + cmsUInt32Number i; + + for (i=0; i < n; i++) { + Out[i] = (cmsFloat32Number) In[i] / 65535.0F; + } +} + + +// This function is quite useful to analyze the structure of a LUT and retrieve the MPE elements +// that conform the LUT. It should be called with the LUT, the number of expected elements and +// then a list of expected types followed with a list of cmsFloat64Number pointers to MPE elements. If +// the function founds a match with current pipeline, it fills the pointers and returns TRUE +// if not, returns FALSE without touching anything. Setting pointers to NULL does bypass +// the storage process. +cmsBool CMSEXPORT cmsPipelineCheckAndRetreiveStages(const cmsPipeline* Lut, cmsUInt32Number n, ...) +{ + va_list args; + cmsUInt32Number i; + cmsStage* mpe; + cmsStageSignature Type; + void** ElemPtr; + + // Make sure same number of elements + if (cmsPipelineStageCount(Lut) != n) return FALSE; + + va_start(args, n); + + // Iterate across asked types + mpe = Lut ->Elements; + for (i=0; i < n; i++) { + + // Get asked type + Type = (cmsStageSignature)va_arg(args, cmsStageSignature); + if (mpe ->Type != Type) { + + va_end(args); // Mismatch. We are done. + return FALSE; + } + mpe = mpe ->Next; + } + + // Found a combination, fill pointers if not NULL + mpe = Lut ->Elements; + for (i=0; i < n; i++) { + + ElemPtr = va_arg(args, void**); + if (ElemPtr != NULL) + *ElemPtr = mpe; + + mpe = mpe ->Next; + } + + va_end(args); + return TRUE; +} + +// Below there are implementations for several types of elements. Each type may be implemented by a +// evaluation function, a duplication function, a function to free resources and a constructor. + +// ************************************************************************************************* +// Type cmsSigCurveSetElemType (curves) +// ************************************************************************************************* + +cmsToneCurve** _cmsStageGetPtrToCurveSet(const cmsStage* mpe) +{ + _cmsStageToneCurvesData* Data = (_cmsStageToneCurvesData*) mpe ->Data; + + return Data ->TheCurves; +} + +static +void EvaluateCurves(const cmsFloat32Number In[], + cmsFloat32Number Out[], + const cmsStage *mpe) +{ + _cmsStageToneCurvesData* Data; + cmsUInt32Number i; + + _cmsAssert(mpe != NULL); + + Data = (_cmsStageToneCurvesData*) mpe ->Data; + if (Data == NULL) return; + + if (Data ->TheCurves == NULL) return; + + for (i=0; i < Data ->nCurves; i++) { + Out[i] = cmsEvalToneCurveFloat(Data ->TheCurves[i], In[i]); + } +} + +static +void CurveSetElemTypeFree(cmsStage* mpe) +{ + _cmsStageToneCurvesData* Data; + cmsUInt32Number i; + + _cmsAssert(mpe != NULL); + + Data = (_cmsStageToneCurvesData*) mpe ->Data; + if (Data == NULL) return; + + if (Data ->TheCurves != NULL) { + for (i=0; i < Data ->nCurves; i++) { + if (Data ->TheCurves[i] != NULL) + cmsFreeToneCurve(Data ->TheCurves[i]); + } + } + _cmsFree(mpe ->ContextID, Data ->TheCurves); + _cmsFree(mpe ->ContextID, Data); +} + + +static +void* CurveSetDup(cmsStage* mpe) +{ + _cmsStageToneCurvesData* Data = (_cmsStageToneCurvesData*) mpe ->Data; + _cmsStageToneCurvesData* NewElem; + cmsUInt32Number i; + + NewElem = (_cmsStageToneCurvesData*) _cmsMallocZero(mpe ->ContextID, sizeof(_cmsStageToneCurvesData)); + if (NewElem == NULL) return NULL; + + NewElem ->nCurves = Data ->nCurves; + NewElem ->TheCurves = (cmsToneCurve**) _cmsCalloc(mpe ->ContextID, NewElem ->nCurves, sizeof(cmsToneCurve*)); + + if (NewElem ->TheCurves == NULL) goto Error; + + for (i=0; i < NewElem ->nCurves; i++) { + + // Duplicate each curve. It may fail. + NewElem ->TheCurves[i] = cmsDupToneCurve(Data ->TheCurves[i]); + if (NewElem ->TheCurves[i] == NULL) goto Error; + + + } + return (void*) NewElem; + +Error: + + if (NewElem ->TheCurves != NULL) { + for (i=0; i < NewElem ->nCurves; i++) { + if (NewElem ->TheCurves[i]) + cmsFreeToneCurve(NewElem ->TheCurves[i]); + } + } + _cmsFree(mpe ->ContextID, NewElem ->TheCurves); + _cmsFree(mpe ->ContextID, NewElem); + return NULL; +} + + +// Curves == NULL forces identity curves +cmsStage* CMSEXPORT cmsStageAllocToneCurves(cmsContext ContextID, cmsUInt32Number nChannels, cmsToneCurve* const Curves[]) +{ + cmsUInt32Number i; + _cmsStageToneCurvesData* NewElem; + cmsStage* NewMPE; + + + NewMPE = _cmsStageAllocPlaceholder(ContextID, cmsSigCurveSetElemType, nChannels, nChannels, + EvaluateCurves, CurveSetDup, CurveSetElemTypeFree, NULL ); + if (NewMPE == NULL) return NULL; + + NewElem = (_cmsStageToneCurvesData*) _cmsMallocZero(ContextID, sizeof(_cmsStageToneCurvesData)); + if (NewElem == NULL) { + cmsStageFree(NewMPE); + return NULL; + } + + NewMPE ->Data = (void*) NewElem; + + NewElem ->nCurves = nChannels; + NewElem ->TheCurves = (cmsToneCurve**) _cmsCalloc(ContextID, nChannels, sizeof(cmsToneCurve*)); + if (NewElem ->TheCurves == NULL) { + cmsStageFree(NewMPE); + return NULL; + } + + for (i=0; i < nChannels; i++) { + + if (Curves == NULL) { + NewElem ->TheCurves[i] = cmsBuildGamma(ContextID, 1.0); + } + else { + NewElem ->TheCurves[i] = cmsDupToneCurve(Curves[i]); + } + + if (NewElem ->TheCurves[i] == NULL) { + cmsStageFree(NewMPE); + return NULL; + } + + } + + return NewMPE; +} + + +// Create a bunch of identity curves +cmsStage* _cmsStageAllocIdentityCurves(cmsContext ContextID, int nChannels) +{ + cmsStage* mpe = cmsStageAllocToneCurves(ContextID, nChannels, NULL); + + if (mpe == NULL) return NULL; + mpe ->Implements = cmsSigIdentityElemType; + return mpe; +} + + +// ************************************************************************************************* +// Type cmsSigMatrixElemType (Matrices) +// ************************************************************************************************* + + +// Special care should be taken here because precision loss. A temporary cmsFloat64Number buffer is being used +static +void EvaluateMatrix(const cmsFloat32Number In[], + cmsFloat32Number Out[], + const cmsStage *mpe) +{ + cmsUInt32Number i, j; + _cmsStageMatrixData* Data = (_cmsStageMatrixData*) mpe ->Data; + cmsFloat64Number Tmp; + + // Input is already in 0..1.0 notation + for (i=0; i < mpe ->OutputChannels; i++) { + + Tmp = 0; + for (j=0; j < mpe->InputChannels; j++) { + Tmp += In[j] * Data->Double[i*mpe->InputChannels + j]; + } + + if (Data ->Offset != NULL) + Tmp += Data->Offset[i]; + + Out[i] = (cmsFloat32Number) Tmp; + } + + + // Output in 0..1.0 domain +} + + +// Duplicate a yet-existing matrix element +static +void* MatrixElemDup(cmsStage* mpe) +{ + _cmsStageMatrixData* Data = (_cmsStageMatrixData*) mpe ->Data; + _cmsStageMatrixData* NewElem; + cmsUInt32Number sz; + + NewElem = (_cmsStageMatrixData*) _cmsMallocZero(mpe ->ContextID, sizeof(_cmsStageMatrixData)); + if (NewElem == NULL) return NULL; + + sz = mpe ->InputChannels * mpe ->OutputChannels; + + NewElem ->Double = (cmsFloat64Number*) _cmsDupMem(mpe ->ContextID, Data ->Double, sz * sizeof(cmsFloat64Number)) ; + + if (Data ->Offset) + NewElem ->Offset = (cmsFloat64Number*) _cmsDupMem(mpe ->ContextID, + Data ->Offset, mpe -> OutputChannels * sizeof(cmsFloat64Number)) ; + + return (void*) NewElem; +} + + +static +void MatrixElemTypeFree(cmsStage* mpe) +{ + _cmsStageMatrixData* Data = (_cmsStageMatrixData*) mpe ->Data; + if (Data == NULL) + return; + if (Data ->Double) + _cmsFree(mpe ->ContextID, Data ->Double); + + if (Data ->Offset) + _cmsFree(mpe ->ContextID, Data ->Offset); + + _cmsFree(mpe ->ContextID, mpe ->Data); +} + + + +cmsStage* CMSEXPORT cmsStageAllocMatrix(cmsContext ContextID, cmsUInt32Number Rows, cmsUInt32Number Cols, + const cmsFloat64Number* Matrix, const cmsFloat64Number* Offset) +{ + cmsUInt32Number i, n; + _cmsStageMatrixData* NewElem; + cmsStage* NewMPE; + + n = Rows * Cols; + + // Check for overflow + if (n == 0) return NULL; + if (n >= UINT_MAX / Cols) return NULL; + if (n >= UINT_MAX / Rows) return NULL; + if (n < Rows || n < Cols) return NULL; + + NewMPE = _cmsStageAllocPlaceholder(ContextID, cmsSigMatrixElemType, Cols, Rows, + EvaluateMatrix, MatrixElemDup, MatrixElemTypeFree, NULL ); + if (NewMPE == NULL) return NULL; + + + NewElem = (_cmsStageMatrixData*) _cmsMallocZero(ContextID, sizeof(_cmsStageMatrixData)); + if (NewElem == NULL) return NULL; + + + NewElem ->Double = (cmsFloat64Number*) _cmsCalloc(ContextID, n, sizeof(cmsFloat64Number)); + + if (NewElem->Double == NULL) { + MatrixElemTypeFree(NewMPE); + return NULL; + } + + for (i=0; i < n; i++) { + NewElem ->Double[i] = Matrix[i]; + } + + + if (Offset != NULL) { + + NewElem ->Offset = (cmsFloat64Number*) _cmsCalloc(ContextID, Cols, sizeof(cmsFloat64Number)); + if (NewElem->Offset == NULL) { + MatrixElemTypeFree(NewMPE); + return NULL; + } + + for (i=0; i < Cols; i++) { + NewElem ->Offset[i] = Offset[i]; + } + + } + + NewMPE ->Data = (void*) NewElem; + return NewMPE; +} + + +// ************************************************************************************************* +// Type cmsSigCLutElemType +// ************************************************************************************************* + + +// Evaluate in true floating point +static +void EvaluateCLUTfloat(const cmsFloat32Number In[], cmsFloat32Number Out[], const cmsStage *mpe) +{ + _cmsStageCLutData* Data = (_cmsStageCLutData*) mpe ->Data; + + Data -> Params ->Interpolation.LerpFloat(In, Out, Data->Params); +} + + +// Convert to 16 bits, evaluate, and back to floating point +static +void EvaluateCLUTfloatIn16(const cmsFloat32Number In[], cmsFloat32Number Out[], const cmsStage *mpe) +{ + _cmsStageCLutData* Data = (_cmsStageCLutData*) mpe ->Data; + cmsUInt16Number In16[MAX_STAGE_CHANNELS], Out16[MAX_STAGE_CHANNELS]; + + _cmsAssert(mpe ->InputChannels <= MAX_STAGE_CHANNELS); + _cmsAssert(mpe ->OutputChannels <= MAX_STAGE_CHANNELS); + + FromFloatTo16(In, In16, mpe ->InputChannels); + Data -> Params ->Interpolation.Lerp16(In16, Out16, Data->Params); + From16ToFloat(Out16, Out, mpe ->OutputChannels); +} + + +// Given an hypercube of b dimensions, with Dims[] number of nodes by dimension, calculate the total amount of nodes +static +cmsUInt32Number CubeSize(const cmsUInt32Number Dims[], cmsUInt32Number b) +{ + cmsUInt32Number rv, dim; + + _cmsAssert(Dims != NULL); + + for (rv = 1; b > 0; b--) { + + dim = Dims[b-1]; + if (dim == 0) return 0; // Error + + rv *= dim; + + // Check for overflow + if (rv > UINT_MAX / dim) return 0; + } + + return rv; +} + +static +void* CLUTElemDup(cmsStage* mpe) +{ + _cmsStageCLutData* Data = (_cmsStageCLutData*) mpe ->Data; + _cmsStageCLutData* NewElem; + + + NewElem = (_cmsStageCLutData*) _cmsMallocZero(mpe ->ContextID, sizeof(_cmsStageCLutData)); + if (NewElem == NULL) return NULL; + + NewElem ->nEntries = Data ->nEntries; + NewElem ->HasFloatValues = Data ->HasFloatValues; + + if (Data ->Tab.T) { + + if (Data ->HasFloatValues) { + NewElem ->Tab.TFloat = (cmsFloat32Number*) _cmsDupMem(mpe ->ContextID, Data ->Tab.TFloat, Data ->nEntries * sizeof (cmsFloat32Number)); + if (NewElem ->Tab.TFloat == NULL) + goto Error; + } else { + NewElem ->Tab.T = (cmsUInt16Number*) _cmsDupMem(mpe ->ContextID, Data ->Tab.T, Data ->nEntries * sizeof (cmsUInt16Number)); + if (NewElem ->Tab.TFloat == NULL) + goto Error; + } + } + + NewElem ->Params = _cmsComputeInterpParamsEx(mpe ->ContextID, + Data ->Params ->nSamples, + Data ->Params ->nInputs, + Data ->Params ->nOutputs, + NewElem ->Tab.T, + Data ->Params ->dwFlags); + if (NewElem->Params != NULL) + return (void*) NewElem; + Error: + if (NewElem->Tab.T) + // This works for both types + _cmsFree(mpe ->ContextID, NewElem -> Tab.T); + _cmsFree(mpe ->ContextID, NewElem); + return NULL; +} + + +static +void CLutElemTypeFree(cmsStage* mpe) +{ + + _cmsStageCLutData* Data = (_cmsStageCLutData*) mpe ->Data; + + // Already empty + if (Data == NULL) return; + + // This works for both types + if (Data -> Tab.T) + _cmsFree(mpe ->ContextID, Data -> Tab.T); + + _cmsFreeInterpParams(Data ->Params); + _cmsFree(mpe ->ContextID, mpe ->Data); +} + + +// Allocates a 16-bit multidimensional CLUT. This is evaluated at 16-bit precision. Table may have different +// granularity on each dimension. +cmsStage* CMSEXPORT cmsStageAllocCLut16bitGranular(cmsContext ContextID, + const cmsUInt32Number clutPoints[], + cmsUInt32Number inputChan, + cmsUInt32Number outputChan, + const cmsUInt16Number* Table) +{ + cmsUInt32Number i, n; + _cmsStageCLutData* NewElem; + cmsStage* NewMPE; + + _cmsAssert(clutPoints != NULL); + + if (inputChan > MAX_INPUT_DIMENSIONS) { + cmsSignalError(ContextID, cmsERROR_RANGE, "Too many input channels (%d channels, max=%d)", inputChan, MAX_INPUT_DIMENSIONS); + return NULL; + } + + NewMPE = _cmsStageAllocPlaceholder(ContextID, cmsSigCLutElemType, inputChan, outputChan, + EvaluateCLUTfloatIn16, CLUTElemDup, CLutElemTypeFree, NULL ); + + if (NewMPE == NULL) return NULL; + + NewElem = (_cmsStageCLutData*) _cmsMallocZero(ContextID, sizeof(_cmsStageCLutData)); + if (NewElem == NULL) { + cmsStageFree(NewMPE); + return NULL; + } + + NewMPE ->Data = (void*) NewElem; + + NewElem -> nEntries = n = outputChan * CubeSize(clutPoints, inputChan); + NewElem -> HasFloatValues = FALSE; + + if (n == 0) { + cmsStageFree(NewMPE); + return NULL; + } + + + NewElem ->Tab.T = (cmsUInt16Number*) _cmsCalloc(ContextID, n, sizeof(cmsUInt16Number)); + if (NewElem ->Tab.T == NULL) { + cmsStageFree(NewMPE); + return NULL; + } + + if (Table != NULL) { + for (i=0; i < n; i++) { + NewElem ->Tab.T[i] = Table[i]; + } + } + + NewElem ->Params = _cmsComputeInterpParamsEx(ContextID, clutPoints, inputChan, outputChan, NewElem ->Tab.T, CMS_LERP_FLAGS_16BITS); + if (NewElem ->Params == NULL) { + cmsStageFree(NewMPE); + return NULL; + } + + return NewMPE; +} + +cmsStage* CMSEXPORT cmsStageAllocCLut16bit(cmsContext ContextID, + cmsUInt32Number nGridPoints, + cmsUInt32Number inputChan, + cmsUInt32Number outputChan, + const cmsUInt16Number* Table) +{ + cmsUInt32Number Dimensions[MAX_INPUT_DIMENSIONS]; + int i; + + // Our resulting LUT would be same gridpoints on all dimensions + for (i=0; i < MAX_INPUT_DIMENSIONS; i++) + Dimensions[i] = nGridPoints; + + return cmsStageAllocCLut16bitGranular(ContextID, Dimensions, inputChan, outputChan, Table); +} + + +cmsStage* CMSEXPORT cmsStageAllocCLutFloat(cmsContext ContextID, + cmsUInt32Number nGridPoints, + cmsUInt32Number inputChan, + cmsUInt32Number outputChan, + const cmsFloat32Number* Table) +{ + cmsUInt32Number Dimensions[MAX_INPUT_DIMENSIONS]; + int i; + + // Our resulting LUT would be same gridpoints on all dimensions + for (i=0; i < MAX_INPUT_DIMENSIONS; i++) + Dimensions[i] = nGridPoints; + + return cmsStageAllocCLutFloatGranular(ContextID, Dimensions, inputChan, outputChan, Table); +} + + + +cmsStage* CMSEXPORT cmsStageAllocCLutFloatGranular(cmsContext ContextID, const cmsUInt32Number clutPoints[], cmsUInt32Number inputChan, cmsUInt32Number outputChan, const cmsFloat32Number* Table) +{ + cmsUInt32Number i, n; + _cmsStageCLutData* NewElem; + cmsStage* NewMPE; + + _cmsAssert(clutPoints != NULL); + + if (inputChan > MAX_INPUT_DIMENSIONS) { + cmsSignalError(ContextID, cmsERROR_RANGE, "Too many input channels (%d channels, max=%d)", inputChan, MAX_INPUT_DIMENSIONS); + return NULL; + } + + NewMPE = _cmsStageAllocPlaceholder(ContextID, cmsSigCLutElemType, inputChan, outputChan, + EvaluateCLUTfloat, CLUTElemDup, CLutElemTypeFree, NULL); + if (NewMPE == NULL) return NULL; + + + NewElem = (_cmsStageCLutData*) _cmsMallocZero(ContextID, sizeof(_cmsStageCLutData)); + if (NewElem == NULL) { + cmsStageFree(NewMPE); + return NULL; + } + + NewMPE ->Data = (void*) NewElem; + + // There is a potential integer overflow on conputing n and nEntries. + NewElem -> nEntries = n = outputChan * CubeSize(clutPoints, inputChan); + NewElem -> HasFloatValues = TRUE; + + if (n == 0) { + cmsStageFree(NewMPE); + return NULL; + } + + NewElem ->Tab.TFloat = (cmsFloat32Number*) _cmsCalloc(ContextID, n, sizeof(cmsFloat32Number)); + if (NewElem ->Tab.TFloat == NULL) { + cmsStageFree(NewMPE); + return NULL; + } + + if (Table != NULL) { + for (i=0; i < n; i++) { + NewElem ->Tab.TFloat[i] = Table[i]; + } + } + + NewElem ->Params = _cmsComputeInterpParamsEx(ContextID, clutPoints, inputChan, outputChan, NewElem ->Tab.TFloat, CMS_LERP_FLAGS_FLOAT); + if (NewElem ->Params == NULL) { + cmsStageFree(NewMPE); + return NULL; + } + + return NewMPE; +} + + +static +int IdentitySampler(register const cmsUInt16Number In[], register cmsUInt16Number Out[], register void * Cargo) +{ + int nChan = *(int*) Cargo; + int i; + + for (i=0; i < nChan; i++) + Out[i] = In[i]; + + return 1; +} + +// Creates an MPE that just copies input to output +cmsStage* _cmsStageAllocIdentityCLut(cmsContext ContextID, int nChan) +{ + cmsUInt32Number Dimensions[MAX_INPUT_DIMENSIONS]; + cmsStage* mpe ; + int i; + + for (i=0; i < MAX_INPUT_DIMENSIONS; i++) + Dimensions[i] = 2; + + mpe = cmsStageAllocCLut16bitGranular(ContextID, Dimensions, nChan, nChan, NULL); + if (mpe == NULL) return NULL; + + if (!cmsStageSampleCLut16bit(mpe, IdentitySampler, &nChan, 0)) { + cmsStageFree(mpe); + return NULL; + } + + mpe ->Implements = cmsSigIdentityElemType; + return mpe; +} + + + +// Quantize a value 0 <= i < MaxSamples to 0..0xffff +cmsUInt16Number _cmsQuantizeVal(cmsFloat64Number i, int MaxSamples) +{ + cmsFloat64Number x; + + x = ((cmsFloat64Number) i * 65535.) / (cmsFloat64Number) (MaxSamples - 1); + return _cmsQuickSaturateWord(x); +} + + +// This routine does a sweep on whole input space, and calls its callback +// function on knots. returns TRUE if all ok, FALSE otherwise. +cmsBool CMSEXPORT cmsStageSampleCLut16bit(cmsStage* mpe, cmsSAMPLER16 Sampler, void * Cargo, cmsUInt32Number dwFlags) +{ + int i, t, nTotalPoints, index, rest; + int nInputs, nOutputs; + cmsUInt32Number* nSamples; + cmsUInt16Number In[MAX_INPUT_DIMENSIONS+1], Out[MAX_STAGE_CHANNELS]; + _cmsStageCLutData* clut; + + if (mpe == NULL) return FALSE; + + clut = (_cmsStageCLutData*) mpe->Data; + + if (clut == NULL) return FALSE; + + nSamples = clut->Params ->nSamples; + nInputs = clut->Params ->nInputs; + nOutputs = clut->Params ->nOutputs; + + if (nInputs <= 0) return FALSE; + if (nOutputs <= 0) return FALSE; + if (nInputs > MAX_INPUT_DIMENSIONS) return FALSE; + if (nOutputs >= MAX_STAGE_CHANNELS) return FALSE; + + nTotalPoints = CubeSize(nSamples, nInputs); + if (nTotalPoints == 0) return FALSE; + + index = 0; + for (i = 0; i < nTotalPoints; i++) { + + rest = i; + for (t = nInputs-1; t >=0; --t) { + + cmsUInt32Number Colorant = rest % nSamples[t]; + + rest /= nSamples[t]; + + In[t] = _cmsQuantizeVal(Colorant, nSamples[t]); + } + + if (clut ->Tab.T != NULL) { + for (t=0; t < nOutputs; t++) + Out[t] = clut->Tab.T[index + t]; + } + + if (!Sampler(In, Out, Cargo)) + return FALSE; + + if (!(dwFlags & SAMPLER_INSPECT)) { + + if (clut ->Tab.T != NULL) { + for (t=0; t < nOutputs; t++) + clut->Tab.T[index + t] = Out[t]; + } + } + + index += nOutputs; + } + + return TRUE; +} + +// Same as anterior, but for floting point +cmsBool CMSEXPORT cmsStageSampleCLutFloat(cmsStage* mpe, cmsSAMPLERFLOAT Sampler, void * Cargo, cmsUInt32Number dwFlags) +{ + int i, t, nTotalPoints, index, rest; + int nInputs, nOutputs; + cmsUInt32Number* nSamples; + cmsFloat32Number In[MAX_INPUT_DIMENSIONS+1], Out[MAX_STAGE_CHANNELS]; + _cmsStageCLutData* clut = (_cmsStageCLutData*) mpe->Data; + + nSamples = clut->Params ->nSamples; + nInputs = clut->Params ->nInputs; + nOutputs = clut->Params ->nOutputs; + + if (nInputs <= 0) return FALSE; + if (nOutputs <= 0) return FALSE; + if (nInputs > MAX_INPUT_DIMENSIONS) return FALSE; + if (nOutputs >= MAX_STAGE_CHANNELS) return FALSE; + + nTotalPoints = CubeSize(nSamples, nInputs); + if (nTotalPoints == 0) return FALSE; + + index = 0; + for (i = 0; i < nTotalPoints; i++) { + + rest = i; + for (t = nInputs-1; t >=0; --t) { + + cmsUInt32Number Colorant = rest % nSamples[t]; + + rest /= nSamples[t]; + + In[t] = (cmsFloat32Number) (_cmsQuantizeVal(Colorant, nSamples[t]) / 65535.0); + } + + if (clut ->Tab.TFloat != NULL) { + for (t=0; t < nOutputs; t++) + Out[t] = clut->Tab.TFloat[index + t]; + } + + if (!Sampler(In, Out, Cargo)) + return FALSE; + + if (!(dwFlags & SAMPLER_INSPECT)) { + + if (clut ->Tab.TFloat != NULL) { + for (t=0; t < nOutputs; t++) + clut->Tab.TFloat[index + t] = Out[t]; + } + } + + index += nOutputs; + } + + return TRUE; +} + + + +// This routine does a sweep on whole input space, and calls its callback +// function on knots. returns TRUE if all ok, FALSE otherwise. +cmsBool CMSEXPORT cmsSliceSpace16(cmsUInt32Number nInputs, const cmsUInt32Number clutPoints[], + cmsSAMPLER16 Sampler, void * Cargo) +{ + int i, t, nTotalPoints, rest; + cmsUInt16Number In[cmsMAXCHANNELS]; + + if (nInputs >= cmsMAXCHANNELS) return FALSE; + + nTotalPoints = CubeSize(clutPoints, nInputs); + if (nTotalPoints == 0) return FALSE; + + for (i = 0; i < nTotalPoints; i++) { + + rest = i; + for (t = nInputs-1; t >=0; --t) { + + cmsUInt32Number Colorant = rest % clutPoints[t]; + + rest /= clutPoints[t]; + In[t] = _cmsQuantizeVal(Colorant, clutPoints[t]); + + } + + if (!Sampler(In, NULL, Cargo)) + return FALSE; + } + + return TRUE; +} + +cmsInt32Number CMSEXPORT cmsSliceSpaceFloat(cmsUInt32Number nInputs, const cmsUInt32Number clutPoints[], + cmsSAMPLERFLOAT Sampler, void * Cargo) +{ + int i, t, nTotalPoints, rest; + cmsFloat32Number In[cmsMAXCHANNELS]; + + if (nInputs >= cmsMAXCHANNELS) return FALSE; + + nTotalPoints = CubeSize(clutPoints, nInputs); + if (nTotalPoints == 0) return FALSE; + + for (i = 0; i < nTotalPoints; i++) { + + rest = i; + for (t = nInputs-1; t >=0; --t) { + + cmsUInt32Number Colorant = rest % clutPoints[t]; + + rest /= clutPoints[t]; + In[t] = (cmsFloat32Number) (_cmsQuantizeVal(Colorant, clutPoints[t]) / 65535.0); + + } + + if (!Sampler(In, NULL, Cargo)) + return FALSE; + } + + return TRUE; +} + +// ******************************************************************************** +// Type cmsSigLab2XYZElemType +// ******************************************************************************** + + +static +void EvaluateLab2XYZ(const cmsFloat32Number In[], + cmsFloat32Number Out[], + const cmsStage *mpe) +{ + cmsCIELab Lab; + cmsCIEXYZ XYZ; + const cmsFloat64Number XYZadj = MAX_ENCODEABLE_XYZ; + + // V4 rules + Lab.L = In[0] * 100.0; + Lab.a = In[1] * 255.0 - 128.0; + Lab.b = In[2] * 255.0 - 128.0; + + cmsLab2XYZ(NULL, &XYZ, &Lab); + + // From XYZ, range 0..19997 to 0..1.0, note that 1.99997 comes from 0xffff + // encoded as 1.15 fixed point, so 1 + (32767.0 / 32768.0) + + Out[0] = (cmsFloat32Number) ((cmsFloat64Number) XYZ.X / XYZadj); + Out[1] = (cmsFloat32Number) ((cmsFloat64Number) XYZ.Y / XYZadj); + Out[2] = (cmsFloat32Number) ((cmsFloat64Number) XYZ.Z / XYZadj); + return; + + cmsUNUSED_PARAMETER(mpe); +} + + +// No dup or free routines needed, as the structure has no pointers in it. +cmsStage* _cmsStageAllocLab2XYZ(cmsContext ContextID) +{ + return _cmsStageAllocPlaceholder(ContextID, cmsSigLab2XYZElemType, 3, 3, EvaluateLab2XYZ, NULL, NULL, NULL); +} + +// ******************************************************************************** + +// v2 L=100 is supposed to be placed on 0xFF00. There is no reasonable +// number of gridpoints that would make exact match. However, a prelinearization +// of 258 entries, would map 0xFF00 exactly on entry 257, and this is good to avoid scum dot. +// Almost all what we need but unfortunately, the rest of entries should be scaled by +// (255*257/256) and this is not exact. + +cmsStage* _cmsStageAllocLabV2ToV4curves(cmsContext ContextID) +{ + cmsStage* mpe; + cmsToneCurve* LabTable[3]; + int i, j; + + LabTable[0] = cmsBuildTabulatedToneCurve16(ContextID, 258, NULL); + LabTable[1] = cmsBuildTabulatedToneCurve16(ContextID, 258, NULL); + LabTable[2] = cmsBuildTabulatedToneCurve16(ContextID, 258, NULL); + + for (j=0; j < 3; j++) { + + if (LabTable[j] == NULL) { + cmsFreeToneCurveTriple(LabTable); + return NULL; + } + + // We need to map * (0xffff / 0xff00), thats same as (257 / 256) + // So we can use 258-entry tables to do the trick (i / 257) * (255 * 257) * (257 / 256); + for (i=0; i < 257; i++) { + + LabTable[j]->Table16[i] = (cmsUInt16Number) ((i * 0xffff + 0x80) >> 8); + } + + LabTable[j] ->Table16[257] = 0xffff; + } + + mpe = cmsStageAllocToneCurves(ContextID, 3, LabTable); + cmsFreeToneCurveTriple(LabTable); + + if (mpe == NULL) return NULL; + mpe ->Implements = cmsSigLabV2toV4; + return mpe; +} + +// ******************************************************************************** + +// Matrix-based conversion, which is more accurate, but slower and cannot properly be saved in devicelink profiles +cmsStage* _cmsStageAllocLabV2ToV4(cmsContext ContextID) +{ + static const cmsFloat64Number V2ToV4[] = { 65535.0/65280.0, 0, 0, + 0, 65535.0/65280.0, 0, + 0, 0, 65535.0/65280.0 + }; + + cmsStage *mpe = cmsStageAllocMatrix(ContextID, 3, 3, V2ToV4, NULL); + + if (mpe == NULL) return mpe; + mpe ->Implements = cmsSigLabV2toV4; + return mpe; +} + + +// Reverse direction +cmsStage* _cmsStageAllocLabV4ToV2(cmsContext ContextID) +{ + static const cmsFloat64Number V4ToV2[] = { 65280.0/65535.0, 0, 0, + 0, 65280.0/65535.0, 0, + 0, 0, 65280.0/65535.0 + }; + + cmsStage *mpe = cmsStageAllocMatrix(ContextID, 3, 3, V4ToV2, NULL); + + if (mpe == NULL) return mpe; + mpe ->Implements = cmsSigLabV4toV2; + return mpe; +} + + +// To Lab to float. Note that the MPE gives numbers in normal Lab range +// and we need 0..1.0 range for the formatters +// L* : 0...100 => 0...1.0 (L* / 100) +// ab* : -128..+127 to 0..1 ((ab* + 128) / 255) + +cmsStage* _cmsStageNormalizeFromLabFloat(cmsContext ContextID) +{ + static const cmsFloat64Number a1[] = { + 1.0/100.0, 0, 0, + 0, 1.0/255.0, 0, + 0, 0, 1.0/255.0 + }; + + static const cmsFloat64Number o1[] = { + 0, + 128.0/255.0, + 128.0/255.0 + }; + + cmsStage *mpe = cmsStageAllocMatrix(ContextID, 3, 3, a1, o1); + + if (mpe == NULL) return mpe; + mpe ->Implements = cmsSigLab2FloatPCS; + return mpe; +} + +// Fom XYZ to floating point PCS +cmsStage* _cmsStageNormalizeFromXyzFloat(cmsContext ContextID) +{ +#define n (32768.0/65535.0) + static const cmsFloat64Number a1[] = { + n, 0, 0, + 0, n, 0, + 0, 0, n + }; +#undef n + + cmsStage *mpe = cmsStageAllocMatrix(ContextID, 3, 3, a1, NULL); + + if (mpe == NULL) return mpe; + mpe ->Implements = cmsSigXYZ2FloatPCS; + return mpe; +} + +cmsStage* _cmsStageNormalizeToLabFloat(cmsContext ContextID) +{ + static const cmsFloat64Number a1[] = { + 100.0, 0, 0, + 0, 255.0, 0, + 0, 0, 255.0 + }; + + static const cmsFloat64Number o1[] = { + 0, + -128.0, + -128.0 + }; + + cmsStage *mpe = cmsStageAllocMatrix(ContextID, 3, 3, a1, o1); + if (mpe == NULL) return mpe; + mpe ->Implements = cmsSigFloatPCS2Lab; + return mpe; +} + +cmsStage* _cmsStageNormalizeToXyzFloat(cmsContext ContextID) +{ +#define n (65535.0/32768.0) + + static const cmsFloat64Number a1[] = { + n, 0, 0, + 0, n, 0, + 0, 0, n + }; +#undef n + + cmsStage *mpe = cmsStageAllocMatrix(ContextID, 3, 3, a1, NULL); + if (mpe == NULL) return mpe; + mpe ->Implements = cmsSigFloatPCS2XYZ; + return mpe; +} + + + +// ******************************************************************************** +// Type cmsSigXYZ2LabElemType +// ******************************************************************************** + +static +void EvaluateXYZ2Lab(const cmsFloat32Number In[], cmsFloat32Number Out[], const cmsStage *mpe) +{ + cmsCIELab Lab; + cmsCIEXYZ XYZ; + const cmsFloat64Number XYZadj = MAX_ENCODEABLE_XYZ; + + // From 0..1.0 to XYZ + + XYZ.X = In[0] * XYZadj; + XYZ.Y = In[1] * XYZadj; + XYZ.Z = In[2] * XYZadj; + + cmsXYZ2Lab(NULL, &Lab, &XYZ); + + // From V4 Lab to 0..1.0 + + Out[0] = (cmsFloat32Number) (Lab.L / 100.0); + Out[1] = (cmsFloat32Number) ((Lab.a + 128.0) / 255.0); + Out[2] = (cmsFloat32Number) ((Lab.b + 128.0) / 255.0); + return; + + cmsUNUSED_PARAMETER(mpe); +} + +cmsStage* _cmsStageAllocXYZ2Lab(cmsContext ContextID) +{ + return _cmsStageAllocPlaceholder(ContextID, cmsSigXYZ2LabElemType, 3, 3, EvaluateXYZ2Lab, NULL, NULL, NULL); + +} + +// ******************************************************************************** + +// For v4, S-Shaped curves are placed in a/b axis to increase resolution near gray + +cmsStage* _cmsStageAllocLabPrelin(cmsContext ContextID) +{ + cmsToneCurve* LabTable[3]; + cmsFloat64Number Params[1] = {2.4} ; + + LabTable[0] = cmsBuildGamma(ContextID, 1.0); + LabTable[1] = cmsBuildParametricToneCurve(ContextID, 108, Params); + LabTable[2] = cmsBuildParametricToneCurve(ContextID, 108, Params); + + return cmsStageAllocToneCurves(ContextID, 3, LabTable); +} + + +// Free a single MPE +void CMSEXPORT cmsStageFree(cmsStage* mpe) +{ + if (mpe ->FreePtr) + mpe ->FreePtr(mpe); + + _cmsFree(mpe ->ContextID, mpe); +} + + +cmsUInt32Number CMSEXPORT cmsStageInputChannels(const cmsStage* mpe) +{ + return mpe ->InputChannels; +} + +cmsUInt32Number CMSEXPORT cmsStageOutputChannels(const cmsStage* mpe) +{ + return mpe ->OutputChannels; +} + +cmsStageSignature CMSEXPORT cmsStageType(const cmsStage* mpe) +{ + return mpe -> Type; +} + +void* CMSEXPORT cmsStageData(const cmsStage* mpe) +{ + return mpe -> Data; +} + +cmsStage* CMSEXPORT cmsStageNext(const cmsStage* mpe) +{ + return mpe -> Next; +} + + +// Duplicates an MPE +cmsStage* CMSEXPORT cmsStageDup(cmsStage* mpe) +{ + cmsStage* NewMPE; + + if (mpe == NULL) return NULL; + NewMPE = _cmsStageAllocPlaceholder(mpe ->ContextID, + mpe ->Type, + mpe ->InputChannels, + mpe ->OutputChannels, + mpe ->EvalPtr, + mpe ->DupElemPtr, + mpe ->FreePtr, + NULL); + if (NewMPE == NULL) return NULL; + + NewMPE ->Implements = mpe ->Implements; + + if (mpe ->DupElemPtr) { + + NewMPE ->Data = mpe ->DupElemPtr(mpe); + + if (NewMPE->Data == NULL) { + + cmsStageFree(NewMPE); + return NULL; + } + + } else { + + NewMPE ->Data = NULL; + } + + return NewMPE; +} + + +// *********************************************************************************************************** + +// This function sets up the channel count + +static +void BlessLUT(cmsPipeline* lut) +{ + // We can set the input/ouput channels only if we have elements. + if (lut ->Elements != NULL) { + + cmsStage *First, *Last; + + First = cmsPipelineGetPtrToFirstStage(lut); + Last = cmsPipelineGetPtrToLastStage(lut); + + if (First != NULL)lut ->InputChannels = First ->InputChannels; + if (Last != NULL) lut ->OutputChannels = Last ->OutputChannels; + } +} + + +// Default to evaluate the LUT on 16 bit-basis. Precision is retained. +static +void _LUTeval16(register const cmsUInt16Number In[], register cmsUInt16Number Out[], register const void* D) +{ + cmsPipeline* lut = (cmsPipeline*) D; + cmsStage *mpe; + cmsFloat32Number Storage[2][MAX_STAGE_CHANNELS]; + int Phase = 0, NextPhase; + + From16ToFloat(In, &Storage[Phase][0], lut ->InputChannels); + + for (mpe = lut ->Elements; + mpe != NULL; + mpe = mpe ->Next) { + + NextPhase = Phase ^ 1; + mpe ->EvalPtr(&Storage[Phase][0], &Storage[NextPhase][0], mpe); + Phase = NextPhase; + } + + + FromFloatTo16(&Storage[Phase][0], Out, lut ->OutputChannels); +} + + + +// Does evaluate the LUT on cmsFloat32Number-basis. +static +void _LUTevalFloat(register const cmsFloat32Number In[], register cmsFloat32Number Out[], const void* D) +{ + cmsPipeline* lut = (cmsPipeline*) D; + cmsStage *mpe; + cmsFloat32Number Storage[2][MAX_STAGE_CHANNELS]; + int Phase = 0, NextPhase; + + memmove(&Storage[Phase][0], In, lut ->InputChannels * sizeof(cmsFloat32Number)); + + for (mpe = lut ->Elements; + mpe != NULL; + mpe = mpe ->Next) { + + NextPhase = Phase ^ 1; + mpe ->EvalPtr(&Storage[Phase][0], &Storage[NextPhase][0], mpe); + Phase = NextPhase; + } + + memmove(Out, &Storage[Phase][0], lut ->OutputChannels * sizeof(cmsFloat32Number)); +} + + + + +// LUT Creation & Destruction + +cmsPipeline* CMSEXPORT cmsPipelineAlloc(cmsContext ContextID, cmsUInt32Number InputChannels, cmsUInt32Number OutputChannels) +{ + cmsPipeline* NewLUT; + + if (InputChannels >= cmsMAXCHANNELS || + OutputChannels >= cmsMAXCHANNELS) return NULL; + + NewLUT = (cmsPipeline*) _cmsMallocZero(ContextID, sizeof(cmsPipeline)); + if (NewLUT == NULL) return NULL; + + + NewLUT -> InputChannels = InputChannels; + NewLUT -> OutputChannels = OutputChannels; + + NewLUT ->Eval16Fn = _LUTeval16; + NewLUT ->EvalFloatFn = _LUTevalFloat; + NewLUT ->DupDataFn = NULL; + NewLUT ->FreeDataFn = NULL; + NewLUT ->Data = NewLUT; + NewLUT ->ContextID = ContextID; + + BlessLUT(NewLUT); + + return NewLUT; +} + +cmsContext CMSEXPORT cmsGetPipelineContextID(const cmsPipeline* lut) +{ + _cmsAssert(lut != NULL); + return lut ->ContextID; +} + +cmsUInt32Number CMSEXPORT cmsPipelineInputChannels(const cmsPipeline* lut) +{ + _cmsAssert(lut != NULL); + return lut ->InputChannels; +} + +cmsUInt32Number CMSEXPORT cmsPipelineOutputChannels(const cmsPipeline* lut) +{ + _cmsAssert(lut != NULL); + return lut ->OutputChannels; +} + +// Free a profile elements LUT +void CMSEXPORT cmsPipelineFree(cmsPipeline* lut) +{ + cmsStage *mpe, *Next; + + if (lut == NULL) return; + + for (mpe = lut ->Elements; + mpe != NULL; + mpe = Next) { + + Next = mpe ->Next; + cmsStageFree(mpe); + } + + if (lut ->FreeDataFn) lut ->FreeDataFn(lut ->ContextID, lut ->Data); + + _cmsFree(lut ->ContextID, lut); +} + + +// Default to evaluate the LUT on 16 bit-basis. +void CMSEXPORT cmsPipelineEval16(const cmsUInt16Number In[], cmsUInt16Number Out[], const cmsPipeline* lut) +{ + _cmsAssert(lut != NULL); + lut ->Eval16Fn(In, Out, lut->Data); +} + + +// Does evaluate the LUT on cmsFloat32Number-basis. +void CMSEXPORT cmsPipelineEvalFloat(const cmsFloat32Number In[], cmsFloat32Number Out[], const cmsPipeline* lut) +{ + _cmsAssert(lut != NULL); + lut ->EvalFloatFn(In, Out, lut); +} + + + +// Duplicates a LUT +cmsPipeline* CMSEXPORT cmsPipelineDup(const cmsPipeline* lut) +{ + cmsPipeline* NewLUT; + cmsStage *NewMPE, *Anterior = NULL, *mpe; + cmsBool First = TRUE; + + if (lut == NULL) return NULL; + + NewLUT = cmsPipelineAlloc(lut ->ContextID, lut ->InputChannels, lut ->OutputChannels); + if (NewLUT == NULL) return NULL; + + for (mpe = lut ->Elements; + mpe != NULL; + mpe = mpe ->Next) { + + NewMPE = cmsStageDup(mpe); + + if (NewMPE == NULL) { + cmsPipelineFree(NewLUT); + return NULL; + } + + if (First) { + NewLUT ->Elements = NewMPE; + First = FALSE; + } + else { + Anterior ->Next = NewMPE; + } + + Anterior = NewMPE; + } + + NewLUT ->Eval16Fn = lut ->Eval16Fn; + NewLUT ->EvalFloatFn = lut ->EvalFloatFn; + NewLUT ->DupDataFn = lut ->DupDataFn; + NewLUT ->FreeDataFn = lut ->FreeDataFn; + + if (NewLUT ->DupDataFn != NULL) + NewLUT ->Data = NewLUT ->DupDataFn(lut ->ContextID, lut->Data); + + + NewLUT ->SaveAs8Bits = lut ->SaveAs8Bits; + + BlessLUT(NewLUT); + return NewLUT; +} + + +int CMSEXPORT cmsPipelineInsertStage(cmsPipeline* lut, cmsStageLoc loc, cmsStage* mpe) +{ + cmsStage* Anterior = NULL, *pt; + + if (lut == NULL || mpe == NULL) + return FALSE; + + switch (loc) { + + case cmsAT_BEGIN: + mpe ->Next = lut ->Elements; + lut ->Elements = mpe; + break; + + case cmsAT_END: + + if (lut ->Elements == NULL) + lut ->Elements = mpe; + else { + + for (pt = lut ->Elements; + pt != NULL; + pt = pt -> Next) Anterior = pt; + + Anterior ->Next = mpe; + mpe ->Next = NULL; + } + break; + default:; + return FALSE; + } + + BlessLUT(lut); + return TRUE; +} + +// Unlink an element and return the pointer to it +void CMSEXPORT cmsPipelineUnlinkStage(cmsPipeline* lut, cmsStageLoc loc, cmsStage** mpe) +{ + cmsStage *Anterior, *pt, *Last; + cmsStage *Unlinked = NULL; + + + // If empty LUT, there is nothing to remove + if (lut ->Elements == NULL) { + if (mpe) *mpe = NULL; + return; + } + + // On depending on the strategy... + switch (loc) { + + case cmsAT_BEGIN: + { + cmsStage* elem = lut ->Elements; + + lut ->Elements = elem -> Next; + elem ->Next = NULL; + Unlinked = elem; + + } + break; + + case cmsAT_END: + Anterior = Last = NULL; + for (pt = lut ->Elements; + pt != NULL; + pt = pt -> Next) { + Anterior = Last; + Last = pt; + } + + Unlinked = Last; // Next already points to NULL + + // Truncate the chain + if (Anterior) + Anterior ->Next = NULL; + else + lut ->Elements = NULL; + break; + default:; + } + + if (mpe) + *mpe = Unlinked; + else + cmsStageFree(Unlinked); + + BlessLUT(lut); +} + + +// Concatenate two LUT into a new single one +cmsBool CMSEXPORT cmsPipelineCat(cmsPipeline* l1, const cmsPipeline* l2) +{ + cmsStage* mpe; + + // If both LUTS does not have elements, we need to inherit + // the number of channels + if (l1 ->Elements == NULL && l2 ->Elements == NULL) { + l1 ->InputChannels = l2 ->InputChannels; + l1 ->OutputChannels = l2 ->OutputChannels; + } + + // Cat second + for (mpe = l2 ->Elements; + mpe != NULL; + mpe = mpe ->Next) { + + // We have to dup each element + if (!cmsPipelineInsertStage(l1, cmsAT_END, cmsStageDup(mpe))) + return FALSE; + } + + BlessLUT(l1); + return TRUE; +} + + +cmsBool CMSEXPORT cmsPipelineSetSaveAs8bitsFlag(cmsPipeline* lut, cmsBool On) +{ + cmsBool Anterior = lut ->SaveAs8Bits; + + lut ->SaveAs8Bits = On; + return Anterior; +} + + +cmsStage* CMSEXPORT cmsPipelineGetPtrToFirstStage(const cmsPipeline* lut) +{ + return lut ->Elements; +} + +cmsStage* CMSEXPORT cmsPipelineGetPtrToLastStage(const cmsPipeline* lut) +{ + cmsStage *mpe, *Anterior = NULL; + + for (mpe = lut ->Elements; mpe != NULL; mpe = mpe ->Next) + Anterior = mpe; + + return Anterior; +} + +cmsUInt32Number CMSEXPORT cmsPipelineStageCount(const cmsPipeline* lut) +{ + cmsStage *mpe; + cmsUInt32Number n; + + for (n=0, mpe = lut ->Elements; mpe != NULL; mpe = mpe ->Next) + n++; + + return n; +} + +// This function may be used to set the optional evaluator and a block of private data. If private data is being used, an optional +// duplicator and free functions should also be specified in order to duplicate the LUT construct. Use NULL to inhibit such functionality. +void CMSEXPORT _cmsPipelineSetOptimizationParameters(cmsPipeline* Lut, + _cmsOPTeval16Fn Eval16, + void* PrivateData, + _cmsFreeUserDataFn FreePrivateDataFn, + _cmsDupUserDataFn DupPrivateDataFn) +{ + + Lut ->Eval16Fn = Eval16; + Lut ->DupDataFn = DupPrivateDataFn; + Lut ->FreeDataFn = FreePrivateDataFn; + Lut ->Data = PrivateData; +} + + +// ----------------------------------------------------------- Reverse interpolation +// Here's how it goes. The derivative Df(x) of the function f is the linear +// transformation that best approximates f near the point x. It can be represented +// by a matrix A whose entries are the partial derivatives of the components of f +// with respect to all the coordinates. This is know as the Jacobian +// +// The best linear approximation to f is given by the matrix equation: +// +// y-y0 = A (x-x0) +// +// So, if x0 is a good "guess" for the zero of f, then solving for the zero of this +// linear approximation will give a "better guess" for the zero of f. Thus let y=0, +// and since y0=f(x0) one can solve the above equation for x. This leads to the +// Newton's method formula: +// +// xn+1 = xn - A-1 f(xn) +// +// where xn+1 denotes the (n+1)-st guess, obtained from the n-th guess xn in the +// fashion described above. Iterating this will give better and better approximations +// if you have a "good enough" initial guess. + + +#define JACOBIAN_EPSILON 0.001f +#define INVERSION_MAX_ITERATIONS 30 + +// Increment with reflexion on boundary +static +void IncDelta(cmsFloat32Number *Val) +{ + if (*Val < (1.0 - JACOBIAN_EPSILON)) + + *Val += JACOBIAN_EPSILON; + + else + *Val -= JACOBIAN_EPSILON; + +} + + + +// Euclidean distance between two vectors of n elements each one +static +cmsFloat32Number EuclideanDistance(cmsFloat32Number a[], cmsFloat32Number b[], int n) +{ + cmsFloat32Number sum = 0; + int i; + + for (i=0; i < n; i++) { + cmsFloat32Number dif = b[i] - a[i]; + sum += dif * dif; + } + + return sqrtf(sum); +} + + +// Evaluate a LUT in reverse direction. It only searches on 3->3 LUT. Uses Newton method +// +// x1 <- x - [J(x)]^-1 * f(x) +// +// lut: The LUT on where to do the search +// Target: LabK, 3 values of Lab plus destination K which is fixed +// Result: The obtained CMYK +// Hint: Location where begin the search + +cmsBool CMSEXPORT cmsPipelineEvalReverseFloat(cmsFloat32Number Target[], + cmsFloat32Number Result[], + cmsFloat32Number Hint[], + const cmsPipeline* lut) +{ + cmsUInt32Number i, j; + cmsFloat64Number error, LastError = 1E20; + cmsFloat32Number fx[4], x[4], xd[4], fxd[4]; + cmsVEC3 tmp, tmp2; + cmsMAT3 Jacobian; + + // Only 3->3 and 4->3 are supported + if (lut ->InputChannels != 3 && lut ->InputChannels != 4) return FALSE; + if (lut ->OutputChannels != 3) return FALSE; + + // Take the hint as starting point if specified + if (Hint == NULL) { + + // Begin at any point, we choose 1/3 of CMY axis + x[0] = x[1] = x[2] = 0.3f; + } + else { + + // Only copy 3 channels from hint... + for (j=0; j < 3; j++) + x[j] = Hint[j]; + } + + // If Lut is 4-dimensions, then grab target[3], which is fixed + if (lut ->InputChannels == 4) { + x[3] = Target[3]; + } + else x[3] = 0; // To keep lint happy + + + // Iterate + for (i = 0; i < INVERSION_MAX_ITERATIONS; i++) { + + // Get beginning fx + cmsPipelineEvalFloat(x, fx, lut); + + // Compute error + error = EuclideanDistance(fx, Target, 3); + + // If not convergent, return last safe value + if (error >= LastError) + break; + + // Keep latest values + LastError = error; + for (j=0; j < lut ->InputChannels; j++) + Result[j] = x[j]; + + // Found an exact match? + if (error <= 0) + break; + + // Obtain slope (the Jacobian) + for (j = 0; j < 3; j++) { + + xd[0] = x[0]; + xd[1] = x[1]; + xd[2] = x[2]; + xd[3] = x[3]; // Keep fixed channel + + IncDelta(&xd[j]); + + cmsPipelineEvalFloat(xd, fxd, lut); + + Jacobian.v[0].n[j] = ((fxd[0] - fx[0]) / JACOBIAN_EPSILON); + Jacobian.v[1].n[j] = ((fxd[1] - fx[1]) / JACOBIAN_EPSILON); + Jacobian.v[2].n[j] = ((fxd[2] - fx[2]) / JACOBIAN_EPSILON); + } + + // Solve system + tmp2.n[0] = fx[0] - Target[0]; + tmp2.n[1] = fx[1] - Target[1]; + tmp2.n[2] = fx[2] - Target[2]; + + if (!_cmsMAT3solve(&tmp, &Jacobian, &tmp2)) + return FALSE; + + // Move our guess + x[0] -= (cmsFloat32Number) tmp.n[0]; + x[1] -= (cmsFloat32Number) tmp.n[1]; + x[2] -= (cmsFloat32Number) tmp.n[2]; + + // Some clipping.... + for (j=0; j < 3; j++) { + if (x[j] < 0) x[j] = 0; + else + if (x[j] > 1.0) x[j] = 1.0; + } + } + + return TRUE; +} + + diff --git a/jni/lcms2-2.5/src/cmsmd5.c b/jni/lcms2-2.5/src/cmsmd5.c new file mode 100644 index 00000000..966730cf --- /dev/null +++ b/jni/lcms2-2.5/src/cmsmd5.c @@ -0,0 +1,317 @@ +//--------------------------------------------------------------------------------- +// +// Little Color Management System +// Copyright (c) 1998-2012 Marti Maria Saguer +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//--------------------------------------------------------------------------------- + + +#include "lcms2_internal.h" + +#ifdef CMS_USE_BIG_ENDIAN + +static +void byteReverse(cmsUInt8Number * buf, cmsUInt32Number longs) +{ + do { + + cmsUInt32Number t = _cmsAdjustEndianess32(*(cmsUInt32Number *) buf); + *(cmsUInt32Number *) buf = t; + buf += sizeof(cmsUInt32Number); + + } while (--longs); + +} + +#else +#define byteReverse(buf, len) +#endif + + +typedef struct { + + cmsUInt32Number buf[4]; + cmsUInt32Number bits[2]; + cmsUInt8Number in[64]; + cmsContext ContextID; + +} _cmsMD5; + +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +#define STEP(f, w, x, y, z, data, s) \ + ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) + + +static +void MD5_Transform(cmsUInt32Number buf[4], cmsUInt32Number in[16]) + +{ + register cmsUInt32Number a, b, c, d; + + a = buf[0]; + b = buf[1]; + c = buf[2]; + d = buf[3]; + + STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); + STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); + STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); + STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); + STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); + STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); + STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); + STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); + STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); + STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); + STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); + STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); + STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); + STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); + STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); + STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); + + STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); + STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); + STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); + STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); + STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); + STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); + STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); + STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); + STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); + STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); + STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); + STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); + STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); + STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); + STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); + STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); + + STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); + STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); + STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); + STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); + STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); + STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); + STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); + STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); + STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); + STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); + STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); + STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); + STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); + STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); + STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); + STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); + + STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); + STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); + STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); + STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); + STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); + STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); + STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); + STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); + STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); + STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); + STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); + STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); + STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); + STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); + STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); + STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + + +// Create a MD5 object +static +cmsHANDLE MD5alloc(cmsContext ContextID) +{ + _cmsMD5* ctx = (_cmsMD5*) _cmsMallocZero(ContextID, sizeof(_cmsMD5)); + if (ctx == NULL) return NULL; + + ctx ->ContextID = ContextID; + + ctx->buf[0] = 0x67452301; + ctx->buf[1] = 0xefcdab89; + ctx->buf[2] = 0x98badcfe; + ctx->buf[3] = 0x10325476; + + ctx->bits[0] = 0; + ctx->bits[1] = 0; + + return (cmsHANDLE) ctx; +} + + +static +void MD5add(cmsHANDLE Handle, cmsUInt8Number* buf, cmsUInt32Number len) +{ + _cmsMD5* ctx = (_cmsMD5*) Handle; + cmsUInt32Number t; + + t = ctx->bits[0]; + if ((ctx->bits[0] = t + (len << 3)) < t) + ctx->bits[1]++; + + ctx->bits[1] += len >> 29; + + t = (t >> 3) & 0x3f; + + if (t) { + + cmsUInt8Number *p = (cmsUInt8Number *) ctx->in + t; + + t = 64 - t; + if (len < t) { + memmove(p, buf, len); + return; + } + + memmove(p, buf, t); + byteReverse(ctx->in, 16); + + MD5_Transform(ctx->buf, (cmsUInt32Number *) ctx->in); + buf += t; + len -= t; + } + + while (len >= 64) { + memmove(ctx->in, buf, 64); + byteReverse(ctx->in, 16); + MD5_Transform(ctx->buf, (cmsUInt32Number *) ctx->in); + buf += 64; + len -= 64; + } + + memmove(ctx->in, buf, len); +} + +// Destroy the object and return the checksum +static +void MD5finish(cmsProfileID* ProfileID, cmsHANDLE Handle) +{ + _cmsMD5* ctx = (_cmsMD5*) Handle; + cmsUInt32Number count; + cmsUInt8Number *p; + + count = (ctx->bits[0] >> 3) & 0x3F; + + p = ctx->in + count; + *p++ = 0x80; + + count = 64 - 1 - count; + + if (count < 8) { + + memset(p, 0, count); + byteReverse(ctx->in, 16); + MD5_Transform(ctx->buf, (cmsUInt32Number *) ctx->in); + + memset(ctx->in, 0, 56); + } else { + memset(p, 0, count - 8); + } + byteReverse(ctx->in, 14); + + ((cmsUInt32Number *) ctx->in)[14] = ctx->bits[0]; + ((cmsUInt32Number *) ctx->in)[15] = ctx->bits[1]; + + MD5_Transform(ctx->buf, (cmsUInt32Number *) ctx->in); + + byteReverse((cmsUInt8Number *) ctx->buf, 4); + memmove(ProfileID ->ID8, ctx->buf, 16); + + _cmsFree(ctx ->ContextID, ctx); +} + + + +// Assuming io points to an ICC profile, compute and store MD5 checksum +// In the header, rendering intentent, attributes and ID should be set to zero +// before computing MD5 checksum (per 6.1.13 in ICC spec) + +cmsBool CMSEXPORT cmsMD5computeID(cmsHPROFILE hProfile) +{ + cmsContext ContextID; + cmsUInt32Number BytesNeeded; + cmsUInt8Number* Mem = NULL; + cmsHANDLE MD5 = NULL; + _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; + _cmsICCPROFILE Keep; + + _cmsAssert(hProfile != NULL); + + ContextID = cmsGetProfileContextID(hProfile); + + // Save a copy of the profile header + memmove(&Keep, Icc, sizeof(_cmsICCPROFILE)); + + // Set RI, attributes and ID + memset(&Icc ->attributes, 0, sizeof(Icc ->attributes)); + Icc ->RenderingIntent = 0; + memset(&Icc ->ProfileID, 0, sizeof(Icc ->ProfileID)); + + // Compute needed storage + if (!cmsSaveProfileToMem(hProfile, NULL, &BytesNeeded)) goto Error; + + // Allocate memory + Mem = (cmsUInt8Number*) _cmsMalloc(ContextID, BytesNeeded); + if (Mem == NULL) goto Error; + + // Save to temporary storage + if (!cmsSaveProfileToMem(hProfile, Mem, &BytesNeeded)) goto Error; + + // Create MD5 object + MD5 = MD5alloc(ContextID); + if (MD5 == NULL) goto Error; + + // Add all bytes + MD5add(MD5, Mem, BytesNeeded); + + // Temp storage is no longer needed + _cmsFree(ContextID, Mem); + + // Restore header + memmove(Icc, &Keep, sizeof(_cmsICCPROFILE)); + + // And store the ID + MD5finish(&Icc ->ProfileID, MD5); + return TRUE; + +Error: + + // Free resources as something went wrong + // "MD5" cannot be other than NULL here, so no need to free it + if (Mem != NULL) _cmsFree(ContextID, Mem); + memmove(Icc, &Keep, sizeof(_cmsICCPROFILE)); + return FALSE; +} + diff --git a/jni/lcms2-2.5/src/cmsmtrx.c b/jni/lcms2-2.5/src/cmsmtrx.c new file mode 100644 index 00000000..583b1ab2 --- /dev/null +++ b/jni/lcms2-2.5/src/cmsmtrx.c @@ -0,0 +1,176 @@ +//--------------------------------------------------------------------------------- +// +// Little Color Management System +// Copyright (c) 1998-2012 Marti Maria Saguer +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//--------------------------------------------------------------------------------- +// + +#include "lcms2_internal.h" + + +#define DSWAP(x, y) {cmsFloat64Number tmp = (x); (x)=(y); (y)=tmp;} + + +// Initiate a vector +void CMSEXPORT _cmsVEC3init(cmsVEC3* r, cmsFloat64Number x, cmsFloat64Number y, cmsFloat64Number z) +{ + r -> n[VX] = x; + r -> n[VY] = y; + r -> n[VZ] = z; +} + +// Vector substraction +void CMSEXPORT _cmsVEC3minus(cmsVEC3* r, const cmsVEC3* a, const cmsVEC3* b) +{ + r -> n[VX] = a -> n[VX] - b -> n[VX]; + r -> n[VY] = a -> n[VY] - b -> n[VY]; + r -> n[VZ] = a -> n[VZ] - b -> n[VZ]; +} + +// Vector cross product +void CMSEXPORT _cmsVEC3cross(cmsVEC3* r, const cmsVEC3* u, const cmsVEC3* v) +{ + r ->n[VX] = u->n[VY] * v->n[VZ] - v->n[VY] * u->n[VZ]; + r ->n[VY] = u->n[VZ] * v->n[VX] - v->n[VZ] * u->n[VX]; + r ->n[VZ] = u->n[VX] * v->n[VY] - v->n[VX] * u->n[VY]; +} + +// Vector dot product +cmsFloat64Number CMSEXPORT _cmsVEC3dot(const cmsVEC3* u, const cmsVEC3* v) +{ + return u->n[VX] * v->n[VX] + u->n[VY] * v->n[VY] + u->n[VZ] * v->n[VZ]; +} + +// Euclidean length +cmsFloat64Number CMSEXPORT _cmsVEC3length(const cmsVEC3* a) +{ + return sqrt(a ->n[VX] * a ->n[VX] + + a ->n[VY] * a ->n[VY] + + a ->n[VZ] * a ->n[VZ]); +} + +// Euclidean distance +cmsFloat64Number CMSEXPORT _cmsVEC3distance(const cmsVEC3* a, const cmsVEC3* b) +{ + cmsFloat64Number d1 = a ->n[VX] - b ->n[VX]; + cmsFloat64Number d2 = a ->n[VY] - b ->n[VY]; + cmsFloat64Number d3 = a ->n[VZ] - b ->n[VZ]; + + return sqrt(d1*d1 + d2*d2 + d3*d3); +} + + + +// 3x3 Identity +void CMSEXPORT _cmsMAT3identity(cmsMAT3* a) +{ + _cmsVEC3init(&a-> v[0], 1.0, 0.0, 0.0); + _cmsVEC3init(&a-> v[1], 0.0, 1.0, 0.0); + _cmsVEC3init(&a-> v[2], 0.0, 0.0, 1.0); +} + +static +cmsBool CloseEnough(cmsFloat64Number a, cmsFloat64Number b) +{ + return fabs(b - a) < (1.0 / 65535.0); +} + + +cmsBool CMSEXPORT _cmsMAT3isIdentity(const cmsMAT3* a) +{ + cmsMAT3 Identity; + int i, j; + + _cmsMAT3identity(&Identity); + + for (i=0; i < 3; i++) + for (j=0; j < 3; j++) + if (!CloseEnough(a ->v[i].n[j], Identity.v[i].n[j])) return FALSE; + + return TRUE; +} + + +// Multiply two matrices +void CMSEXPORT _cmsMAT3per(cmsMAT3* r, const cmsMAT3* a, const cmsMAT3* b) +{ +#define ROWCOL(i, j) \ + a->v[i].n[0]*b->v[0].n[j] + a->v[i].n[1]*b->v[1].n[j] + a->v[i].n[2]*b->v[2].n[j] + + _cmsVEC3init(&r-> v[0], ROWCOL(0,0), ROWCOL(0,1), ROWCOL(0,2)); + _cmsVEC3init(&r-> v[1], ROWCOL(1,0), ROWCOL(1,1), ROWCOL(1,2)); + _cmsVEC3init(&r-> v[2], ROWCOL(2,0), ROWCOL(2,1), ROWCOL(2,2)); + +#undef ROWCOL //(i, j) +} + + + +// Inverse of a matrix b = a^(-1) +cmsBool CMSEXPORT _cmsMAT3inverse(const cmsMAT3* a, cmsMAT3* b) +{ + cmsFloat64Number det, c0, c1, c2; + + c0 = a -> v[1].n[1]*a -> v[2].n[2] - a -> v[1].n[2]*a -> v[2].n[1]; + c1 = -a -> v[1].n[0]*a -> v[2].n[2] + a -> v[1].n[2]*a -> v[2].n[0]; + c2 = a -> v[1].n[0]*a -> v[2].n[1] - a -> v[1].n[1]*a -> v[2].n[0]; + + det = a -> v[0].n[0]*c0 + a -> v[0].n[1]*c1 + a -> v[0].n[2]*c2; + + if (fabs(det) < MATRIX_DET_TOLERANCE) return FALSE; // singular matrix; can't invert + + b -> v[0].n[0] = c0/det; + b -> v[0].n[1] = (a -> v[0].n[2]*a -> v[2].n[1] - a -> v[0].n[1]*a -> v[2].n[2])/det; + b -> v[0].n[2] = (a -> v[0].n[1]*a -> v[1].n[2] - a -> v[0].n[2]*a -> v[1].n[1])/det; + b -> v[1].n[0] = c1/det; + b -> v[1].n[1] = (a -> v[0].n[0]*a -> v[2].n[2] - a -> v[0].n[2]*a -> v[2].n[0])/det; + b -> v[1].n[2] = (a -> v[0].n[2]*a -> v[1].n[0] - a -> v[0].n[0]*a -> v[1].n[2])/det; + b -> v[2].n[0] = c2/det; + b -> v[2].n[1] = (a -> v[0].n[1]*a -> v[2].n[0] - a -> v[0].n[0]*a -> v[2].n[1])/det; + b -> v[2].n[2] = (a -> v[0].n[0]*a -> v[1].n[1] - a -> v[0].n[1]*a -> v[1].n[0])/det; + + return TRUE; +} + + +// Solve a system in the form Ax = b +cmsBool CMSEXPORT _cmsMAT3solve(cmsVEC3* x, cmsMAT3* a, cmsVEC3* b) +{ + cmsMAT3 m, a_1; + + memmove(&m, a, sizeof(cmsMAT3)); + + if (!_cmsMAT3inverse(&m, &a_1)) return FALSE; // Singular matrix + + _cmsMAT3eval(x, &a_1, b); + return TRUE; +} + +// Evaluate a vector across a matrix +void CMSEXPORT _cmsMAT3eval(cmsVEC3* r, const cmsMAT3* a, const cmsVEC3* v) +{ + r->n[VX] = a->v[0].n[VX]*v->n[VX] + a->v[0].n[VY]*v->n[VY] + a->v[0].n[VZ]*v->n[VZ]; + r->n[VY] = a->v[1].n[VX]*v->n[VX] + a->v[1].n[VY]*v->n[VY] + a->v[1].n[VZ]*v->n[VZ]; + r->n[VZ] = a->v[2].n[VX]*v->n[VX] + a->v[2].n[VY]*v->n[VY] + a->v[2].n[VZ]*v->n[VZ]; +} + + diff --git a/jni/lcms2-2.5/src/cmsnamed.c b/jni/lcms2-2.5/src/cmsnamed.c new file mode 100644 index 00000000..acfd1c8c --- /dev/null +++ b/jni/lcms2-2.5/src/cmsnamed.c @@ -0,0 +1,929 @@ +//--------------------------------------------------------------------------------- +// +// Little Color Management System +// Copyright (c) 1998-2012 Marti Maria Saguer +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//--------------------------------------------------------------------------------- +// + +#include "lcms2_internal.h" + +// Multilocalized unicode objects. That is an attempt to encapsulate i18n. + + +// Allocates an empty multi localizad unicode object +cmsMLU* CMSEXPORT cmsMLUalloc(cmsContext ContextID, cmsUInt32Number nItems) +{ + cmsMLU* mlu; + + // nItems should be positive if given + if (nItems <= 0) nItems = 2; + + // Create the container + mlu = (cmsMLU*) _cmsMallocZero(ContextID, sizeof(cmsMLU)); + if (mlu == NULL) return NULL; + + mlu ->ContextID = ContextID; + + // Create entry array + mlu ->Entries = (_cmsMLUentry*) _cmsCalloc(ContextID, nItems, sizeof(_cmsMLUentry)); + if (mlu ->Entries == NULL) { + _cmsFree(ContextID, mlu); + return NULL; + } + + // Ok, keep indexes up to date + mlu ->AllocatedEntries = nItems; + mlu ->UsedEntries = 0; + + return mlu; +} + + +// Grows a mempool table for a MLU. Each time this function is called, mempool size is multiplied times two. +static +cmsBool GrowMLUpool(cmsMLU* mlu) +{ + cmsUInt32Number size; + void *NewPtr; + + // Sanity check + if (mlu == NULL) return FALSE; + + if (mlu ->PoolSize == 0) + size = 256; + else + size = mlu ->PoolSize * 2; + + // Check for overflow + if (size < mlu ->PoolSize) return FALSE; + + // Reallocate the pool + NewPtr = _cmsRealloc(mlu ->ContextID, mlu ->MemPool, size); + if (NewPtr == NULL) return FALSE; + + + mlu ->MemPool = NewPtr; + mlu ->PoolSize = size; + + return TRUE; +} + + +// Grows a entry table for a MLU. Each time this function is called, table size is multiplied times two. +static +cmsBool GrowMLUtable(cmsMLU* mlu) +{ + int AllocatedEntries; + _cmsMLUentry *NewPtr; + + // Sanity check + if (mlu == NULL) return FALSE; + + AllocatedEntries = mlu ->AllocatedEntries * 2; + + // Check for overflow + if (AllocatedEntries / 2 != mlu ->AllocatedEntries) return FALSE; + + // Reallocate the memory + NewPtr = (_cmsMLUentry*)_cmsRealloc(mlu ->ContextID, mlu ->Entries, AllocatedEntries*sizeof(_cmsMLUentry)); + if (NewPtr == NULL) return FALSE; + + mlu ->Entries = NewPtr; + mlu ->AllocatedEntries = AllocatedEntries; + + return TRUE; +} + + +// Search for a specific entry in the structure. Language and Country are used. +static +int SearchMLUEntry(cmsMLU* mlu, cmsUInt16Number LanguageCode, cmsUInt16Number CountryCode) +{ + int i; + + // Sanity check + if (mlu == NULL) return -1; + + // Iterate whole table + for (i=0; i < mlu ->UsedEntries; i++) { + + if (mlu ->Entries[i].Country == CountryCode && + mlu ->Entries[i].Language == LanguageCode) return i; + } + + // Not found + return -1; +} + +// Add a block of characters to the intended MLU. Language and country are specified. +// Only one entry for Language/country pair is allowed. +static +cmsBool AddMLUBlock(cmsMLU* mlu, cmsUInt32Number size, const wchar_t *Block, + cmsUInt16Number LanguageCode, cmsUInt16Number CountryCode) +{ + cmsUInt32Number Offset; + cmsUInt8Number* Ptr; + + // Sanity check + if (mlu == NULL) return FALSE; + + // Is there any room available? + if (mlu ->UsedEntries >= mlu ->AllocatedEntries) { + if (!GrowMLUtable(mlu)) return FALSE; + } + + // Only one ASCII string + if (SearchMLUEntry(mlu, LanguageCode, CountryCode) >= 0) return FALSE; // Only one is allowed! + + // Check for size + while ((mlu ->PoolSize - mlu ->PoolUsed) < size) { + + if (!GrowMLUpool(mlu)) return FALSE; + } + + Offset = mlu ->PoolUsed; + + Ptr = (cmsUInt8Number*) mlu ->MemPool; + if (Ptr == NULL) return FALSE; + + // Set the entry + memmove(Ptr + Offset, Block, size); + mlu ->PoolUsed += size; + + mlu ->Entries[mlu ->UsedEntries].StrW = Offset; + mlu ->Entries[mlu ->UsedEntries].Len = size; + mlu ->Entries[mlu ->UsedEntries].Country = CountryCode; + mlu ->Entries[mlu ->UsedEntries].Language = LanguageCode; + mlu ->UsedEntries++; + + return TRUE; +} + + +// Add an ASCII entry. +cmsBool CMSEXPORT cmsMLUsetASCII(cmsMLU* mlu, const char LanguageCode[3], const char CountryCode[3], const char* ASCIIString) +{ + cmsUInt32Number i, len = (cmsUInt32Number) strlen(ASCIIString)+1; + wchar_t* WStr; + cmsBool rc; + cmsUInt16Number Lang = _cmsAdjustEndianess16(*(cmsUInt16Number*) LanguageCode); + cmsUInt16Number Cntry = _cmsAdjustEndianess16(*(cmsUInt16Number*) CountryCode); + + if (mlu == NULL) return FALSE; + + WStr = (wchar_t*) _cmsCalloc(mlu ->ContextID, len, sizeof(wchar_t)); + if (WStr == NULL) return FALSE; + + for (i=0; i < len; i++) + WStr[i] = (wchar_t) ASCIIString[i]; + + rc = AddMLUBlock(mlu, len * sizeof(wchar_t), WStr, Lang, Cntry); + + _cmsFree(mlu ->ContextID, WStr); + return rc; + +} + +// We don't need any wcs support library +static +cmsUInt32Number mywcslen(const wchar_t *s) +{ + const wchar_t *p; + + p = s; + while (*p) + p++; + + return (cmsUInt32Number)(p - s); +} + + +// Add a wide entry +cmsBool CMSEXPORT cmsMLUsetWide(cmsMLU* mlu, const char Language[3], const char Country[3], const wchar_t* WideString) +{ + cmsUInt16Number Lang = _cmsAdjustEndianess16(*(cmsUInt16Number*) Language); + cmsUInt16Number Cntry = _cmsAdjustEndianess16(*(cmsUInt16Number*) Country); + cmsUInt32Number len; + + if (mlu == NULL) return FALSE; + if (WideString == NULL) return FALSE; + + len = (cmsUInt32Number) (mywcslen(WideString) + 1) * sizeof(wchar_t); + return AddMLUBlock(mlu, len, WideString, Lang, Cntry); +} + +// Duplicating a MLU is as easy as copying all members +cmsMLU* CMSEXPORT cmsMLUdup(const cmsMLU* mlu) +{ + cmsMLU* NewMlu = NULL; + + // Duplicating a NULL obtains a NULL + if (mlu == NULL) return NULL; + + NewMlu = cmsMLUalloc(mlu ->ContextID, mlu ->UsedEntries); + if (NewMlu == NULL) return NULL; + + // Should never happen + if (NewMlu ->AllocatedEntries < mlu ->UsedEntries) + goto Error; + + // Sanitize... + if (NewMlu ->Entries == NULL || mlu ->Entries == NULL) goto Error; + + memmove(NewMlu ->Entries, mlu ->Entries, mlu ->UsedEntries * sizeof(_cmsMLUentry)); + NewMlu ->UsedEntries = mlu ->UsedEntries; + + // The MLU may be empty + if (mlu ->PoolUsed == 0) { + NewMlu ->MemPool = NULL; + } + else { + // It is not empty + NewMlu ->MemPool = _cmsMalloc(mlu ->ContextID, mlu ->PoolUsed); + if (NewMlu ->MemPool == NULL) goto Error; + } + + NewMlu ->PoolSize = mlu ->PoolUsed; + + if (NewMlu ->MemPool == NULL || mlu ->MemPool == NULL) goto Error; + + memmove(NewMlu ->MemPool, mlu->MemPool, mlu ->PoolUsed); + NewMlu ->PoolUsed = mlu ->PoolUsed; + + return NewMlu; + +Error: + + if (NewMlu != NULL) cmsMLUfree(NewMlu); + return NULL; +} + +// Free any used memory +void CMSEXPORT cmsMLUfree(cmsMLU* mlu) +{ + if (mlu) { + + if (mlu -> Entries) _cmsFree(mlu ->ContextID, mlu->Entries); + if (mlu -> MemPool) _cmsFree(mlu ->ContextID, mlu->MemPool); + + _cmsFree(mlu ->ContextID, mlu); + } +} + + +// The algorithm first searches for an exact match of country and language, if not found it uses +// the Language. If none is found, first entry is used instead. +static +const wchar_t* _cmsMLUgetWide(const cmsMLU* mlu, + cmsUInt32Number *len, + cmsUInt16Number LanguageCode, cmsUInt16Number CountryCode, + cmsUInt16Number* UsedLanguageCode, cmsUInt16Number* UsedCountryCode) +{ + int i; + int Best = -1; + _cmsMLUentry* v; + + if (mlu == NULL) return NULL; + + if (mlu -> AllocatedEntries <= 0) return NULL; + + for (i=0; i < mlu ->UsedEntries; i++) { + + v = mlu ->Entries + i; + + if (v -> Language == LanguageCode) { + + if (Best == -1) Best = i; + + if (v -> Country == CountryCode) { + + if (UsedLanguageCode != NULL) *UsedLanguageCode = v ->Language; + if (UsedCountryCode != NULL) *UsedCountryCode = v ->Country; + + if (len != NULL) *len = v ->Len; + + return (wchar_t*) ((cmsUInt8Number*) mlu ->MemPool + v -> StrW); // Found exact match + } + } + } + + // No string found. Return First one + if (Best == -1) + Best = 0; + + v = mlu ->Entries + Best; + + if (UsedLanguageCode != NULL) *UsedLanguageCode = v ->Language; + if (UsedCountryCode != NULL) *UsedCountryCode = v ->Country; + + if (len != NULL) *len = v ->Len; + + return(wchar_t*) ((cmsUInt8Number*) mlu ->MemPool + v ->StrW); +} + + +// Obtain an ASCII representation of the wide string. Setting buffer to NULL returns the len +cmsUInt32Number CMSEXPORT cmsMLUgetASCII(const cmsMLU* mlu, + const char LanguageCode[3], const char CountryCode[3], + char* Buffer, cmsUInt32Number BufferSize) +{ + const wchar_t *Wide; + cmsUInt32Number StrLen = 0; + cmsUInt32Number ASCIIlen, i; + + cmsUInt16Number Lang = _cmsAdjustEndianess16(*(cmsUInt16Number*) LanguageCode); + cmsUInt16Number Cntry = _cmsAdjustEndianess16(*(cmsUInt16Number*) CountryCode); + + // Sanitize + if (mlu == NULL) return 0; + + // Get WideChar + Wide = _cmsMLUgetWide(mlu, &StrLen, Lang, Cntry, NULL, NULL); + if (Wide == NULL) return 0; + + ASCIIlen = StrLen / sizeof(wchar_t); + + // Maybe we want only to know the len? + if (Buffer == NULL) return ASCIIlen + 1; // Note the zero at the end + + // No buffer size means no data + if (BufferSize <= 0) return 0; + + // Some clipping may be required + if (BufferSize < ASCIIlen + 1) + ASCIIlen = BufferSize - 1; + + // Precess each character + for (i=0; i < ASCIIlen; i++) { + + if (Wide[i] == 0) + Buffer[i] = 0; + else + Buffer[i] = (char) Wide[i]; + } + + // We put a termination "\0" + Buffer[ASCIIlen] = 0; + return ASCIIlen + 1; +} + +// Obtain a wide representation of the MLU, on depending on current locale settings +cmsUInt32Number CMSEXPORT cmsMLUgetWide(const cmsMLU* mlu, + const char LanguageCode[3], const char CountryCode[3], + wchar_t* Buffer, cmsUInt32Number BufferSize) +{ + const wchar_t *Wide; + cmsUInt32Number StrLen = 0; + + cmsUInt16Number Lang = _cmsAdjustEndianess16(*(cmsUInt16Number*) LanguageCode); + cmsUInt16Number Cntry = _cmsAdjustEndianess16(*(cmsUInt16Number*) CountryCode); + + // Sanitize + if (mlu == NULL) return 0; + + Wide = _cmsMLUgetWide(mlu, &StrLen, Lang, Cntry, NULL, NULL); + if (Wide == NULL) return 0; + + // Maybe we want only to know the len? + if (Buffer == NULL) return StrLen + sizeof(wchar_t); + + // No buffer size means no data + if (BufferSize <= 0) return 0; + + // Some clipping may be required + if (BufferSize < StrLen + sizeof(wchar_t)) + StrLen = BufferSize - + sizeof(wchar_t); + + memmove(Buffer, Wide, StrLen); + Buffer[StrLen / sizeof(wchar_t)] = 0; + + return StrLen + sizeof(wchar_t); +} + + +// Get also the language and country +CMSAPI cmsBool CMSEXPORT cmsMLUgetTranslation(const cmsMLU* mlu, + const char LanguageCode[3], const char CountryCode[3], + char ObtainedLanguage[3], char ObtainedCountry[3]) +{ + const wchar_t *Wide; + + cmsUInt16Number Lang = _cmsAdjustEndianess16(*(cmsUInt16Number*) LanguageCode); + cmsUInt16Number Cntry = _cmsAdjustEndianess16(*(cmsUInt16Number*) CountryCode); + cmsUInt16Number ObtLang, ObtCode; + + // Sanitize + if (mlu == NULL) return FALSE; + + Wide = _cmsMLUgetWide(mlu, NULL, Lang, Cntry, &ObtLang, &ObtCode); + if (Wide == NULL) return FALSE; + + // Get used language and code + *(cmsUInt16Number *)ObtainedLanguage = _cmsAdjustEndianess16(ObtLang); + *(cmsUInt16Number *)ObtainedCountry = _cmsAdjustEndianess16(ObtCode); + + ObtainedLanguage[2] = ObtainedCountry[2] = 0; + return TRUE; +} + + + +// Get the number of translations in the MLU object +cmsUInt32Number CMSEXPORT cmsMLUtranslationsCount(const cmsMLU* mlu) +{ + if (mlu == NULL) return 0; + return mlu->UsedEntries; +} + +// Get the language and country codes for a specific MLU index +cmsBool CMSEXPORT cmsMLUtranslationsCodes(const cmsMLU* mlu, + cmsUInt32Number idx, + char LanguageCode[3], + char CountryCode[3]) +{ + _cmsMLUentry *entry; + + if (mlu == NULL) return FALSE; + + if (idx >= (cmsUInt32Number) mlu->UsedEntries) return FALSE; + + entry = &mlu->Entries[idx]; + + *(cmsUInt16Number *)LanguageCode = _cmsAdjustEndianess16(entry->Language); + *(cmsUInt16Number *)CountryCode = _cmsAdjustEndianess16(entry->Country); + + return TRUE; +} + + +// Named color lists -------------------------------------------------------------------------------------------- + +// Grow the list to keep at least NumElements +static +cmsBool GrowNamedColorList(cmsNAMEDCOLORLIST* v) +{ + cmsUInt32Number size; + _cmsNAMEDCOLOR * NewPtr; + + if (v == NULL) return FALSE; + + if (v ->Allocated == 0) + size = 64; // Initial guess + else + size = v ->Allocated * 2; + + // Keep a maximum color lists can grow, 100K entries seems reasonable + if (size > 1024*100) return FALSE; + + NewPtr = (_cmsNAMEDCOLOR*) _cmsRealloc(v ->ContextID, v ->List, size * sizeof(_cmsNAMEDCOLOR)); + if (NewPtr == NULL) + return FALSE; + + v ->List = NewPtr; + v ->Allocated = size; + return TRUE; +} + +// Allocate a list for n elements +cmsNAMEDCOLORLIST* CMSEXPORT cmsAllocNamedColorList(cmsContext ContextID, cmsUInt32Number n, cmsUInt32Number ColorantCount, const char* Prefix, const char* Suffix) +{ + cmsNAMEDCOLORLIST* v = (cmsNAMEDCOLORLIST*) _cmsMallocZero(ContextID, sizeof(cmsNAMEDCOLORLIST)); + + if (v == NULL) return NULL; + + v ->List = NULL; + v ->nColors = 0; + v ->ContextID = ContextID; + + while (v -> Allocated < n) + GrowNamedColorList(v); + + strncpy(v ->Prefix, Prefix, sizeof(v ->Prefix)-1); + strncpy(v ->Suffix, Suffix, sizeof(v ->Suffix)-1); + v->Prefix[32] = v->Suffix[32] = 0; + + v -> ColorantCount = ColorantCount; + + return v; +} + +// Free a list +void CMSEXPORT cmsFreeNamedColorList(cmsNAMEDCOLORLIST* v) +{ + if (v == NULL) return; + if (v ->List) _cmsFree(v ->ContextID, v ->List); + _cmsFree(v ->ContextID, v); +} + +cmsNAMEDCOLORLIST* CMSEXPORT cmsDupNamedColorList(const cmsNAMEDCOLORLIST* v) +{ + cmsNAMEDCOLORLIST* NewNC; + + if (v == NULL) return NULL; + + NewNC= cmsAllocNamedColorList(v ->ContextID, v -> nColors, v ->ColorantCount, v ->Prefix, v ->Suffix); + if (NewNC == NULL) return NULL; + + // For really large tables we need this + while (NewNC ->Allocated < v ->Allocated) + GrowNamedColorList(NewNC); + + memmove(NewNC ->Prefix, v ->Prefix, sizeof(v ->Prefix)); + memmove(NewNC ->Suffix, v ->Suffix, sizeof(v ->Suffix)); + NewNC ->ColorantCount = v ->ColorantCount; + memmove(NewNC->List, v ->List, v->nColors * sizeof(_cmsNAMEDCOLOR)); + NewNC ->nColors = v ->nColors; + return NewNC; +} + + +// Append a color to a list. List pointer may change if reallocated +cmsBool CMSEXPORT cmsAppendNamedColor(cmsNAMEDCOLORLIST* NamedColorList, + const char* Name, + cmsUInt16Number PCS[3], cmsUInt16Number Colorant[cmsMAXCHANNELS]) +{ + cmsUInt32Number i; + + if (NamedColorList == NULL) return FALSE; + + if (NamedColorList ->nColors + 1 > NamedColorList ->Allocated) { + if (!GrowNamedColorList(NamedColorList)) return FALSE; + } + + for (i=0; i < NamedColorList ->ColorantCount; i++) + NamedColorList ->List[NamedColorList ->nColors].DeviceColorant[i] = Colorant == NULL? 0 : Colorant[i]; + + for (i=0; i < 3; i++) + NamedColorList ->List[NamedColorList ->nColors].PCS[i] = PCS == NULL ? 0 : PCS[i]; + + if (Name != NULL) { + + strncpy(NamedColorList ->List[NamedColorList ->nColors].Name, Name, cmsMAX_PATH-1); + NamedColorList ->List[NamedColorList ->nColors].Name[cmsMAX_PATH-1] = 0; + + } + else + NamedColorList ->List[NamedColorList ->nColors].Name[0] = 0; + + + NamedColorList ->nColors++; + return TRUE; +} + +// Returns number of elements +cmsUInt32Number CMSEXPORT cmsNamedColorCount(const cmsNAMEDCOLORLIST* NamedColorList) +{ + if (NamedColorList == NULL) return 0; + return NamedColorList ->nColors; +} + +// Info aboout a given color +cmsBool CMSEXPORT cmsNamedColorInfo(const cmsNAMEDCOLORLIST* NamedColorList, cmsUInt32Number nColor, + char* Name, + char* Prefix, + char* Suffix, + cmsUInt16Number* PCS, + cmsUInt16Number* Colorant) +{ + if (NamedColorList == NULL) return FALSE; + + if (nColor >= cmsNamedColorCount(NamedColorList)) return FALSE; + + if (Name) strcpy(Name, NamedColorList->List[nColor].Name); + if (Prefix) strcpy(Prefix, NamedColorList->Prefix); + if (Suffix) strcpy(Suffix, NamedColorList->Suffix); + if (PCS) + memmove(PCS, NamedColorList ->List[nColor].PCS, 3*sizeof(cmsUInt16Number)); + + if (Colorant) + memmove(Colorant, NamedColorList ->List[nColor].DeviceColorant, + sizeof(cmsUInt16Number) * NamedColorList ->ColorantCount); + + + return TRUE; +} + +// Search for a given color name (no prefix or suffix) +cmsInt32Number CMSEXPORT cmsNamedColorIndex(const cmsNAMEDCOLORLIST* NamedColorList, const char* Name) +{ + int i, n; + + if (NamedColorList == NULL) return -1; + n = cmsNamedColorCount(NamedColorList); + for (i=0; i < n; i++) { + if (cmsstrcasecmp(Name, NamedColorList->List[i].Name) == 0) + return i; + } + + return -1; +} + +// MPE support ----------------------------------------------------------------------------------------------------------------- + +static +void FreeNamedColorList(cmsStage* mpe) +{ + cmsNAMEDCOLORLIST* List = (cmsNAMEDCOLORLIST*) mpe ->Data; + cmsFreeNamedColorList(List); +} + +static +void* DupNamedColorList(cmsStage* mpe) +{ + cmsNAMEDCOLORLIST* List = (cmsNAMEDCOLORLIST*) mpe ->Data; + return cmsDupNamedColorList(List); +} + +static +void EvalNamedColorPCS(const cmsFloat32Number In[], cmsFloat32Number Out[], const cmsStage *mpe) +{ + cmsNAMEDCOLORLIST* NamedColorList = (cmsNAMEDCOLORLIST*) mpe ->Data; + cmsUInt16Number index = (cmsUInt16Number) _cmsQuickSaturateWord(In[0] * 65535.0); + + if (index >= NamedColorList-> nColors) { + cmsSignalError(NamedColorList ->ContextID, cmsERROR_RANGE, "Color %d out of range; ignored", index); + } + else { + + // Named color always uses Lab + Out[0] = (cmsFloat32Number) (NamedColorList->List[index].PCS[0] / 65535.0); + Out[1] = (cmsFloat32Number) (NamedColorList->List[index].PCS[1] / 65535.0); + Out[2] = (cmsFloat32Number) (NamedColorList->List[index].PCS[2] / 65535.0); + } +} + +static +void EvalNamedColor(const cmsFloat32Number In[], cmsFloat32Number Out[], const cmsStage *mpe) +{ + cmsNAMEDCOLORLIST* NamedColorList = (cmsNAMEDCOLORLIST*) mpe ->Data; + cmsUInt16Number index = (cmsUInt16Number) _cmsQuickSaturateWord(In[0] * 65535.0); + cmsUInt32Number j; + + if (index >= NamedColorList-> nColors) { + cmsSignalError(NamedColorList ->ContextID, cmsERROR_RANGE, "Color %d out of range; ignored", index); + } + else { + for (j=0; j < NamedColorList ->ColorantCount; j++) + Out[j] = (cmsFloat32Number) (NamedColorList->List[index].DeviceColorant[j] / 65535.0); + } +} + + +// Named color lookup element +cmsStage* _cmsStageAllocNamedColor(cmsNAMEDCOLORLIST* NamedColorList, cmsBool UsePCS) +{ + return _cmsStageAllocPlaceholder(NamedColorList ->ContextID, + cmsSigNamedColorElemType, + 1, UsePCS ? 3 : NamedColorList ->ColorantCount, + UsePCS ? EvalNamedColorPCS : EvalNamedColor, + DupNamedColorList, + FreeNamedColorList, + cmsDupNamedColorList(NamedColorList)); + +} + + +// Retrieve the named color list from a transform. Should be first element in the LUT +cmsNAMEDCOLORLIST* CMSEXPORT cmsGetNamedColorList(cmsHTRANSFORM xform) +{ + _cmsTRANSFORM* v = (_cmsTRANSFORM*) xform; + cmsStage* mpe = v ->Lut->Elements; + + if (mpe ->Type != cmsSigNamedColorElemType) return NULL; + return (cmsNAMEDCOLORLIST*) mpe ->Data; +} + + +// Profile sequence description routines ------------------------------------------------------------------------------------- + +cmsSEQ* CMSEXPORT cmsAllocProfileSequenceDescription(cmsContext ContextID, cmsUInt32Number n) +{ + cmsSEQ* Seq; + cmsUInt32Number i; + + if (n == 0) return NULL; + + // In a absolutely arbitrary way, I hereby decide to allow a maxim of 255 profiles linked + // in a devicelink. It makes not sense anyway and may be used for exploits, so let's close the door! + if (n > 255) return NULL; + + Seq = (cmsSEQ*) _cmsMallocZero(ContextID, sizeof(cmsSEQ)); + if (Seq == NULL) return NULL; + + Seq -> ContextID = ContextID; + Seq -> seq = (cmsPSEQDESC*) _cmsCalloc(ContextID, n, sizeof(cmsPSEQDESC)); + Seq -> n = n; + + if (Seq -> seq == NULL) { + _cmsFree(ContextID, Seq); + return NULL; + } + + for (i=0; i < n; i++) { + Seq -> seq[i].Manufacturer = NULL; + Seq -> seq[i].Model = NULL; + Seq -> seq[i].Description = NULL; + } + + return Seq; +} + +void CMSEXPORT cmsFreeProfileSequenceDescription(cmsSEQ* pseq) +{ + cmsUInt32Number i; + + for (i=0; i < pseq ->n; i++) { + if (pseq ->seq[i].Manufacturer != NULL) cmsMLUfree(pseq ->seq[i].Manufacturer); + if (pseq ->seq[i].Model != NULL) cmsMLUfree(pseq ->seq[i].Model); + if (pseq ->seq[i].Description != NULL) cmsMLUfree(pseq ->seq[i].Description); + } + + if (pseq ->seq != NULL) _cmsFree(pseq ->ContextID, pseq ->seq); + _cmsFree(pseq -> ContextID, pseq); +} + +cmsSEQ* CMSEXPORT cmsDupProfileSequenceDescription(const cmsSEQ* pseq) +{ + cmsSEQ *NewSeq; + cmsUInt32Number i; + + if (pseq == NULL) + return NULL; + + NewSeq = (cmsSEQ*) _cmsMalloc(pseq -> ContextID, sizeof(cmsSEQ)); + if (NewSeq == NULL) return NULL; + + + NewSeq -> seq = (cmsPSEQDESC*) _cmsCalloc(pseq ->ContextID, pseq ->n, sizeof(cmsPSEQDESC)); + if (NewSeq ->seq == NULL) goto Error; + + NewSeq -> ContextID = pseq ->ContextID; + NewSeq -> n = pseq ->n; + + for (i=0; i < pseq->n; i++) { + + memmove(&NewSeq ->seq[i].attributes, &pseq ->seq[i].attributes, sizeof(cmsUInt64Number)); + + NewSeq ->seq[i].deviceMfg = pseq ->seq[i].deviceMfg; + NewSeq ->seq[i].deviceModel = pseq ->seq[i].deviceModel; + memmove(&NewSeq ->seq[i].ProfileID, &pseq ->seq[i].ProfileID, sizeof(cmsProfileID)); + NewSeq ->seq[i].technology = pseq ->seq[i].technology; + + NewSeq ->seq[i].Manufacturer = cmsMLUdup(pseq ->seq[i].Manufacturer); + NewSeq ->seq[i].Model = cmsMLUdup(pseq ->seq[i].Model); + NewSeq ->seq[i].Description = cmsMLUdup(pseq ->seq[i].Description); + + } + + return NewSeq; + +Error: + + cmsFreeProfileSequenceDescription(NewSeq); + return NULL; +} + +// Dictionaries -------------------------------------------------------------------------------------------------------- + +// Dictionaries are just very simple linked lists + + +typedef struct _cmsDICT_struct { + cmsDICTentry* head; + cmsContext ContextID; +} _cmsDICT; + + +// Allocate an empty dictionary +cmsHANDLE CMSEXPORT cmsDictAlloc(cmsContext ContextID) +{ + _cmsDICT* dict = (_cmsDICT*) _cmsMallocZero(ContextID, sizeof(_cmsDICT)); + if (dict == NULL) return NULL; + + dict ->ContextID = ContextID; + return (cmsHANDLE) dict; + +} + +// Dispose resources +void CMSEXPORT cmsDictFree(cmsHANDLE hDict) +{ + _cmsDICT* dict = (_cmsDICT*) hDict; + cmsDICTentry *entry, *next; + + _cmsAssert(dict != NULL); + + // Walk the list freeing all nodes + entry = dict ->head; + while (entry != NULL) { + + if (entry ->DisplayName != NULL) cmsMLUfree(entry ->DisplayName); + if (entry ->DisplayValue != NULL) cmsMLUfree(entry ->DisplayValue); + if (entry ->Name != NULL) _cmsFree(dict ->ContextID, entry -> Name); + if (entry ->Value != NULL) _cmsFree(dict ->ContextID, entry -> Value); + + // Don't fall in the habitual trap... + next = entry ->Next; + _cmsFree(dict ->ContextID, entry); + + entry = next; + } + + _cmsFree(dict ->ContextID, dict); +} + + +// Duplicate a wide char string +static +wchar_t* DupWcs(cmsContext ContextID, const wchar_t* ptr) +{ + if (ptr == NULL) return NULL; + return (wchar_t*) _cmsDupMem(ContextID, ptr, (mywcslen(ptr) + 1) * sizeof(wchar_t)); +} + +// Add a new entry to the linked list +cmsBool CMSEXPORT cmsDictAddEntry(cmsHANDLE hDict, const wchar_t* Name, const wchar_t* Value, const cmsMLU *DisplayName, const cmsMLU *DisplayValue) +{ + _cmsDICT* dict = (_cmsDICT*) hDict; + cmsDICTentry *entry; + + _cmsAssert(dict != NULL); + _cmsAssert(Name != NULL); + + entry = (cmsDICTentry*) _cmsMallocZero(dict ->ContextID, sizeof(cmsDICTentry)); + if (entry == NULL) return FALSE; + + entry ->DisplayName = cmsMLUdup(DisplayName); + entry ->DisplayValue = cmsMLUdup(DisplayValue); + entry ->Name = DupWcs(dict ->ContextID, Name); + entry ->Value = DupWcs(dict ->ContextID, Value); + + entry ->Next = dict ->head; + dict ->head = entry; + + return TRUE; +} + + +// Duplicates an existing dictionary +cmsHANDLE CMSEXPORT cmsDictDup(cmsHANDLE hDict) +{ + _cmsDICT* old_dict = (_cmsDICT*) hDict; + cmsHANDLE hNew; + cmsDICTentry *entry; + + _cmsAssert(old_dict != NULL); + + hNew = cmsDictAlloc(old_dict ->ContextID); + if (hNew == NULL) return NULL; + + // Walk the list freeing all nodes + entry = old_dict ->head; + while (entry != NULL) { + + if (!cmsDictAddEntry(hNew, entry ->Name, entry ->Value, entry ->DisplayName, entry ->DisplayValue)) { + + cmsDictFree(hNew); + return NULL; + } + + entry = entry -> Next; + } + + return hNew; +} + +// Get a pointer to the linked list +const cmsDICTentry* CMSEXPORT cmsDictGetEntryList(cmsHANDLE hDict) +{ + _cmsDICT* dict = (_cmsDICT*) hDict; + + if (dict == NULL) return NULL; + return dict ->head; +} + +// Helper For external languages +const cmsDICTentry* CMSEXPORT cmsDictNextEntry(const cmsDICTentry* e) +{ + if (e == NULL) return NULL; + return e ->Next; +} diff --git a/jni/lcms2-2.5/src/cmsopt.c b/jni/lcms2-2.5/src/cmsopt.c new file mode 100644 index 00000000..4bdf0a7c --- /dev/null +++ b/jni/lcms2-2.5/src/cmsopt.c @@ -0,0 +1,1720 @@ + +//--------------------------------------------------------------------------------- +// +// Little Color Management System +// Copyright (c) 1998-2011 Marti Maria Saguer +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//--------------------------------------------------------------------------------- +// + +#include "lcms2_internal.h" + + +//---------------------------------------------------------------------------------- + +// Optimization for 8 bits, Shaper-CLUT (3 inputs only) +typedef struct { + + cmsContext ContextID; + + const cmsInterpParams* p; // Tetrahedrical interpolation parameters. This is a not-owned pointer. + + cmsUInt16Number rx[256], ry[256], rz[256]; + cmsUInt32Number X0[256], Y0[256], Z0[256]; // Precomputed nodes and offsets for 8-bit input data + + +} Prelin8Data; + + +// Generic optimization for 16 bits Shaper-CLUT-Shaper (any inputs) +typedef struct { + + cmsContext ContextID; + + // Number of channels + int nInputs; + int nOutputs; + + _cmsInterpFn16 EvalCurveIn16[MAX_INPUT_DIMENSIONS]; // The maximum number of input channels is known in advance + cmsInterpParams* ParamsCurveIn16[MAX_INPUT_DIMENSIONS]; + + _cmsInterpFn16 EvalCLUT; // The evaluator for 3D grid + const cmsInterpParams* CLUTparams; // (not-owned pointer) + + + _cmsInterpFn16* EvalCurveOut16; // Points to an array of curve evaluators in 16 bits (not-owned pointer) + cmsInterpParams** ParamsCurveOut16; // Points to an array of references to interpolation params (not-owned pointer) + + +} Prelin16Data; + + +// Optimization for matrix-shaper in 8 bits. Numbers are operated in n.14 signed, tables are stored in 1.14 fixed + +typedef cmsInt32Number cmsS1Fixed14Number; // Note that this may hold more than 16 bits! + +#define DOUBLE_TO_1FIXED14(x) ((cmsS1Fixed14Number) floor((x) * 16384.0 + 0.5)) + +typedef struct { + + cmsContext ContextID; + + cmsS1Fixed14Number Shaper1R[256]; // from 0..255 to 1.14 (0.0...1.0) + cmsS1Fixed14Number Shaper1G[256]; + cmsS1Fixed14Number Shaper1B[256]; + + cmsS1Fixed14Number Mat[3][3]; // n.14 to n.14 (needs a saturation after that) + cmsS1Fixed14Number Off[3]; + + cmsUInt16Number Shaper2R[16385]; // 1.14 to 0..255 + cmsUInt16Number Shaper2G[16385]; + cmsUInt16Number Shaper2B[16385]; + +} MatShaper8Data; + +// Curves, optimization is shared between 8 and 16 bits +typedef struct { + + cmsContext ContextID; + + int nCurves; // Number of curves + int nElements; // Elements in curves + cmsUInt16Number** Curves; // Points to a dynamically allocated array + +} Curves16Data; + + +// Simple optimizations ---------------------------------------------------------------------------------------------------------- + + +// Remove an element in linked chain +static +void _RemoveElement(cmsStage** head) +{ + cmsStage* mpe = *head; + cmsStage* next = mpe ->Next; + *head = next; + cmsStageFree(mpe); +} + +// Remove all identities in chain. Note that pt actually is a double pointer to the element that holds the pointer. +static +cmsBool _Remove1Op(cmsPipeline* Lut, cmsStageSignature UnaryOp) +{ + cmsStage** pt = &Lut ->Elements; + cmsBool AnyOpt = FALSE; + + while (*pt != NULL) { + + if ((*pt) ->Implements == UnaryOp) { + _RemoveElement(pt); + AnyOpt = TRUE; + } + else + pt = &((*pt) -> Next); + } + + return AnyOpt; +} + +// Same, but only if two adjacent elements are found +static +cmsBool _Remove2Op(cmsPipeline* Lut, cmsStageSignature Op1, cmsStageSignature Op2) +{ + cmsStage** pt1; + cmsStage** pt2; + cmsBool AnyOpt = FALSE; + + pt1 = &Lut ->Elements; + if (*pt1 == NULL) return AnyOpt; + + while (*pt1 != NULL) { + + pt2 = &((*pt1) -> Next); + if (*pt2 == NULL) return AnyOpt; + + if ((*pt1) ->Implements == Op1 && (*pt2) ->Implements == Op2) { + _RemoveElement(pt2); + _RemoveElement(pt1); + AnyOpt = TRUE; + } + else + pt1 = &((*pt1) -> Next); + } + + return AnyOpt; +} + +// Preoptimize just gets rif of no-ops coming paired. Conversion from v2 to v4 followed +// by a v4 to v2 and vice-versa. The elements are then discarded. +static +cmsBool PreOptimize(cmsPipeline* Lut) +{ + cmsBool AnyOpt = FALSE, Opt; + + do { + + Opt = FALSE; + + // Remove all identities + Opt |= _Remove1Op(Lut, cmsSigIdentityElemType); + + // Remove XYZ2Lab followed by Lab2XYZ + Opt |= _Remove2Op(Lut, cmsSigXYZ2LabElemType, cmsSigLab2XYZElemType); + + // Remove Lab2XYZ followed by XYZ2Lab + Opt |= _Remove2Op(Lut, cmsSigLab2XYZElemType, cmsSigXYZ2LabElemType); + + // Remove V4 to V2 followed by V2 to V4 + Opt |= _Remove2Op(Lut, cmsSigLabV4toV2, cmsSigLabV2toV4); + + // Remove V2 to V4 followed by V4 to V2 + Opt |= _Remove2Op(Lut, cmsSigLabV2toV4, cmsSigLabV4toV2); + + // Remove float pcs Lab conversions + Opt |= _Remove2Op(Lut, cmsSigLab2FloatPCS, cmsSigFloatPCS2Lab); + + // Remove float pcs Lab conversions + Opt |= _Remove2Op(Lut, cmsSigXYZ2FloatPCS, cmsSigFloatPCS2XYZ); + + if (Opt) AnyOpt = TRUE; + + } while (Opt); + + return AnyOpt; +} + +static +void Eval16nop1D(register const cmsUInt16Number Input[], + register cmsUInt16Number Output[], + register const struct _cms_interp_struc* p) +{ + Output[0] = Input[0]; + + cmsUNUSED_PARAMETER(p); +} + +static +void PrelinEval16(register const cmsUInt16Number Input[], + register cmsUInt16Number Output[], + register const void* D) +{ + Prelin16Data* p16 = (Prelin16Data*) D; + cmsUInt16Number StageABC[MAX_INPUT_DIMENSIONS]; + cmsUInt16Number StageDEF[cmsMAXCHANNELS]; + int i; + + for (i=0; i < p16 ->nInputs; i++) { + + p16 ->EvalCurveIn16[i](&Input[i], &StageABC[i], p16 ->ParamsCurveIn16[i]); + } + + p16 ->EvalCLUT(StageABC, StageDEF, p16 ->CLUTparams); + + for (i=0; i < p16 ->nOutputs; i++) { + + p16 ->EvalCurveOut16[i](&StageDEF[i], &Output[i], p16 ->ParamsCurveOut16[i]); + } +} + + +static +void PrelinOpt16free(cmsContext ContextID, void* ptr) +{ + Prelin16Data* p16 = (Prelin16Data*) ptr; + + _cmsFree(ContextID, p16 ->EvalCurveOut16); + _cmsFree(ContextID, p16 ->ParamsCurveOut16); + + _cmsFree(ContextID, p16); +} + +static +void* Prelin16dup(cmsContext ContextID, const void* ptr) +{ + Prelin16Data* p16 = (Prelin16Data*) ptr; + Prelin16Data* Duped = _cmsDupMem(ContextID, p16, sizeof(Prelin16Data)); + + if (Duped == NULL) return NULL; + + Duped ->EvalCurveOut16 = _cmsDupMem(ContextID, p16 ->EvalCurveOut16, p16 ->nOutputs * sizeof(_cmsInterpFn16)); + Duped ->ParamsCurveOut16 = _cmsDupMem(ContextID, p16 ->ParamsCurveOut16, p16 ->nOutputs * sizeof(cmsInterpParams* )); + + return Duped; +} + + +static +Prelin16Data* PrelinOpt16alloc(cmsContext ContextID, + const cmsInterpParams* ColorMap, + int nInputs, cmsToneCurve** In, + int nOutputs, cmsToneCurve** Out ) +{ + int i; + Prelin16Data* p16 = _cmsMallocZero(ContextID, sizeof(Prelin16Data)); + if (p16 == NULL) return NULL; + + p16 ->nInputs = nInputs; + p16 -> nOutputs = nOutputs; + + + for (i=0; i < nInputs; i++) { + + if (In == NULL) { + p16 -> ParamsCurveIn16[i] = NULL; + p16 -> EvalCurveIn16[i] = Eval16nop1D; + + } + else { + p16 -> ParamsCurveIn16[i] = In[i] ->InterpParams; + p16 -> EvalCurveIn16[i] = p16 ->ParamsCurveIn16[i]->Interpolation.Lerp16; + } + } + + p16 ->CLUTparams = ColorMap; + p16 ->EvalCLUT = ColorMap ->Interpolation.Lerp16; + + + p16 -> EvalCurveOut16 = (_cmsInterpFn16*) _cmsCalloc(ContextID, nOutputs, sizeof(_cmsInterpFn16)); + p16 -> ParamsCurveOut16 = (cmsInterpParams**) _cmsCalloc(ContextID, nOutputs, sizeof(cmsInterpParams* )); + + for (i=0; i < nOutputs; i++) { + + if (Out == NULL) { + p16 ->ParamsCurveOut16[i] = NULL; + p16 -> EvalCurveOut16[i] = Eval16nop1D; + } + else { + + p16 ->ParamsCurveOut16[i] = Out[i] ->InterpParams; + p16 -> EvalCurveOut16[i] = p16 ->ParamsCurveOut16[i]->Interpolation.Lerp16; + } + } + + return p16; +} + + + +// Resampling --------------------------------------------------------------------------------- + +#define PRELINEARIZATION_POINTS 4096 + +// Sampler implemented by another LUT. This is a clean way to precalculate the devicelink 3D CLUT for +// almost any transform. We use floating point precision and then convert from floating point to 16 bits. +static +int XFormSampler16(register const cmsUInt16Number In[], register cmsUInt16Number Out[], register void* Cargo) +{ + cmsPipeline* Lut = (cmsPipeline*) Cargo; + cmsFloat32Number InFloat[cmsMAXCHANNELS], OutFloat[cmsMAXCHANNELS]; + cmsUInt32Number i; + + _cmsAssert(Lut -> InputChannels < cmsMAXCHANNELS); + _cmsAssert(Lut -> OutputChannels < cmsMAXCHANNELS); + + // From 16 bit to floating point + for (i=0; i < Lut ->InputChannels; i++) + InFloat[i] = (cmsFloat32Number) (In[i] / 65535.0); + + // Evaluate in floating point + cmsPipelineEvalFloat(InFloat, OutFloat, Lut); + + // Back to 16 bits representation + for (i=0; i < Lut ->OutputChannels; i++) + Out[i] = _cmsQuickSaturateWord(OutFloat[i] * 65535.0); + + // Always succeed + return TRUE; +} + +// Try to see if the curves of a given MPE are linear +static +cmsBool AllCurvesAreLinear(cmsStage* mpe) +{ + cmsToneCurve** Curves; + cmsUInt32Number i, n; + + Curves = _cmsStageGetPtrToCurveSet(mpe); + if (Curves == NULL) return FALSE; + + n = cmsStageOutputChannels(mpe); + + for (i=0; i < n; i++) { + if (!cmsIsToneCurveLinear(Curves[i])) return FALSE; + } + + return TRUE; +} + +// This function replaces a specific node placed in "At" by the "Value" numbers. Its purpose +// is to fix scum dot on broken profiles/transforms. Works on 1, 3 and 4 channels +static +cmsBool PatchLUT(cmsStage* CLUT, cmsUInt16Number At[], cmsUInt16Number Value[], + int nChannelsOut, int nChannelsIn) +{ + _cmsStageCLutData* Grid = (_cmsStageCLutData*) CLUT ->Data; + cmsInterpParams* p16 = Grid ->Params; + cmsFloat64Number px, py, pz, pw; + int x0, y0, z0, w0; + int i, index; + + if (CLUT -> Type != cmsSigCLutElemType) { + cmsSignalError(CLUT->ContextID, cmsERROR_INTERNAL, "(internal) Attempt to PatchLUT on non-lut stage"); + return FALSE; + } + + if (nChannelsIn == 4) { + + px = ((cmsFloat64Number) At[0] * (p16->Domain[0])) / 65535.0; + py = ((cmsFloat64Number) At[1] * (p16->Domain[1])) / 65535.0; + pz = ((cmsFloat64Number) At[2] * (p16->Domain[2])) / 65535.0; + pw = ((cmsFloat64Number) At[3] * (p16->Domain[3])) / 65535.0; + + x0 = (int) floor(px); + y0 = (int) floor(py); + z0 = (int) floor(pz); + w0 = (int) floor(pw); + + if (((px - x0) != 0) || + ((py - y0) != 0) || + ((pz - z0) != 0) || + ((pw - w0) != 0)) return FALSE; // Not on exact node + + index = p16 -> opta[3] * x0 + + p16 -> opta[2] * y0 + + p16 -> opta[1] * z0 + + p16 -> opta[0] * w0; + } + else + if (nChannelsIn == 3) { + + px = ((cmsFloat64Number) At[0] * (p16->Domain[0])) / 65535.0; + py = ((cmsFloat64Number) At[1] * (p16->Domain[1])) / 65535.0; + pz = ((cmsFloat64Number) At[2] * (p16->Domain[2])) / 65535.0; + + x0 = (int) floor(px); + y0 = (int) floor(py); + z0 = (int) floor(pz); + + if (((px - x0) != 0) || + ((py - y0) != 0) || + ((pz - z0) != 0)) return FALSE; // Not on exact node + + index = p16 -> opta[2] * x0 + + p16 -> opta[1] * y0 + + p16 -> opta[0] * z0; + } + else + if (nChannelsIn == 1) { + + px = ((cmsFloat64Number) At[0] * (p16->Domain[0])) / 65535.0; + + x0 = (int) floor(px); + + if (((px - x0) != 0)) return FALSE; // Not on exact node + + index = p16 -> opta[0] * x0; + } + else { + cmsSignalError(CLUT->ContextID, cmsERROR_INTERNAL, "(internal) %d Channels are not supported on PatchLUT", nChannelsIn); + return FALSE; + } + + for (i=0; i < nChannelsOut; i++) + Grid -> Tab.T[index + i] = Value[i]; + + return TRUE; +} + +// Auxiliar, to see if two values are equal or very different +static +cmsBool WhitesAreEqual(int n, cmsUInt16Number White1[], cmsUInt16Number White2[] ) +{ + int i; + + for (i=0; i < n; i++) { + + if (abs(White1[i] - White2[i]) > 0xf000) return TRUE; // Values are so extremly different that the fixup should be avoided + if (White1[i] != White2[i]) return FALSE; + } + return TRUE; +} + + +// Locate the node for the white point and fix it to pure white in order to avoid scum dot. +static +cmsBool FixWhiteMisalignment(cmsPipeline* Lut, cmsColorSpaceSignature EntryColorSpace, cmsColorSpaceSignature ExitColorSpace) +{ + cmsUInt16Number *WhitePointIn, *WhitePointOut; + cmsUInt16Number WhiteIn[cmsMAXCHANNELS], WhiteOut[cmsMAXCHANNELS], ObtainedOut[cmsMAXCHANNELS]; + cmsUInt32Number i, nOuts, nIns; + cmsStage *PreLin = NULL, *CLUT = NULL, *PostLin = NULL; + + if (!_cmsEndPointsBySpace(EntryColorSpace, + &WhitePointIn, NULL, &nIns)) return FALSE; + + if (!_cmsEndPointsBySpace(ExitColorSpace, + &WhitePointOut, NULL, &nOuts)) return FALSE; + + // It needs to be fixed? + if (Lut ->InputChannels != nIns) return FALSE; + if (Lut ->OutputChannels != nOuts) return FALSE; + + cmsPipelineEval16(WhitePointIn, ObtainedOut, Lut); + + if (WhitesAreEqual(nOuts, WhitePointOut, ObtainedOut)) return TRUE; // whites already match + + // Check if the LUT comes as Prelin, CLUT or Postlin. We allow all combinations + if (!cmsPipelineCheckAndRetreiveStages(Lut, 3, cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType, &PreLin, &CLUT, &PostLin)) + if (!cmsPipelineCheckAndRetreiveStages(Lut, 2, cmsSigCurveSetElemType, cmsSigCLutElemType, &PreLin, &CLUT)) + if (!cmsPipelineCheckAndRetreiveStages(Lut, 2, cmsSigCLutElemType, cmsSigCurveSetElemType, &CLUT, &PostLin)) + if (!cmsPipelineCheckAndRetreiveStages(Lut, 1, cmsSigCLutElemType, &CLUT)) + return FALSE; + + // We need to interpolate white points of both, pre and post curves + if (PreLin) { + + cmsToneCurve** Curves = _cmsStageGetPtrToCurveSet(PreLin); + + for (i=0; i < nIns; i++) { + WhiteIn[i] = cmsEvalToneCurve16(Curves[i], WhitePointIn[i]); + } + } + else { + for (i=0; i < nIns; i++) + WhiteIn[i] = WhitePointIn[i]; + } + + // If any post-linearization, we need to find how is represented white before the curve, do + // a reverse interpolation in this case. + if (PostLin) { + + cmsToneCurve** Curves = _cmsStageGetPtrToCurveSet(PostLin); + + for (i=0; i < nOuts; i++) { + + cmsToneCurve* InversePostLin = cmsReverseToneCurve(Curves[i]); + WhiteOut[i] = cmsEvalToneCurve16(InversePostLin, WhitePointOut[i]); + cmsFreeToneCurve(InversePostLin); + } + } + else { + for (i=0; i < nOuts; i++) + WhiteOut[i] = WhitePointOut[i]; + } + + // Ok, proceed with patching. May fail and we don't care if it fails + PatchLUT(CLUT, WhiteIn, WhiteOut, nOuts, nIns); + + return TRUE; +} + +// ----------------------------------------------------------------------------------------------------------------------------------------------- +// This function creates simple LUT from complex ones. The generated LUT has an optional set of +// prelinearization curves, a CLUT of nGridPoints and optional postlinearization tables. +// These curves have to exist in the original LUT in order to be used in the simplified output. +// Caller may also use the flags to allow this feature. +// LUTS with all curves will be simplified to a single curve. Parametric curves are lost. +// This function should be used on 16-bits LUTS only, as floating point losses precision when simplified +// ----------------------------------------------------------------------------------------------------------------------------------------------- + +static +cmsBool OptimizeByResampling(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags) +{ + cmsPipeline* Src = NULL; + cmsPipeline* Dest = NULL; + cmsStage* mpe; + cmsStage* CLUT; + cmsStage *KeepPreLin = NULL, *KeepPostLin = NULL; + int nGridPoints; + cmsColorSpaceSignature ColorSpace, OutputColorSpace; + cmsStage *NewPreLin = NULL; + cmsStage *NewPostLin = NULL; + _cmsStageCLutData* DataCLUT; + cmsToneCurve** DataSetIn; + cmsToneCurve** DataSetOut; + Prelin16Data* p16; + + // This is a loosy optimization! does not apply in floating-point cases + if (_cmsFormatterIsFloat(*InputFormat) || _cmsFormatterIsFloat(*OutputFormat)) return FALSE; + + ColorSpace = _cmsICCcolorSpace(T_COLORSPACE(*InputFormat)); + OutputColorSpace = _cmsICCcolorSpace(T_COLORSPACE(*OutputFormat)); + nGridPoints = _cmsReasonableGridpointsByColorspace(ColorSpace, *dwFlags); + + // For empty LUTs, 2 points are enough + if (cmsPipelineStageCount(*Lut) == 0) + nGridPoints = 2; + + Src = *Lut; + + // Named color pipelines cannot be optimized either + for (mpe = cmsPipelineGetPtrToFirstStage(Src); + mpe != NULL; + mpe = cmsStageNext(mpe)) { + if (cmsStageType(mpe) == cmsSigNamedColorElemType) return FALSE; + } + + // Allocate an empty LUT + Dest = cmsPipelineAlloc(Src ->ContextID, Src ->InputChannels, Src ->OutputChannels); + if (!Dest) return FALSE; + + // Prelinearization tables are kept unless indicated by flags + if (*dwFlags & cmsFLAGS_CLUT_PRE_LINEARIZATION) { + + // Get a pointer to the prelinearization element + cmsStage* PreLin = cmsPipelineGetPtrToFirstStage(Src); + + // Check if suitable + if (PreLin ->Type == cmsSigCurveSetElemType) { + + // Maybe this is a linear tram, so we can avoid the whole stuff + if (!AllCurvesAreLinear(PreLin)) { + + // All seems ok, proceed. + NewPreLin = cmsStageDup(PreLin); + if(!cmsPipelineInsertStage(Dest, cmsAT_BEGIN, NewPreLin)) + goto Error; + + // Remove prelinearization. Since we have duplicated the curve + // in destination LUT, the sampling shoud be applied after this stage. + cmsPipelineUnlinkStage(Src, cmsAT_BEGIN, &KeepPreLin); + } + } + } + + // Allocate the CLUT + CLUT = cmsStageAllocCLut16bit(Src ->ContextID, nGridPoints, Src ->InputChannels, Src->OutputChannels, NULL); + if (CLUT == NULL) return FALSE; + + // Add the CLUT to the destination LUT + if (!cmsPipelineInsertStage(Dest, cmsAT_END, CLUT)) { + goto Error; + } + + // Postlinearization tables are kept unless indicated by flags + if (*dwFlags & cmsFLAGS_CLUT_POST_LINEARIZATION) { + + // Get a pointer to the postlinearization if present + cmsStage* PostLin = cmsPipelineGetPtrToLastStage(Src); + + // Check if suitable + if (cmsStageType(PostLin) == cmsSigCurveSetElemType) { + + // Maybe this is a linear tram, so we can avoid the whole stuff + if (!AllCurvesAreLinear(PostLin)) { + + // All seems ok, proceed. + NewPostLin = cmsStageDup(PostLin); + if (!cmsPipelineInsertStage(Dest, cmsAT_END, NewPostLin)) + goto Error; + + // In destination LUT, the sampling shoud be applied after this stage. + cmsPipelineUnlinkStage(Src, cmsAT_END, &KeepPostLin); + } + } + } + + // Now its time to do the sampling. We have to ignore pre/post linearization + // The source LUT whithout pre/post curves is passed as parameter. + if (!cmsStageSampleCLut16bit(CLUT, XFormSampler16, (void*) Src, 0)) { +Error: + // Ops, something went wrong, Restore stages + if (KeepPreLin != NULL) { + if (!cmsPipelineInsertStage(Src, cmsAT_BEGIN, KeepPreLin)) { + _cmsAssert(0); // This never happens + } + } + if (KeepPostLin != NULL) { + if (!cmsPipelineInsertStage(Src, cmsAT_END, KeepPostLin)) { + _cmsAssert(0); // This never happens + } + } + cmsPipelineFree(Dest); + return FALSE; + } + + // Done. + + if (KeepPreLin != NULL) cmsStageFree(KeepPreLin); + if (KeepPostLin != NULL) cmsStageFree(KeepPostLin); + cmsPipelineFree(Src); + + DataCLUT = (_cmsStageCLutData*) CLUT ->Data; + + if (NewPreLin == NULL) DataSetIn = NULL; + else DataSetIn = ((_cmsStageToneCurvesData*) NewPreLin ->Data) ->TheCurves; + + if (NewPostLin == NULL) DataSetOut = NULL; + else DataSetOut = ((_cmsStageToneCurvesData*) NewPostLin ->Data) ->TheCurves; + + + if (DataSetIn == NULL && DataSetOut == NULL) { + + _cmsPipelineSetOptimizationParameters(Dest, (_cmsOPTeval16Fn) DataCLUT->Params->Interpolation.Lerp16, DataCLUT->Params, NULL, NULL); + } + else { + + p16 = PrelinOpt16alloc(Dest ->ContextID, + DataCLUT ->Params, + Dest ->InputChannels, + DataSetIn, + Dest ->OutputChannels, + DataSetOut); + + _cmsPipelineSetOptimizationParameters(Dest, PrelinEval16, (void*) p16, PrelinOpt16free, Prelin16dup); + } + + + // Don't fix white on absolute colorimetric + if (Intent == INTENT_ABSOLUTE_COLORIMETRIC) + *dwFlags |= cmsFLAGS_NOWHITEONWHITEFIXUP; + + if (!(*dwFlags & cmsFLAGS_NOWHITEONWHITEFIXUP)) { + + FixWhiteMisalignment(Dest, ColorSpace, OutputColorSpace); + } + + *Lut = Dest; + return TRUE; + + cmsUNUSED_PARAMETER(Intent); +} + + +// ----------------------------------------------------------------------------------------------------------------------------------------------- +// Fixes the gamma balancing of transform. This is described in my paper "Prelinearization Stages on +// Color-Management Application-Specific Integrated Circuits (ASICs)" presented at NIP24. It only works +// for RGB transforms. See the paper for more details +// ----------------------------------------------------------------------------------------------------------------------------------------------- + + +// Normalize endpoints by slope limiting max and min. This assures endpoints as well. +// Descending curves are handled as well. +static +void SlopeLimiting(cmsToneCurve* g) +{ + int BeginVal, EndVal; + int AtBegin = (int) floor((cmsFloat64Number) g ->nEntries * 0.02 + 0.5); // Cutoff at 2% + int AtEnd = g ->nEntries - AtBegin - 1; // And 98% + cmsFloat64Number Val, Slope, beta; + int i; + + if (cmsIsToneCurveDescending(g)) { + BeginVal = 0xffff; EndVal = 0; + } + else { + BeginVal = 0; EndVal = 0xffff; + } + + // Compute slope and offset for begin of curve + Val = g ->Table16[AtBegin]; + Slope = (Val - BeginVal) / AtBegin; + beta = Val - Slope * AtBegin; + + for (i=0; i < AtBegin; i++) + g ->Table16[i] = _cmsQuickSaturateWord(i * Slope + beta); + + // Compute slope and offset for the end + Val = g ->Table16[AtEnd]; + Slope = (EndVal - Val) / AtBegin; // AtBegin holds the X interval, which is same in both cases + beta = Val - Slope * AtEnd; + + for (i = AtEnd; i < (int) g ->nEntries; i++) + g ->Table16[i] = _cmsQuickSaturateWord(i * Slope + beta); +} + + +// Precomputes tables for 8-bit on input devicelink. +static +Prelin8Data* PrelinOpt8alloc(cmsContext ContextID, const cmsInterpParams* p, cmsToneCurve* G[3]) +{ + int i; + cmsUInt16Number Input[3]; + cmsS15Fixed16Number v1, v2, v3; + Prelin8Data* p8; + + p8 = _cmsMallocZero(ContextID, sizeof(Prelin8Data)); + if (p8 == NULL) return NULL; + + // Since this only works for 8 bit input, values comes always as x * 257, + // we can safely take msb byte (x << 8 + x) + + for (i=0; i < 256; i++) { + + if (G != NULL) { + + // Get 16-bit representation + Input[0] = cmsEvalToneCurve16(G[0], FROM_8_TO_16(i)); + Input[1] = cmsEvalToneCurve16(G[1], FROM_8_TO_16(i)); + Input[2] = cmsEvalToneCurve16(G[2], FROM_8_TO_16(i)); + } + else { + Input[0] = FROM_8_TO_16(i); + Input[1] = FROM_8_TO_16(i); + Input[2] = FROM_8_TO_16(i); + } + + + // Move to 0..1.0 in fixed domain + v1 = _cmsToFixedDomain(Input[0] * p -> Domain[0]); + v2 = _cmsToFixedDomain(Input[1] * p -> Domain[1]); + v3 = _cmsToFixedDomain(Input[2] * p -> Domain[2]); + + // Store the precalculated table of nodes + p8 ->X0[i] = (p->opta[2] * FIXED_TO_INT(v1)); + p8 ->Y0[i] = (p->opta[1] * FIXED_TO_INT(v2)); + p8 ->Z0[i] = (p->opta[0] * FIXED_TO_INT(v3)); + + // Store the precalculated table of offsets + p8 ->rx[i] = (cmsUInt16Number) FIXED_REST_TO_INT(v1); + p8 ->ry[i] = (cmsUInt16Number) FIXED_REST_TO_INT(v2); + p8 ->rz[i] = (cmsUInt16Number) FIXED_REST_TO_INT(v3); + } + + p8 ->ContextID = ContextID; + p8 ->p = p; + + return p8; +} + +static +void Prelin8free(cmsContext ContextID, void* ptr) +{ + _cmsFree(ContextID, ptr); +} + +static +void* Prelin8dup(cmsContext ContextID, const void* ptr) +{ + return _cmsDupMem(ContextID, ptr, sizeof(Prelin8Data)); +} + + + +// A optimized interpolation for 8-bit input. +#define DENS(i,j,k) (LutTable[(i)+(j)+(k)+OutChan]) +static +void PrelinEval8(register const cmsUInt16Number Input[], + register cmsUInt16Number Output[], + register const void* D) +{ + + cmsUInt8Number r, g, b; + cmsS15Fixed16Number rx, ry, rz; + cmsS15Fixed16Number c0, c1, c2, c3, Rest; + int OutChan; + register cmsS15Fixed16Number X0, X1, Y0, Y1, Z0, Z1; + Prelin8Data* p8 = (Prelin8Data*) D; + register const cmsInterpParams* p = p8 ->p; + int TotalOut = p -> nOutputs; + const cmsUInt16Number* LutTable = p -> Table; + + r = Input[0] >> 8; + g = Input[1] >> 8; + b = Input[2] >> 8; + + X0 = X1 = p8->X0[r]; + Y0 = Y1 = p8->Y0[g]; + Z0 = Z1 = p8->Z0[b]; + + rx = p8 ->rx[r]; + ry = p8 ->ry[g]; + rz = p8 ->rz[b]; + + X1 = X0 + ((rx == 0) ? 0 : p ->opta[2]); + Y1 = Y0 + ((ry == 0) ? 0 : p ->opta[1]); + Z1 = Z0 + ((rz == 0) ? 0 : p ->opta[0]); + + + // These are the 6 Tetrahedral + for (OutChan=0; OutChan < TotalOut; OutChan++) { + + c0 = DENS(X0, Y0, Z0); + + if (rx >= ry && ry >= rz) + { + c1 = DENS(X1, Y0, Z0) - c0; + c2 = DENS(X1, Y1, Z0) - DENS(X1, Y0, Z0); + c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0); + } + else + if (rx >= rz && rz >= ry) + { + c1 = DENS(X1, Y0, Z0) - c0; + c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1); + c3 = DENS(X1, Y0, Z1) - DENS(X1, Y0, Z0); + } + else + if (rz >= rx && rx >= ry) + { + c1 = DENS(X1, Y0, Z1) - DENS(X0, Y0, Z1); + c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1); + c3 = DENS(X0, Y0, Z1) - c0; + } + else + if (ry >= rx && rx >= rz) + { + c1 = DENS(X1, Y1, Z0) - DENS(X0, Y1, Z0); + c2 = DENS(X0, Y1, Z0) - c0; + c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0); + } + else + if (ry >= rz && rz >= rx) + { + c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1); + c2 = DENS(X0, Y1, Z0) - c0; + c3 = DENS(X0, Y1, Z1) - DENS(X0, Y1, Z0); + } + else + if (rz >= ry && ry >= rx) + { + c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1); + c2 = DENS(X0, Y1, Z1) - DENS(X0, Y0, Z1); + c3 = DENS(X0, Y0, Z1) - c0; + } + else { + c1 = c2 = c3 = 0; + } + + + Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001; + Output[OutChan] = (cmsUInt16Number)c0 + ((Rest + (Rest>>16))>>16); + + } +} + +#undef DENS + + +// Curves that contain wide empty areas are not optimizeable +static +cmsBool IsDegenerated(const cmsToneCurve* g) +{ + int i, Zeros = 0, Poles = 0; + int nEntries = g ->nEntries; + + for (i=0; i < nEntries; i++) { + + if (g ->Table16[i] == 0x0000) Zeros++; + if (g ->Table16[i] == 0xffff) Poles++; + } + + if (Zeros == 1 && Poles == 1) return FALSE; // For linear tables + if (Zeros > (nEntries / 4)) return TRUE; // Degenerated, mostly zeros + if (Poles > (nEntries / 4)) return TRUE; // Degenerated, mostly poles + + return FALSE; +} + +// -------------------------------------------------------------------------------------------------------------- +// We need xput over here + +static +cmsBool OptimizeByComputingLinearization(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags) +{ + cmsPipeline* OriginalLut; + int nGridPoints; + cmsToneCurve *Trans[cmsMAXCHANNELS], *TransReverse[cmsMAXCHANNELS]; + cmsUInt32Number t, i; + cmsFloat32Number v, In[cmsMAXCHANNELS], Out[cmsMAXCHANNELS]; + cmsBool lIsSuitable, lIsLinear; + cmsPipeline* OptimizedLUT = NULL, *LutPlusCurves = NULL; + cmsStage* OptimizedCLUTmpe; + cmsColorSpaceSignature ColorSpace, OutputColorSpace; + cmsStage* OptimizedPrelinMpe; + cmsStage* mpe; + cmsToneCurve** OptimizedPrelinCurves; + _cmsStageCLutData* OptimizedPrelinCLUT; + + + // This is a loosy optimization! does not apply in floating-point cases + if (_cmsFormatterIsFloat(*InputFormat) || _cmsFormatterIsFloat(*OutputFormat)) return FALSE; + + // Only on RGB + if (T_COLORSPACE(*InputFormat) != PT_RGB) return FALSE; + if (T_COLORSPACE(*OutputFormat) != PT_RGB) return FALSE; + + + // On 16 bits, user has to specify the feature + if (!_cmsFormatterIs8bit(*InputFormat)) { + if (!(*dwFlags & cmsFLAGS_CLUT_PRE_LINEARIZATION)) return FALSE; + } + + OriginalLut = *Lut; + + // Named color pipelines cannot be optimized either + for (mpe = cmsPipelineGetPtrToFirstStage(OriginalLut); + mpe != NULL; + mpe = cmsStageNext(mpe)) { + if (cmsStageType(mpe) == cmsSigNamedColorElemType) return FALSE; + } + + ColorSpace = _cmsICCcolorSpace(T_COLORSPACE(*InputFormat)); + OutputColorSpace = _cmsICCcolorSpace(T_COLORSPACE(*OutputFormat)); + nGridPoints = _cmsReasonableGridpointsByColorspace(ColorSpace, *dwFlags); + + // Empty gamma containers + memset(Trans, 0, sizeof(Trans)); + memset(TransReverse, 0, sizeof(TransReverse)); + + for (t = 0; t < OriginalLut ->InputChannels; t++) { + Trans[t] = cmsBuildTabulatedToneCurve16(OriginalLut ->ContextID, PRELINEARIZATION_POINTS, NULL); + if (Trans[t] == NULL) goto Error; + } + + // Populate the curves + for (i=0; i < PRELINEARIZATION_POINTS; i++) { + + v = (cmsFloat32Number) ((cmsFloat64Number) i / (PRELINEARIZATION_POINTS - 1)); + + // Feed input with a gray ramp + for (t=0; t < OriginalLut ->InputChannels; t++) + In[t] = v; + + // Evaluate the gray value + cmsPipelineEvalFloat(In, Out, OriginalLut); + + // Store result in curve + for (t=0; t < OriginalLut ->InputChannels; t++) + Trans[t] ->Table16[i] = _cmsQuickSaturateWord(Out[t] * 65535.0); + } + + // Slope-limit the obtained curves + for (t = 0; t < OriginalLut ->InputChannels; t++) + SlopeLimiting(Trans[t]); + + // Check for validity + lIsSuitable = TRUE; + lIsLinear = TRUE; + for (t=0; (lIsSuitable && (t < OriginalLut ->InputChannels)); t++) { + + // Exclude if already linear + if (!cmsIsToneCurveLinear(Trans[t])) + lIsLinear = FALSE; + + // Exclude if non-monotonic + if (!cmsIsToneCurveMonotonic(Trans[t])) + lIsSuitable = FALSE; + + if (IsDegenerated(Trans[t])) + lIsSuitable = FALSE; + } + + // If it is not suitable, just quit + if (!lIsSuitable) goto Error; + + // Invert curves if possible + for (t = 0; t < OriginalLut ->InputChannels; t++) { + TransReverse[t] = cmsReverseToneCurveEx(PRELINEARIZATION_POINTS, Trans[t]); + if (TransReverse[t] == NULL) goto Error; + } + + // Now inset the reversed curves at the begin of transform + LutPlusCurves = cmsPipelineDup(OriginalLut); + if (LutPlusCurves == NULL) goto Error; + + if (!cmsPipelineInsertStage(LutPlusCurves, cmsAT_BEGIN, cmsStageAllocToneCurves(OriginalLut ->ContextID, OriginalLut ->InputChannels, TransReverse))) + goto Error; + + // Create the result LUT + OptimizedLUT = cmsPipelineAlloc(OriginalLut ->ContextID, OriginalLut ->InputChannels, OriginalLut ->OutputChannels); + if (OptimizedLUT == NULL) goto Error; + + OptimizedPrelinMpe = cmsStageAllocToneCurves(OriginalLut ->ContextID, OriginalLut ->InputChannels, Trans); + + // Create and insert the curves at the beginning + if (!cmsPipelineInsertStage(OptimizedLUT, cmsAT_BEGIN, OptimizedPrelinMpe)) + goto Error; + + // Allocate the CLUT for result + OptimizedCLUTmpe = cmsStageAllocCLut16bit(OriginalLut ->ContextID, nGridPoints, OriginalLut ->InputChannels, OriginalLut ->OutputChannels, NULL); + + // Add the CLUT to the destination LUT + if (!cmsPipelineInsertStage(OptimizedLUT, cmsAT_END, OptimizedCLUTmpe)) + goto Error; + + // Resample the LUT + if (!cmsStageSampleCLut16bit(OptimizedCLUTmpe, XFormSampler16, (void*) LutPlusCurves, 0)) goto Error; + + // Free resources + for (t = 0; t < OriginalLut ->InputChannels; t++) { + + if (Trans[t]) cmsFreeToneCurve(Trans[t]); + if (TransReverse[t]) cmsFreeToneCurve(TransReverse[t]); + } + + cmsPipelineFree(LutPlusCurves); + + + OptimizedPrelinCurves = _cmsStageGetPtrToCurveSet(OptimizedPrelinMpe); + OptimizedPrelinCLUT = (_cmsStageCLutData*) OptimizedCLUTmpe ->Data; + + // Set the evaluator if 8-bit + if (_cmsFormatterIs8bit(*InputFormat)) { + + Prelin8Data* p8 = PrelinOpt8alloc(OptimizedLUT ->ContextID, + OptimizedPrelinCLUT ->Params, + OptimizedPrelinCurves); + if (p8 == NULL) return FALSE; + + _cmsPipelineSetOptimizationParameters(OptimizedLUT, PrelinEval8, (void*) p8, Prelin8free, Prelin8dup); + + } + else + { + Prelin16Data* p16 = PrelinOpt16alloc(OptimizedLUT ->ContextID, + OptimizedPrelinCLUT ->Params, + 3, OptimizedPrelinCurves, 3, NULL); + if (p16 == NULL) return FALSE; + + _cmsPipelineSetOptimizationParameters(OptimizedLUT, PrelinEval16, (void*) p16, PrelinOpt16free, Prelin16dup); + + } + + // Don't fix white on absolute colorimetric + if (Intent == INTENT_ABSOLUTE_COLORIMETRIC) + *dwFlags |= cmsFLAGS_NOWHITEONWHITEFIXUP; + + if (!(*dwFlags & cmsFLAGS_NOWHITEONWHITEFIXUP)) { + + if (!FixWhiteMisalignment(OptimizedLUT, ColorSpace, OutputColorSpace)) { + + return FALSE; + } + } + + // And return the obtained LUT + + cmsPipelineFree(OriginalLut); + *Lut = OptimizedLUT; + return TRUE; + +Error: + + for (t = 0; t < OriginalLut ->InputChannels; t++) { + + if (Trans[t]) cmsFreeToneCurve(Trans[t]); + if (TransReverse[t]) cmsFreeToneCurve(TransReverse[t]); + } + + if (LutPlusCurves != NULL) cmsPipelineFree(LutPlusCurves); + if (OptimizedLUT != NULL) cmsPipelineFree(OptimizedLUT); + + return FALSE; + + cmsUNUSED_PARAMETER(Intent); +} + + +// Curves optimizer ------------------------------------------------------------------------------------------------------------------ + +static +void CurvesFree(cmsContext ContextID, void* ptr) +{ + Curves16Data* Data = (Curves16Data*) ptr; + int i; + + for (i=0; i < Data -> nCurves; i++) { + + _cmsFree(ContextID, Data ->Curves[i]); + } + + _cmsFree(ContextID, Data ->Curves); + _cmsFree(ContextID, ptr); +} + +static +void* CurvesDup(cmsContext ContextID, const void* ptr) +{ + Curves16Data* Data = _cmsDupMem(ContextID, ptr, sizeof(Curves16Data)); + int i; + + if (Data == NULL) return NULL; + + Data ->Curves = _cmsDupMem(ContextID, Data ->Curves, Data ->nCurves * sizeof(cmsUInt16Number*)); + + for (i=0; i < Data -> nCurves; i++) { + Data ->Curves[i] = _cmsDupMem(ContextID, Data ->Curves[i], Data -> nElements * sizeof(cmsUInt16Number)); + } + + return (void*) Data; +} + +// Precomputes tables for 8-bit on input devicelink. +static +Curves16Data* CurvesAlloc(cmsContext ContextID, int nCurves, int nElements, cmsToneCurve** G) +{ + int i, j; + Curves16Data* c16; + + c16 = _cmsMallocZero(ContextID, sizeof(Curves16Data)); + if (c16 == NULL) return NULL; + + c16 ->nCurves = nCurves; + c16 ->nElements = nElements; + + c16 ->Curves = _cmsCalloc(ContextID, nCurves, sizeof(cmsUInt16Number*)); + if (c16 ->Curves == NULL) return NULL; + + for (i=0; i < nCurves; i++) { + + c16->Curves[i] = _cmsCalloc(ContextID, nElements, sizeof(cmsUInt16Number)); + + if (c16->Curves[i] == NULL) { + + for (j=0; j < i; j++) { + _cmsFree(ContextID, c16->Curves[j]); + } + _cmsFree(ContextID, c16->Curves); + _cmsFree(ContextID, c16); + return NULL; + } + + if (nElements == 256) { + + for (j=0; j < nElements; j++) { + + c16 ->Curves[i][j] = cmsEvalToneCurve16(G[i], FROM_8_TO_16(j)); + } + } + else { + + for (j=0; j < nElements; j++) { + c16 ->Curves[i][j] = cmsEvalToneCurve16(G[i], (cmsUInt16Number) j); + } + } + } + + return c16; +} + +static +void FastEvaluateCurves8(register const cmsUInt16Number In[], + register cmsUInt16Number Out[], + register const void* D) +{ + Curves16Data* Data = (Curves16Data*) D; + cmsUInt8Number x; + int i; + + for (i=0; i < Data ->nCurves; i++) { + + x = (In[i] >> 8); + Out[i] = Data -> Curves[i][x]; + } +} + + +static +void FastEvaluateCurves16(register const cmsUInt16Number In[], + register cmsUInt16Number Out[], + register const void* D) +{ + Curves16Data* Data = (Curves16Data*) D; + int i; + + for (i=0; i < Data ->nCurves; i++) { + Out[i] = Data -> Curves[i][In[i]]; + } +} + + +static +void FastIdentity16(register const cmsUInt16Number In[], + register cmsUInt16Number Out[], + register const void* D) +{ + cmsPipeline* Lut = (cmsPipeline*) D; + cmsUInt32Number i; + + for (i=0; i < Lut ->InputChannels; i++) { + Out[i] = In[i]; + } +} + + +// If the target LUT holds only curves, the optimization procedure is to join all those +// curves together. That only works on curves and does not work on matrices. +static +cmsBool OptimizeByJoiningCurves(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags) +{ + cmsToneCurve** GammaTables = NULL; + cmsFloat32Number InFloat[cmsMAXCHANNELS], OutFloat[cmsMAXCHANNELS]; + cmsUInt32Number i, j; + cmsPipeline* Src = *Lut; + cmsPipeline* Dest = NULL; + cmsStage* mpe; + cmsStage* ObtainedCurves = NULL; + + + // This is a loosy optimization! does not apply in floating-point cases + if (_cmsFormatterIsFloat(*InputFormat) || _cmsFormatterIsFloat(*OutputFormat)) return FALSE; + + // Only curves in this LUT? + for (mpe = cmsPipelineGetPtrToFirstStage(Src); + mpe != NULL; + mpe = cmsStageNext(mpe)) { + if (cmsStageType(mpe) != cmsSigCurveSetElemType) return FALSE; + } + + // Allocate an empty LUT + Dest = cmsPipelineAlloc(Src ->ContextID, Src ->InputChannels, Src ->OutputChannels); + if (Dest == NULL) return FALSE; + + // Create target curves + GammaTables = (cmsToneCurve**) _cmsCalloc(Src ->ContextID, Src ->InputChannels, sizeof(cmsToneCurve*)); + if (GammaTables == NULL) goto Error; + + for (i=0; i < Src ->InputChannels; i++) { + GammaTables[i] = cmsBuildTabulatedToneCurve16(Src ->ContextID, PRELINEARIZATION_POINTS, NULL); + if (GammaTables[i] == NULL) goto Error; + } + + // Compute 16 bit result by using floating point + for (i=0; i < PRELINEARIZATION_POINTS; i++) { + + for (j=0; j < Src ->InputChannels; j++) + InFloat[j] = (cmsFloat32Number) ((cmsFloat64Number) i / (PRELINEARIZATION_POINTS - 1)); + + cmsPipelineEvalFloat(InFloat, OutFloat, Src); + + for (j=0; j < Src ->InputChannels; j++) + GammaTables[j] -> Table16[i] = _cmsQuickSaturateWord(OutFloat[j] * 65535.0); + } + + ObtainedCurves = cmsStageAllocToneCurves(Src ->ContextID, Src ->InputChannels, GammaTables); + if (ObtainedCurves == NULL) goto Error; + + for (i=0; i < Src ->InputChannels; i++) { + cmsFreeToneCurve(GammaTables[i]); + GammaTables[i] = NULL; + } + + if (GammaTables != NULL) _cmsFree(Src ->ContextID, GammaTables); + + // Maybe the curves are linear at the end + if (!AllCurvesAreLinear(ObtainedCurves)) { + + if (!cmsPipelineInsertStage(Dest, cmsAT_BEGIN, ObtainedCurves)) + goto Error; + + // If the curves are to be applied in 8 bits, we can save memory + if (_cmsFormatterIs8bit(*InputFormat)) { + + _cmsStageToneCurvesData* Data = (_cmsStageToneCurvesData*) ObtainedCurves ->Data; + Curves16Data* c16 = CurvesAlloc(Dest ->ContextID, Data ->nCurves, 256, Data ->TheCurves); + + if (c16 == NULL) goto Error; + *dwFlags |= cmsFLAGS_NOCACHE; + _cmsPipelineSetOptimizationParameters(Dest, FastEvaluateCurves8, c16, CurvesFree, CurvesDup); + + } + else { + + _cmsStageToneCurvesData* Data = (_cmsStageToneCurvesData*) cmsStageData(ObtainedCurves); + Curves16Data* c16 = CurvesAlloc(Dest ->ContextID, Data ->nCurves, 65536, Data ->TheCurves); + + if (c16 == NULL) goto Error; + *dwFlags |= cmsFLAGS_NOCACHE; + _cmsPipelineSetOptimizationParameters(Dest, FastEvaluateCurves16, c16, CurvesFree, CurvesDup); + } + } + else { + + // LUT optimizes to nothing. Set the identity LUT + cmsStageFree(ObtainedCurves); + + if (!cmsPipelineInsertStage(Dest, cmsAT_BEGIN, cmsStageAllocIdentity(Dest ->ContextID, Src ->InputChannels))) + goto Error; + + *dwFlags |= cmsFLAGS_NOCACHE; + _cmsPipelineSetOptimizationParameters(Dest, FastIdentity16, (void*) Dest, NULL, NULL); + } + + // We are done. + cmsPipelineFree(Src); + *Lut = Dest; + return TRUE; + +Error: + + if (ObtainedCurves != NULL) cmsStageFree(ObtainedCurves); + if (GammaTables != NULL) { + for (i=0; i < Src ->InputChannels; i++) { + if (GammaTables[i] != NULL) cmsFreeToneCurve(GammaTables[i]); + } + + _cmsFree(Src ->ContextID, GammaTables); + } + + if (Dest != NULL) cmsPipelineFree(Dest); + return FALSE; + + cmsUNUSED_PARAMETER(Intent); + cmsUNUSED_PARAMETER(InputFormat); + cmsUNUSED_PARAMETER(OutputFormat); + cmsUNUSED_PARAMETER(dwFlags); +} + +// ------------------------------------------------------------------------------------------------------------------------------------- +// LUT is Shaper - Matrix - Matrix - Shaper, which is very frequent when combining two matrix-shaper profiles + + +static +void FreeMatShaper(cmsContext ContextID, void* Data) +{ + if (Data != NULL) _cmsFree(ContextID, Data); +} + +static +void* DupMatShaper(cmsContext ContextID, const void* Data) +{ + return _cmsDupMem(ContextID, Data, sizeof(MatShaper8Data)); +} + + +// A fast matrix-shaper evaluator for 8 bits. This is a bit ticky since I'm using 1.14 signed fixed point +// to accomplish some performance. Actually it takes 256x3 16 bits tables and 16385 x 3 tables of 8 bits, +// in total about 50K, and the performance boost is huge! +static +void MatShaperEval16(register const cmsUInt16Number In[], + register cmsUInt16Number Out[], + register const void* D) +{ + MatShaper8Data* p = (MatShaper8Data*) D; + cmsS1Fixed14Number l1, l2, l3, r, g, b; + cmsUInt32Number ri, gi, bi; + + // In this case (and only in this case!) we can use this simplification since + // In[] is assured to come from a 8 bit number. (a << 8 | a) + ri = In[0] & 0xFF; + gi = In[1] & 0xFF; + bi = In[2] & 0xFF; + + // Across first shaper, which also converts to 1.14 fixed point + r = p->Shaper1R[ri]; + g = p->Shaper1G[gi]; + b = p->Shaper1B[bi]; + + // Evaluate the matrix in 1.14 fixed point + l1 = (p->Mat[0][0] * r + p->Mat[0][1] * g + p->Mat[0][2] * b + p->Off[0] + 0x2000) >> 14; + l2 = (p->Mat[1][0] * r + p->Mat[1][1] * g + p->Mat[1][2] * b + p->Off[1] + 0x2000) >> 14; + l3 = (p->Mat[2][0] * r + p->Mat[2][1] * g + p->Mat[2][2] * b + p->Off[2] + 0x2000) >> 14; + + // Now we have to clip to 0..1.0 range + ri = (l1 < 0) ? 0 : ((l1 > 16384) ? 16384 : l1); + gi = (l2 < 0) ? 0 : ((l2 > 16384) ? 16384 : l2); + bi = (l3 < 0) ? 0 : ((l3 > 16384) ? 16384 : l3); + + // And across second shaper, + Out[0] = p->Shaper2R[ri]; + Out[1] = p->Shaper2G[gi]; + Out[2] = p->Shaper2B[bi]; + +} + +// This table converts from 8 bits to 1.14 after applying the curve +static +void FillFirstShaper(cmsS1Fixed14Number* Table, cmsToneCurve* Curve) +{ + int i; + cmsFloat32Number R, y; + + for (i=0; i < 256; i++) { + + R = (cmsFloat32Number) (i / 255.0); + y = cmsEvalToneCurveFloat(Curve, R); + + Table[i] = DOUBLE_TO_1FIXED14(y); + } +} + +// This table converts form 1.14 (being 0x4000 the last entry) to 8 bits after applying the curve +static +void FillSecondShaper(cmsUInt16Number* Table, cmsToneCurve* Curve, cmsBool Is8BitsOutput) +{ + int i; + cmsFloat32Number R, Val; + + for (i=0; i < 16385; i++) { + + R = (cmsFloat32Number) (i / 16384.0); + Val = cmsEvalToneCurveFloat(Curve, R); // Val comes 0..1.0 + + if (Is8BitsOutput) { + + // If 8 bits output, we can optimize further by computing the / 257 part. + // first we compute the resulting byte and then we store the byte times + // 257. This quantization allows to round very quick by doing a >> 8, but + // since the low byte is always equal to msb, we can do a & 0xff and this works! + cmsUInt16Number w = _cmsQuickSaturateWord(Val * 65535.0); + cmsUInt8Number b = FROM_16_TO_8(w); + + Table[i] = FROM_8_TO_16(b); + } + else Table[i] = _cmsQuickSaturateWord(Val * 65535.0); + } +} + +// Compute the matrix-shaper structure +static +cmsBool SetMatShaper(cmsPipeline* Dest, cmsToneCurve* Curve1[3], cmsMAT3* Mat, cmsVEC3* Off, cmsToneCurve* Curve2[3], cmsUInt32Number* OutputFormat) +{ + MatShaper8Data* p; + int i, j; + cmsBool Is8Bits = _cmsFormatterIs8bit(*OutputFormat); + + // Allocate a big chuck of memory to store precomputed tables + p = (MatShaper8Data*) _cmsMalloc(Dest ->ContextID, sizeof(MatShaper8Data)); + if (p == NULL) return FALSE; + + p -> ContextID = Dest -> ContextID; + + // Precompute tables + FillFirstShaper(p ->Shaper1R, Curve1[0]); + FillFirstShaper(p ->Shaper1G, Curve1[1]); + FillFirstShaper(p ->Shaper1B, Curve1[2]); + + FillSecondShaper(p ->Shaper2R, Curve2[0], Is8Bits); + FillSecondShaper(p ->Shaper2G, Curve2[1], Is8Bits); + FillSecondShaper(p ->Shaper2B, Curve2[2], Is8Bits); + + // Convert matrix to nFixed14. Note that those values may take more than 16 bits as + for (i=0; i < 3; i++) { + for (j=0; j < 3; j++) { + p ->Mat[i][j] = DOUBLE_TO_1FIXED14(Mat->v[i].n[j]); + } + } + + for (i=0; i < 3; i++) { + + if (Off == NULL) { + p ->Off[i] = 0; + } + else { + p ->Off[i] = DOUBLE_TO_1FIXED14(Off->n[i]); + } + } + + // Mark as optimized for faster formatter + if (Is8Bits) + *OutputFormat |= OPTIMIZED_SH(1); + + // Fill function pointers + _cmsPipelineSetOptimizationParameters(Dest, MatShaperEval16, (void*) p, FreeMatShaper, DupMatShaper); + return TRUE; +} + +// 8 bits on input allows matrix-shaper boot up to 25 Mpixels per second on RGB. That's fast! +// TODO: Allow a third matrix for abs. colorimetric +static +cmsBool OptimizeMatrixShaper(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags) +{ + cmsStage* Curve1, *Curve2; + cmsStage* Matrix1, *Matrix2; + _cmsStageMatrixData* Data1; + _cmsStageMatrixData* Data2; + cmsMAT3 res; + cmsBool IdentityMat; + cmsPipeline* Dest, *Src; + + // Only works on RGB to RGB + if (T_CHANNELS(*InputFormat) != 3 || T_CHANNELS(*OutputFormat) != 3) return FALSE; + + // Only works on 8 bit input + if (!_cmsFormatterIs8bit(*InputFormat)) return FALSE; + + // Seems suitable, proceed + Src = *Lut; + + // Check for shaper-matrix-matrix-shaper structure, that is what this optimizer stands for + if (!cmsPipelineCheckAndRetreiveStages(Src, 4, + cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType, + &Curve1, &Matrix1, &Matrix2, &Curve2)) return FALSE; + + // Get both matrices + Data1 = (_cmsStageMatrixData*) cmsStageData(Matrix1); + Data2 = (_cmsStageMatrixData*) cmsStageData(Matrix2); + + // Input offset should be zero + if (Data1 ->Offset != NULL) return FALSE; + + // Multiply both matrices to get the result + _cmsMAT3per(&res, (cmsMAT3*) Data2 ->Double, (cmsMAT3*) Data1 ->Double); + + // Now the result is in res + Data2 -> Offset. Maybe is a plain identity? + IdentityMat = FALSE; + if (_cmsMAT3isIdentity(&res) && Data2 ->Offset == NULL) { + + // We can get rid of full matrix + IdentityMat = TRUE; + } + + // Allocate an empty LUT + Dest = cmsPipelineAlloc(Src ->ContextID, Src ->InputChannels, Src ->OutputChannels); + if (!Dest) return FALSE; + + // Assamble the new LUT + if (!cmsPipelineInsertStage(Dest, cmsAT_BEGIN, cmsStageDup(Curve1))) + goto Error; + + if (!IdentityMat) + if (!cmsPipelineInsertStage(Dest, cmsAT_END, cmsStageAllocMatrix(Dest ->ContextID, 3, 3, (const cmsFloat64Number*) &res, Data2 ->Offset))) + goto Error; + if (!cmsPipelineInsertStage(Dest, cmsAT_END, cmsStageDup(Curve2))) + goto Error; + + // If identity on matrix, we can further optimize the curves, so call the join curves routine + if (IdentityMat) { + + OptimizeByJoiningCurves(&Dest, Intent, InputFormat, OutputFormat, dwFlags); + } + else { + _cmsStageToneCurvesData* mpeC1 = (_cmsStageToneCurvesData*) cmsStageData(Curve1); + _cmsStageToneCurvesData* mpeC2 = (_cmsStageToneCurvesData*) cmsStageData(Curve2); + + // In this particular optimization, caché does not help as it takes more time to deal with + // the caché that with the pixel handling + *dwFlags |= cmsFLAGS_NOCACHE; + + // Setup the optimizarion routines + SetMatShaper(Dest, mpeC1 ->TheCurves, &res, (cmsVEC3*) Data2 ->Offset, mpeC2->TheCurves, OutputFormat); + } + + cmsPipelineFree(Src); + *Lut = Dest; + return TRUE; +Error: + // Leave Src unchanged + cmsPipelineFree(Dest); + return FALSE; +} + + +// ------------------------------------------------------------------------------------------------------------------------------------- +// Optimization plug-ins + +// List of optimizations +typedef struct _cmsOptimizationCollection_st { + + _cmsOPToptimizeFn OptimizePtr; + + struct _cmsOptimizationCollection_st *Next; + +} _cmsOptimizationCollection; + + +// The built-in list. We currently implement 4 types of optimizations. Joining of curves, matrix-shaper, linearization and resampling +static _cmsOptimizationCollection DefaultOptimization[] = { + + { OptimizeByJoiningCurves, &DefaultOptimization[1] }, + { OptimizeMatrixShaper, &DefaultOptimization[2] }, + { OptimizeByComputingLinearization, &DefaultOptimization[3] }, + { OptimizeByResampling, NULL } +}; + +// The linked list head +static _cmsOptimizationCollection* OptimizationCollection = DefaultOptimization; + +// Register new ways to optimize +cmsBool _cmsRegisterOptimizationPlugin(cmsContext id, cmsPluginBase* Data) +{ + cmsPluginOptimization* Plugin = (cmsPluginOptimization*) Data; + _cmsOptimizationCollection* fl; + + if (Data == NULL) { + + OptimizationCollection = DefaultOptimization; + return TRUE; + } + + // Optimizer callback is required + if (Plugin ->OptimizePtr == NULL) return FALSE; + + fl = (_cmsOptimizationCollection*) _cmsPluginMalloc(id, sizeof(_cmsOptimizationCollection)); + if (fl == NULL) return FALSE; + + // Copy the parameters + fl ->OptimizePtr = Plugin ->OptimizePtr; + + // Keep linked list + fl ->Next = OptimizationCollection; + OptimizationCollection = fl; + + // All is ok + return TRUE; +} + +// The entry point for LUT optimization +cmsBool _cmsOptimizePipeline(cmsPipeline** PtrLut, + int Intent, + cmsUInt32Number* InputFormat, + cmsUInt32Number* OutputFormat, + cmsUInt32Number* dwFlags) +{ + _cmsOptimizationCollection* Opts; + cmsBool AnySuccess = FALSE; + + // A CLUT is being asked, so force this specific optimization + if (*dwFlags & cmsFLAGS_FORCE_CLUT) { + + PreOptimize(*PtrLut); + return OptimizeByResampling(PtrLut, Intent, InputFormat, OutputFormat, dwFlags); + } + + // Anything to optimize? + if ((*PtrLut) ->Elements == NULL) { + _cmsPipelineSetOptimizationParameters(*PtrLut, FastIdentity16, (void*) *PtrLut, NULL, NULL); + return TRUE; + } + + // Try to get rid of identities and trivial conversions. + AnySuccess = PreOptimize(*PtrLut); + + // After removal do we end with an identity? + if ((*PtrLut) ->Elements == NULL) { + _cmsPipelineSetOptimizationParameters(*PtrLut, FastIdentity16, (void*) *PtrLut, NULL, NULL); + return TRUE; + } + + // Do not optimize, keep all precision + if (*dwFlags & cmsFLAGS_NOOPTIMIZE) + return FALSE; + + // Try built-in optimizations and plug-in + for (Opts = OptimizationCollection; + Opts != NULL; + Opts = Opts ->Next) { + + // If one schema succeeded, we are done + if (Opts ->OptimizePtr(PtrLut, Intent, InputFormat, OutputFormat, dwFlags)) { + + return TRUE; // Optimized! + } + } + + // Only simple optimizations succeeded + return AnySuccess; +} + + + diff --git a/jni/lcms2-2.5/src/cmspack.c b/jni/lcms2-2.5/src/cmspack.c new file mode 100644 index 00000000..d54a8cf6 --- /dev/null +++ b/jni/lcms2-2.5/src/cmspack.c @@ -0,0 +1,3242 @@ +//--------------------------------------------------------------------------------- +// +// Little Color Management System +// Copyright (c) 1998-2010 Marti Maria Saguer +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//--------------------------------------------------------------------------------- +// + +#include "lcms2_internal.h" + +// This module handles all formats supported by lcms. There are two flavors, 16 bits and +// floating point. Floating point is supported only in a subset, those formats holding +// cmsFloat32Number (4 bytes per component) and double (marked as 0 bytes per component +// as special case) + +// --------------------------------------------------------------------------- + + +// This macro return words stored as big endian +#define CHANGE_ENDIAN(w) (cmsUInt16Number) ((cmsUInt16Number) ((w)<<8)|((w)>>8)) + +// These macros handles reversing (negative) +#define REVERSE_FLAVOR_8(x) ((cmsUInt8Number) (0xff-(x))) +#define REVERSE_FLAVOR_16(x) ((cmsUInt16Number)(0xffff-(x))) + +// * 0xffff / 0xff00 = (255 * 257) / (255 * 256) = 257 / 256 +cmsINLINE cmsUInt16Number FomLabV2ToLabV4(cmsUInt16Number x) +{ + int a = (x << 8 | x) >> 8; // * 257 / 256 + if ( a > 0xffff) return 0xffff; + return (cmsUInt16Number) a; +} + +// * 0xf00 / 0xffff = * 256 / 257 +cmsINLINE cmsUInt16Number FomLabV4ToLabV2(cmsUInt16Number x) +{ + return (cmsUInt16Number) (((x << 8) + 0x80) / 257); +} + + +typedef struct { + cmsUInt32Number Type; + cmsUInt32Number Mask; + cmsFormatter16 Frm; + +} cmsFormatters16; + +typedef struct { + cmsUInt32Number Type; + cmsUInt32Number Mask; + cmsFormatterFloat Frm; + +} cmsFormattersFloat; + + +#define ANYSPACE COLORSPACE_SH(31) +#define ANYCHANNELS CHANNELS_SH(15) +#define ANYEXTRA EXTRA_SH(7) +#define ANYPLANAR PLANAR_SH(1) +#define ANYENDIAN ENDIAN16_SH(1) +#define ANYSWAP DOSWAP_SH(1) +#define ANYSWAPFIRST SWAPFIRST_SH(1) +#define ANYFLAVOR FLAVOR_SH(1) + + +// Supress waning about info never being used + +#ifdef _MSC_VER +#pragma warning(disable : 4100) +#endif + +// Unpacking routines (16 bits) ---------------------------------------------------------------------------------------- + + +// Does almost everything but is slow +static +cmsUInt8Number* UnrollChunkyBytes(register _cmsTRANSFORM* info, + register cmsUInt16Number wIn[], + register cmsUInt8Number* accum, + register cmsUInt32Number Stride) +{ + int nChan = T_CHANNELS(info -> InputFormat); + int DoSwap = T_DOSWAP(info ->InputFormat); + int Reverse = T_FLAVOR(info ->InputFormat); + int SwapFirst = T_SWAPFIRST(info -> InputFormat); + int Extra = T_EXTRA(info -> InputFormat); + int ExtraFirst = DoSwap ^ SwapFirst; + cmsUInt16Number v; + int i; + + if (ExtraFirst) { + accum += Extra; + } + + for (i=0; i < nChan; i++) { + int index = DoSwap ? (nChan - i - 1) : i; + + v = FROM_8_TO_16(*accum); + v = Reverse ? REVERSE_FLAVOR_16(v) : v; + wIn[index] = v; + accum++; + } + + if (!ExtraFirst) { + accum += Extra; + } + + if (Extra == 0 && SwapFirst) { + cmsUInt16Number tmp = wIn[0]; + + memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsUInt16Number)); + wIn[nChan-1] = tmp; + } + + return accum; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); + +} + +// Extra channels are just ignored because come in the next planes +static +cmsUInt8Number* UnrollPlanarBytes(register _cmsTRANSFORM* info, + register cmsUInt16Number wIn[], + register cmsUInt8Number* accum, + register cmsUInt32Number Stride) +{ + int nChan = T_CHANNELS(info -> InputFormat); + int DoSwap = T_DOSWAP(info ->InputFormat); + int SwapFirst = T_SWAPFIRST(info ->InputFormat); + int Reverse = T_FLAVOR(info ->InputFormat); + int i; + cmsUInt8Number* Init = accum; + + if (DoSwap ^ SwapFirst) { + accum += T_EXTRA(info -> InputFormat) * Stride; + } + + for (i=0; i < nChan; i++) { + + int index = DoSwap ? (nChan - i - 1) : i; + cmsUInt16Number v = FROM_8_TO_16(*accum); + + wIn[index] = Reverse ? REVERSE_FLAVOR_16(v) : v; + accum += Stride; + } + + return (Init + 1); +} + +// Special cases, provided for performance +static +cmsUInt8Number* Unroll4Bytes(register _cmsTRANSFORM* info, + register cmsUInt16Number wIn[], + register cmsUInt8Number* accum, + register cmsUInt32Number Stride) +{ + wIn[0] = FROM_8_TO_16(*accum); accum++; // C + wIn[1] = FROM_8_TO_16(*accum); accum++; // M + wIn[2] = FROM_8_TO_16(*accum); accum++; // Y + wIn[3] = FROM_8_TO_16(*accum); accum++; // K + + return accum; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +static +cmsUInt8Number* Unroll4BytesReverse(register _cmsTRANSFORM* info, + register cmsUInt16Number wIn[], + register cmsUInt8Number* accum, + register cmsUInt32Number Stride) +{ + wIn[0] = FROM_8_TO_16(REVERSE_FLAVOR_8(*accum)); accum++; // C + wIn[1] = FROM_8_TO_16(REVERSE_FLAVOR_8(*accum)); accum++; // M + wIn[2] = FROM_8_TO_16(REVERSE_FLAVOR_8(*accum)); accum++; // Y + wIn[3] = FROM_8_TO_16(REVERSE_FLAVOR_8(*accum)); accum++; // K + + return accum; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +static +cmsUInt8Number* Unroll4BytesSwapFirst(register _cmsTRANSFORM* info, + register cmsUInt16Number wIn[], + register cmsUInt8Number* accum, + register cmsUInt32Number Stride) +{ + wIn[3] = FROM_8_TO_16(*accum); accum++; // K + wIn[0] = FROM_8_TO_16(*accum); accum++; // C + wIn[1] = FROM_8_TO_16(*accum); accum++; // M + wIn[2] = FROM_8_TO_16(*accum); accum++; // Y + + return accum; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +// KYMC +static +cmsUInt8Number* Unroll4BytesSwap(register _cmsTRANSFORM* info, + register cmsUInt16Number wIn[], + register cmsUInt8Number* accum, + register cmsUInt32Number Stride) +{ + wIn[3] = FROM_8_TO_16(*accum); accum++; // K + wIn[2] = FROM_8_TO_16(*accum); accum++; // Y + wIn[1] = FROM_8_TO_16(*accum); accum++; // M + wIn[0] = FROM_8_TO_16(*accum); accum++; // C + + return accum; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +static +cmsUInt8Number* Unroll4BytesSwapSwapFirst(register _cmsTRANSFORM* info, + register cmsUInt16Number wIn[], + register cmsUInt8Number* accum, + register cmsUInt32Number Stride) +{ + wIn[2] = FROM_8_TO_16(*accum); accum++; // K + wIn[1] = FROM_8_TO_16(*accum); accum++; // Y + wIn[0] = FROM_8_TO_16(*accum); accum++; // M + wIn[3] = FROM_8_TO_16(*accum); accum++; // C + + return accum; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +static +cmsUInt8Number* Unroll3Bytes(register _cmsTRANSFORM* info, + register cmsUInt16Number wIn[], + register cmsUInt8Number* accum, + register cmsUInt32Number Stride) +{ + wIn[0] = FROM_8_TO_16(*accum); accum++; // R + wIn[1] = FROM_8_TO_16(*accum); accum++; // G + wIn[2] = FROM_8_TO_16(*accum); accum++; // B + + return accum; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +static +cmsUInt8Number* Unroll3BytesSkip1Swap(register _cmsTRANSFORM* info, + register cmsUInt16Number wIn[], + register cmsUInt8Number* accum, + register cmsUInt32Number Stride) +{ + accum++; // A + wIn[2] = FROM_8_TO_16(*accum); accum++; // B + wIn[1] = FROM_8_TO_16(*accum); accum++; // G + wIn[0] = FROM_8_TO_16(*accum); accum++; // R + + return accum; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +static +cmsUInt8Number* Unroll3BytesSkip1SwapSwapFirst(register _cmsTRANSFORM* info, + register cmsUInt16Number wIn[], + register cmsUInt8Number* accum, + register cmsUInt32Number Stride) +{ + wIn[2] = FROM_8_TO_16(*accum); accum++; // B + wIn[1] = FROM_8_TO_16(*accum); accum++; // G + wIn[0] = FROM_8_TO_16(*accum); accum++; // R + accum++; // A + + return accum; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +static +cmsUInt8Number* Unroll3BytesSkip1SwapFirst(register _cmsTRANSFORM* info, + register cmsUInt16Number wIn[], + register cmsUInt8Number* accum, + register cmsUInt32Number Stride) +{ + accum++; // A + wIn[0] = FROM_8_TO_16(*accum); accum++; // R + wIn[1] = FROM_8_TO_16(*accum); accum++; // G + wIn[2] = FROM_8_TO_16(*accum); accum++; // B + + return accum; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + + +// BRG +static +cmsUInt8Number* Unroll3BytesSwap(register _cmsTRANSFORM* info, + register cmsUInt16Number wIn[], + register cmsUInt8Number* accum, + register cmsUInt32Number Stride) +{ + wIn[2] = FROM_8_TO_16(*accum); accum++; // B + wIn[1] = FROM_8_TO_16(*accum); accum++; // G + wIn[0] = FROM_8_TO_16(*accum); accum++; // R + + return accum; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +static +cmsUInt8Number* UnrollLabV2_8(register _cmsTRANSFORM* info, + register cmsUInt16Number wIn[], + register cmsUInt8Number* accum, + register cmsUInt32Number Stride) +{ + wIn[0] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++; // L + wIn[1] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++; // a + wIn[2] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++; // b + + return accum; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +static +cmsUInt8Number* UnrollALabV2_8(register _cmsTRANSFORM* info, + register cmsUInt16Number wIn[], + register cmsUInt8Number* accum, + register cmsUInt32Number Stride) +{ + accum++; // A + wIn[0] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++; // L + wIn[1] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++; // a + wIn[2] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++; // b + + return accum; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +static +cmsUInt8Number* UnrollLabV2_16(register _cmsTRANSFORM* info, + register cmsUInt16Number wIn[], + register cmsUInt8Number* accum, + register cmsUInt32Number Stride) +{ + wIn[0] = FomLabV2ToLabV4(*(cmsUInt16Number*) accum); accum += 2; // L + wIn[1] = FomLabV2ToLabV4(*(cmsUInt16Number*) accum); accum += 2; // a + wIn[2] = FomLabV2ToLabV4(*(cmsUInt16Number*) accum); accum += 2; // b + + return accum; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +// for duplex +static +cmsUInt8Number* Unroll2Bytes(register _cmsTRANSFORM* info, + register cmsUInt16Number wIn[], + register cmsUInt8Number* accum, + register cmsUInt32Number Stride) +{ + wIn[0] = FROM_8_TO_16(*accum); accum++; // ch1 + wIn[1] = FROM_8_TO_16(*accum); accum++; // ch2 + + return accum; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + + + + +// Monochrome duplicates L into RGB for null-transforms +static +cmsUInt8Number* Unroll1Byte(register _cmsTRANSFORM* info, + register cmsUInt16Number wIn[], + register cmsUInt8Number* accum, + register cmsUInt32Number Stride) +{ + wIn[0] = wIn[1] = wIn[2] = FROM_8_TO_16(*accum); accum++; // L + + return accum; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + + +static +cmsUInt8Number* Unroll1ByteSkip1(register _cmsTRANSFORM* info, + register cmsUInt16Number wIn[], + register cmsUInt8Number* accum, + register cmsUInt32Number Stride) +{ + wIn[0] = wIn[1] = wIn[2] = FROM_8_TO_16(*accum); accum++; // L + accum += 1; + + return accum; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +static +cmsUInt8Number* Unroll1ByteSkip2(register _cmsTRANSFORM* info, + register cmsUInt16Number wIn[], + register cmsUInt8Number* accum, + register cmsUInt32Number Stride) +{ + wIn[0] = wIn[1] = wIn[2] = FROM_8_TO_16(*accum); accum++; // L + accum += 2; + + return accum; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +static +cmsUInt8Number* Unroll1ByteReversed(register _cmsTRANSFORM* info, + register cmsUInt16Number wIn[], + register cmsUInt8Number* accum, + register cmsUInt32Number Stride) +{ + wIn[0] = wIn[1] = wIn[2] = REVERSE_FLAVOR_16(FROM_8_TO_16(*accum)); accum++; // L + + return accum; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + + +static +cmsUInt8Number* UnrollAnyWords(register _cmsTRANSFORM* info, + register cmsUInt16Number wIn[], + register cmsUInt8Number* accum, + register cmsUInt32Number Stride) +{ + int nChan = T_CHANNELS(info -> InputFormat); + int SwapEndian = T_ENDIAN16(info -> InputFormat); + int DoSwap = T_DOSWAP(info ->InputFormat); + int Reverse = T_FLAVOR(info ->InputFormat); + int SwapFirst = T_SWAPFIRST(info -> InputFormat); + int Extra = T_EXTRA(info -> InputFormat); + int ExtraFirst = DoSwap ^ SwapFirst; + int i; + + if (ExtraFirst) { + accum += Extra * sizeof(cmsUInt16Number); + } + + for (i=0; i < nChan; i++) { + + int index = DoSwap ? (nChan - i - 1) : i; + cmsUInt16Number v = *(cmsUInt16Number*) accum; + + if (SwapEndian) + v = CHANGE_ENDIAN(v); + + wIn[index] = Reverse ? REVERSE_FLAVOR_16(v) : v; + + accum += sizeof(cmsUInt16Number); + } + + if (!ExtraFirst) { + accum += Extra * sizeof(cmsUInt16Number); + } + + if (Extra == 0 && SwapFirst) { + + cmsUInt16Number tmp = wIn[0]; + + memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsUInt16Number)); + wIn[nChan-1] = tmp; + } + + return accum; + + cmsUNUSED_PARAMETER(Stride); +} + +static +cmsUInt8Number* UnrollPlanarWords(register _cmsTRANSFORM* info, + register cmsUInt16Number wIn[], + register cmsUInt8Number* accum, + register cmsUInt32Number Stride) +{ + int nChan = T_CHANNELS(info -> InputFormat); + int DoSwap= T_DOSWAP(info ->InputFormat); + int Reverse= T_FLAVOR(info ->InputFormat); + int SwapEndian = T_ENDIAN16(info -> InputFormat); + int i; + cmsUInt8Number* Init = accum; + + if (DoSwap) { + accum += T_EXTRA(info -> InputFormat) * Stride * sizeof(cmsUInt16Number); + } + + for (i=0; i < nChan; i++) { + + int index = DoSwap ? (nChan - i - 1) : i; + cmsUInt16Number v = *(cmsUInt16Number*) accum; + + if (SwapEndian) + v = CHANGE_ENDIAN(v); + + wIn[index] = Reverse ? REVERSE_FLAVOR_16(v) : v; + + accum += Stride * sizeof(cmsUInt16Number); + } + + return (Init + sizeof(cmsUInt16Number)); +} + + +static +cmsUInt8Number* Unroll4Words(register _cmsTRANSFORM* info, + register cmsUInt16Number wIn[], + register cmsUInt8Number* accum, + register cmsUInt32Number Stride) +{ + wIn[0] = *(cmsUInt16Number*) accum; accum+= 2; // C + wIn[1] = *(cmsUInt16Number*) accum; accum+= 2; // M + wIn[2] = *(cmsUInt16Number*) accum; accum+= 2; // Y + wIn[3] = *(cmsUInt16Number*) accum; accum+= 2; // K + + return accum; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +static +cmsUInt8Number* Unroll4WordsReverse(register _cmsTRANSFORM* info, + register cmsUInt16Number wIn[], + register cmsUInt8Number* accum, + register cmsUInt32Number Stride) +{ + wIn[0] = REVERSE_FLAVOR_16(*(cmsUInt16Number*) accum); accum+= 2; // C + wIn[1] = REVERSE_FLAVOR_16(*(cmsUInt16Number*) accum); accum+= 2; // M + wIn[2] = REVERSE_FLAVOR_16(*(cmsUInt16Number*) accum); accum+= 2; // Y + wIn[3] = REVERSE_FLAVOR_16(*(cmsUInt16Number*) accum); accum+= 2; // K + + return accum; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +static +cmsUInt8Number* Unroll4WordsSwapFirst(register _cmsTRANSFORM* info, + register cmsUInt16Number wIn[], + register cmsUInt8Number* accum, + register cmsUInt32Number Stride) +{ + wIn[3] = *(cmsUInt16Number*) accum; accum+= 2; // K + wIn[0] = *(cmsUInt16Number*) accum; accum+= 2; // C + wIn[1] = *(cmsUInt16Number*) accum; accum+= 2; // M + wIn[2] = *(cmsUInt16Number*) accum; accum+= 2; // Y + + return accum; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +// KYMC +static +cmsUInt8Number* Unroll4WordsSwap(register _cmsTRANSFORM* info, + register cmsUInt16Number wIn[], + register cmsUInt8Number* accum, + register cmsUInt32Number Stride) +{ + wIn[3] = *(cmsUInt16Number*) accum; accum+= 2; // K + wIn[2] = *(cmsUInt16Number*) accum; accum+= 2; // Y + wIn[1] = *(cmsUInt16Number*) accum; accum+= 2; // M + wIn[0] = *(cmsUInt16Number*) accum; accum+= 2; // C + + return accum; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +static +cmsUInt8Number* Unroll4WordsSwapSwapFirst(register _cmsTRANSFORM* info, + register cmsUInt16Number wIn[], + register cmsUInt8Number* accum, + register cmsUInt32Number Stride) +{ + wIn[2] = *(cmsUInt16Number*) accum; accum+= 2; // K + wIn[1] = *(cmsUInt16Number*) accum; accum+= 2; // Y + wIn[0] = *(cmsUInt16Number*) accum; accum+= 2; // M + wIn[3] = *(cmsUInt16Number*) accum; accum+= 2; // C + + return accum; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +static +cmsUInt8Number* Unroll3Words(register _cmsTRANSFORM* info, + register cmsUInt16Number wIn[], + register cmsUInt8Number* accum, + register cmsUInt32Number Stride) +{ + wIn[0] = *(cmsUInt16Number*) accum; accum+= 2; // C R + wIn[1] = *(cmsUInt16Number*) accum; accum+= 2; // M G + wIn[2] = *(cmsUInt16Number*) accum; accum+= 2; // Y B + + return accum; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +static +cmsUInt8Number* Unroll3WordsSwap(register _cmsTRANSFORM* info, + register cmsUInt16Number wIn[], + register cmsUInt8Number* accum, + register cmsUInt32Number Stride) +{ + wIn[2] = *(cmsUInt16Number*) accum; accum+= 2; // C R + wIn[1] = *(cmsUInt16Number*) accum; accum+= 2; // M G + wIn[0] = *(cmsUInt16Number*) accum; accum+= 2; // Y B + + return accum; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +static +cmsUInt8Number* Unroll3WordsSkip1Swap(register _cmsTRANSFORM* info, + register cmsUInt16Number wIn[], + register cmsUInt8Number* accum, + register cmsUInt32Number Stride) +{ + accum += 2; // A + wIn[2] = *(cmsUInt16Number*) accum; accum += 2; // R + wIn[1] = *(cmsUInt16Number*) accum; accum += 2; // G + wIn[0] = *(cmsUInt16Number*) accum; accum += 2; // B + + return accum; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +static +cmsUInt8Number* Unroll3WordsSkip1SwapFirst(register _cmsTRANSFORM* info, + register cmsUInt16Number wIn[], + register cmsUInt8Number* accum, + register cmsUInt32Number Stride) +{ + accum += 2; // A + wIn[0] = *(cmsUInt16Number*) accum; accum += 2; // R + wIn[1] = *(cmsUInt16Number*) accum; accum += 2; // G + wIn[2] = *(cmsUInt16Number*) accum; accum += 2; // B + + return accum; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +static +cmsUInt8Number* Unroll1Word(register _cmsTRANSFORM* info, + register cmsUInt16Number wIn[], + register cmsUInt8Number* accum, + register cmsUInt32Number Stride) +{ + wIn[0] = wIn[1] = wIn[2] = *(cmsUInt16Number*) accum; accum+= 2; // L + + return accum; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +static +cmsUInt8Number* Unroll1WordReversed(register _cmsTRANSFORM* info, + register cmsUInt16Number wIn[], + register cmsUInt8Number* accum, + register cmsUInt32Number Stride) +{ + wIn[0] = wIn[1] = wIn[2] = REVERSE_FLAVOR_16(*(cmsUInt16Number*) accum); accum+= 2; + + return accum; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +static +cmsUInt8Number* Unroll1WordSkip3(register _cmsTRANSFORM* info, + register cmsUInt16Number wIn[], + register cmsUInt8Number* accum, + register cmsUInt32Number Stride) +{ + wIn[0] = wIn[1] = wIn[2] = *(cmsUInt16Number*) accum; + + accum += 8; + + return accum; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +static +cmsUInt8Number* Unroll2Words(register _cmsTRANSFORM* info, + register cmsUInt16Number wIn[], + register cmsUInt8Number* accum, + register cmsUInt32Number Stride) +{ + wIn[0] = *(cmsUInt16Number*) accum; accum += 2; // ch1 + wIn[1] = *(cmsUInt16Number*) accum; accum += 2; // ch2 + + return accum; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + + +// This is a conversion of Lab double to 16 bits +static +cmsUInt8Number* UnrollLabDoubleTo16(register _cmsTRANSFORM* info, + register cmsUInt16Number wIn[], + register cmsUInt8Number* accum, + register cmsUInt32Number Stride) +{ + if (T_PLANAR(info -> InputFormat)) { + + cmsFloat64Number* Pt = (cmsFloat64Number*) accum; + + cmsCIELab Lab; + + Lab.L = Pt[0]; + Lab.a = Pt[Stride]; + Lab.b = Pt[Stride*2]; + + cmsFloat2LabEncoded(wIn, &Lab); + return accum + sizeof(cmsFloat64Number); + } + else { + + cmsFloat2LabEncoded(wIn, (cmsCIELab*) accum); + accum += sizeof(cmsCIELab) + T_EXTRA(info ->InputFormat) * sizeof(cmsFloat64Number); + return accum; + } +} + + +// This is a conversion of Lab float to 16 bits +static +cmsUInt8Number* UnrollLabFloatTo16(register _cmsTRANSFORM* info, + register cmsUInt16Number wIn[], + register cmsUInt8Number* accum, + register cmsUInt32Number Stride) +{ + cmsCIELab Lab; + + if (T_PLANAR(info -> InputFormat)) { + + cmsFloat32Number* Pt = (cmsFloat32Number*) accum; + + + Lab.L = Pt[0]; + Lab.a = Pt[Stride]; + Lab.b = Pt[Stride*2]; + + cmsFloat2LabEncoded(wIn, &Lab); + return accum + sizeof(cmsFloat32Number); + } + else { + + Lab.L = ((cmsFloat32Number*) accum)[0]; + Lab.a = ((cmsFloat32Number*) accum)[1]; + Lab.b = ((cmsFloat32Number*) accum)[2]; + + cmsFloat2LabEncoded(wIn, &Lab); + accum += (3 + T_EXTRA(info ->InputFormat)) * sizeof(cmsFloat32Number); + return accum; + } +} + +// This is a conversion of XYZ double to 16 bits +static +cmsUInt8Number* UnrollXYZDoubleTo16(register _cmsTRANSFORM* info, + register cmsUInt16Number wIn[], + register cmsUInt8Number* accum, + register cmsUInt32Number Stride) +{ + if (T_PLANAR(info -> InputFormat)) { + + cmsFloat64Number* Pt = (cmsFloat64Number*) accum; + cmsCIEXYZ XYZ; + + XYZ.X = Pt[0]; + XYZ.Y = Pt[Stride]; + XYZ.Z = Pt[Stride*2]; + cmsFloat2XYZEncoded(wIn, &XYZ); + + return accum + sizeof(cmsFloat64Number); + + } + + else { + cmsFloat2XYZEncoded(wIn, (cmsCIEXYZ*) accum); + accum += sizeof(cmsCIEXYZ) + T_EXTRA(info ->InputFormat) * sizeof(cmsFloat64Number); + + return accum; + } +} + +// Check if space is marked as ink +cmsINLINE cmsBool IsInkSpace(cmsUInt32Number Type) +{ + switch (T_COLORSPACE(Type)) { + + case PT_CMY: + case PT_CMYK: + case PT_MCH5: + case PT_MCH6: + case PT_MCH7: + case PT_MCH8: + case PT_MCH9: + case PT_MCH10: + case PT_MCH11: + case PT_MCH12: + case PT_MCH13: + case PT_MCH14: + case PT_MCH15: return TRUE; + + default: return FALSE; + } +} + +// Inks does come in percentage, remaining cases are between 0..1.0, again to 16 bits +static +cmsUInt8Number* UnrollDoubleTo16(register _cmsTRANSFORM* info, + register cmsUInt16Number wIn[], + register cmsUInt8Number* accum, + register cmsUInt32Number Stride) +{ + + int nChan = T_CHANNELS(info -> InputFormat); + int DoSwap = T_DOSWAP(info ->InputFormat); + int Reverse = T_FLAVOR(info ->InputFormat); + int SwapFirst = T_SWAPFIRST(info -> InputFormat); + int Extra = T_EXTRA(info -> InputFormat); + int ExtraFirst = DoSwap ^ SwapFirst; + int Planar = T_PLANAR(info -> InputFormat); + cmsFloat64Number v; + cmsUInt16Number vi; + int i, start = 0; + cmsFloat64Number maximum = IsInkSpace(info ->InputFormat) ? 655.35 : 65535.0; + + + if (ExtraFirst) + start = Extra; + + for (i=0; i < nChan; i++) { + + int index = DoSwap ? (nChan - i - 1) : i; + + if (Planar) + v = (cmsFloat32Number) ((cmsFloat64Number*) accum)[(i + start) * Stride]; + else + v = (cmsFloat32Number) ((cmsFloat64Number*) accum)[i + start]; + + vi = _cmsQuickSaturateWord(v * maximum); + + if (Reverse) + vi = REVERSE_FLAVOR_16(vi); + + wIn[index] = vi; + } + + + if (Extra == 0 && SwapFirst) { + cmsUInt16Number tmp = wIn[0]; + + memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsUInt16Number)); + wIn[nChan-1] = tmp; + } + + if (T_PLANAR(info -> InputFormat)) + return accum + sizeof(cmsFloat64Number); + else + return accum + (nChan + Extra) * sizeof(cmsFloat64Number); +} + + + +static +cmsUInt8Number* UnrollFloatTo16(register _cmsTRANSFORM* info, + register cmsUInt16Number wIn[], + register cmsUInt8Number* accum, + register cmsUInt32Number Stride) +{ + + int nChan = T_CHANNELS(info -> InputFormat); + int DoSwap = T_DOSWAP(info ->InputFormat); + int Reverse = T_FLAVOR(info ->InputFormat); + int SwapFirst = T_SWAPFIRST(info -> InputFormat); + int Extra = T_EXTRA(info -> InputFormat); + int ExtraFirst = DoSwap ^ SwapFirst; + int Planar = T_PLANAR(info -> InputFormat); + cmsFloat32Number v; + cmsUInt16Number vi; + int i, start = 0; + cmsFloat64Number maximum = IsInkSpace(info ->InputFormat) ? 655.35 : 65535.0; + + + if (ExtraFirst) + start = Extra; + + for (i=0; i < nChan; i++) { + + int index = DoSwap ? (nChan - i - 1) : i; + + if (Planar) + v = (cmsFloat32Number) ((cmsFloat32Number*) accum)[(i + start) * Stride]; + else + v = (cmsFloat32Number) ((cmsFloat32Number*) accum)[i + start]; + + vi = _cmsQuickSaturateWord(v * maximum); + + if (Reverse) + vi = REVERSE_FLAVOR_16(vi); + + wIn[index] = vi; + } + + + if (Extra == 0 && SwapFirst) { + cmsUInt16Number tmp = wIn[0]; + + memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsUInt16Number)); + wIn[nChan-1] = tmp; + } + + if (T_PLANAR(info -> InputFormat)) + return accum + sizeof(cmsFloat32Number); + else + return accum + (nChan + Extra) * sizeof(cmsFloat32Number); +} + + + + +// For 1 channel, we need to duplicate data (it comes in 0..1.0 range) +static +cmsUInt8Number* UnrollDouble1Chan(register _cmsTRANSFORM* info, + register cmsUInt16Number wIn[], + register cmsUInt8Number* accum, + register cmsUInt32Number Stride) +{ + cmsFloat64Number* Inks = (cmsFloat64Number*) accum; + + wIn[0] = wIn[1] = wIn[2] = _cmsQuickSaturateWord(Inks[0] * 65535.0); + + return accum + sizeof(cmsFloat64Number); + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +//------------------------------------------------------------------------------------------------------------------- + +// For anything going from cmsFloat32Number +static +cmsUInt8Number* UnrollFloatsToFloat(_cmsTRANSFORM* info, + cmsFloat32Number wIn[], + cmsUInt8Number* accum, + cmsUInt32Number Stride) +{ + + int nChan = T_CHANNELS(info -> InputFormat); + int DoSwap = T_DOSWAP(info ->InputFormat); + int Reverse = T_FLAVOR(info ->InputFormat); + int SwapFirst = T_SWAPFIRST(info -> InputFormat); + int Extra = T_EXTRA(info -> InputFormat); + int ExtraFirst = DoSwap ^ SwapFirst; + int Planar = T_PLANAR(info -> InputFormat); + cmsFloat32Number v; + int i, start = 0; + cmsFloat32Number maximum = IsInkSpace(info ->InputFormat) ? 100.0F : 1.0F; + + + if (ExtraFirst) + start = Extra; + + for (i=0; i < nChan; i++) { + + int index = DoSwap ? (nChan - i - 1) : i; + + if (Planar) + v = (cmsFloat32Number) ((cmsFloat32Number*) accum)[(i + start) * Stride]; + else + v = (cmsFloat32Number) ((cmsFloat32Number*) accum)[i + start]; + + v /= maximum; + + wIn[index] = Reverse ? 1 - v : v; + } + + + if (Extra == 0 && SwapFirst) { + cmsFloat32Number tmp = wIn[0]; + + memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsFloat32Number)); + wIn[nChan-1] = tmp; + } + + if (T_PLANAR(info -> InputFormat)) + return accum + sizeof(cmsFloat32Number); + else + return accum + (nChan + Extra) * sizeof(cmsFloat32Number); +} + +// For anything going from double + +static +cmsUInt8Number* UnrollDoublesToFloat(_cmsTRANSFORM* info, + cmsFloat32Number wIn[], + cmsUInt8Number* accum, + cmsUInt32Number Stride) +{ + + int nChan = T_CHANNELS(info -> InputFormat); + int DoSwap = T_DOSWAP(info ->InputFormat); + int Reverse = T_FLAVOR(info ->InputFormat); + int SwapFirst = T_SWAPFIRST(info -> InputFormat); + int Extra = T_EXTRA(info -> InputFormat); + int ExtraFirst = DoSwap ^ SwapFirst; + int Planar = T_PLANAR(info -> InputFormat); + cmsFloat64Number v; + int i, start = 0; + cmsFloat64Number maximum = IsInkSpace(info ->InputFormat) ? 100.0 : 1.0; + + + if (ExtraFirst) + start = Extra; + + for (i=0; i < nChan; i++) { + + int index = DoSwap ? (nChan - i - 1) : i; + + if (Planar) + v = (cmsFloat64Number) ((cmsFloat64Number*) accum)[(i + start) * Stride]; + else + v = (cmsFloat64Number) ((cmsFloat64Number*) accum)[i + start]; + + v /= maximum; + + wIn[index] = (cmsFloat32Number) (Reverse ? 1.0 - v : v); + } + + + if (Extra == 0 && SwapFirst) { + cmsFloat32Number tmp = wIn[0]; + + memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsFloat32Number)); + wIn[nChan-1] = tmp; + } + + if (T_PLANAR(info -> InputFormat)) + return accum + sizeof(cmsFloat64Number); + else + return accum + (nChan + Extra) * sizeof(cmsFloat64Number); +} + + + +// From Lab double to cmsFloat32Number +static +cmsUInt8Number* UnrollLabDoubleToFloat(_cmsTRANSFORM* info, + cmsFloat32Number wIn[], + cmsUInt8Number* accum, + cmsUInt32Number Stride) +{ + cmsFloat64Number* Pt = (cmsFloat64Number*) accum; + + if (T_PLANAR(info -> InputFormat)) { + + wIn[0] = (cmsFloat32Number) (Pt[0] / 100.0); // from 0..100 to 0..1 + wIn[1] = (cmsFloat32Number) ((Pt[Stride] + 128) / 255.0); // form -128..+127 to 0..1 + wIn[2] = (cmsFloat32Number) ((Pt[Stride*2] + 128) / 255.0); + + return accum + sizeof(cmsFloat64Number); + } + else { + + wIn[0] = (cmsFloat32Number) (Pt[0] / 100.0); // from 0..100 to 0..1 + wIn[1] = (cmsFloat32Number) ((Pt[1] + 128) / 255.0); // form -128..+127 to 0..1 + wIn[2] = (cmsFloat32Number) ((Pt[2] + 128) / 255.0); + + accum += sizeof(cmsFloat64Number)*(3 + T_EXTRA(info ->InputFormat)); + return accum; + } +} + +// From Lab double to cmsFloat32Number +static +cmsUInt8Number* UnrollLabFloatToFloat(_cmsTRANSFORM* info, + cmsFloat32Number wIn[], + cmsUInt8Number* accum, + cmsUInt32Number Stride) +{ + cmsFloat32Number* Pt = (cmsFloat32Number*) accum; + + if (T_PLANAR(info -> InputFormat)) { + + wIn[0] = (cmsFloat32Number) (Pt[0] / 100.0); // from 0..100 to 0..1 + wIn[1] = (cmsFloat32Number) ((Pt[Stride] + 128) / 255.0); // form -128..+127 to 0..1 + wIn[2] = (cmsFloat32Number) ((Pt[Stride*2] + 128) / 255.0); + + return accum + sizeof(cmsFloat32Number); + } + else { + + wIn[0] = (cmsFloat32Number) (Pt[0] / 100.0); // from 0..100 to 0..1 + wIn[1] = (cmsFloat32Number) ((Pt[1] + 128) / 255.0); // form -128..+127 to 0..1 + wIn[2] = (cmsFloat32Number) ((Pt[2] + 128) / 255.0); + + accum += sizeof(cmsFloat32Number)*(3 + T_EXTRA(info ->InputFormat)); + return accum; + } +} + + + +// 1.15 fixed point, that means maximum value is MAX_ENCODEABLE_XYZ (0xFFFF) +static +cmsUInt8Number* UnrollXYZDoubleToFloat(_cmsTRANSFORM* info, + cmsFloat32Number wIn[], + cmsUInt8Number* accum, + cmsUInt32Number Stride) +{ + cmsFloat64Number* Pt = (cmsFloat64Number*) accum; + + if (T_PLANAR(info -> InputFormat)) { + + wIn[0] = (cmsFloat32Number) (Pt[0] / MAX_ENCODEABLE_XYZ); + wIn[1] = (cmsFloat32Number) (Pt[Stride] / MAX_ENCODEABLE_XYZ); + wIn[2] = (cmsFloat32Number) (Pt[Stride*2] / MAX_ENCODEABLE_XYZ); + + return accum + sizeof(cmsFloat64Number); + } + else { + + wIn[0] = (cmsFloat32Number) (Pt[0] / MAX_ENCODEABLE_XYZ); + wIn[1] = (cmsFloat32Number) (Pt[1] / MAX_ENCODEABLE_XYZ); + wIn[2] = (cmsFloat32Number) (Pt[2] / MAX_ENCODEABLE_XYZ); + + accum += sizeof(cmsFloat64Number)*(3 + T_EXTRA(info ->InputFormat)); + return accum; + } +} + +static +cmsUInt8Number* UnrollXYZFloatToFloat(_cmsTRANSFORM* info, + cmsFloat32Number wIn[], + cmsUInt8Number* accum, + cmsUInt32Number Stride) +{ + cmsFloat32Number* Pt = (cmsFloat32Number*) accum; + + if (T_PLANAR(info -> InputFormat)) { + + wIn[0] = (cmsFloat32Number) (Pt[0] / MAX_ENCODEABLE_XYZ); + wIn[1] = (cmsFloat32Number) (Pt[Stride] / MAX_ENCODEABLE_XYZ); + wIn[2] = (cmsFloat32Number) (Pt[Stride*2] / MAX_ENCODEABLE_XYZ); + + return accum + sizeof(cmsFloat32Number); + } + else { + + wIn[0] = (cmsFloat32Number) (Pt[0] / MAX_ENCODEABLE_XYZ); + wIn[1] = (cmsFloat32Number) (Pt[1] / MAX_ENCODEABLE_XYZ); + wIn[2] = (cmsFloat32Number) (Pt[2] / MAX_ENCODEABLE_XYZ); + + accum += sizeof(cmsFloat32Number)*(3 + T_EXTRA(info ->InputFormat)); + return accum; + } +} + + + +// Packing routines ----------------------------------------------------------------------------------------------------------- + + +// Generic chunky for byte + +static +cmsUInt8Number* PackAnyBytes(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + int nChan = T_CHANNELS(info -> OutputFormat); + int DoSwap = T_DOSWAP(info ->OutputFormat); + int Reverse = T_FLAVOR(info ->OutputFormat); + int Extra = T_EXTRA(info -> OutputFormat); + int SwapFirst = T_SWAPFIRST(info -> OutputFormat); + int ExtraFirst = DoSwap ^ SwapFirst; + cmsUInt8Number* swap1; + cmsUInt8Number v = 0; + int i; + + swap1 = output; + + if (ExtraFirst) { + output += Extra; + } + + for (i=0; i < nChan; i++) { + + int index = DoSwap ? (nChan - i - 1) : i; + + v = FROM_16_TO_8(wOut[index]); + + if (Reverse) + v = REVERSE_FLAVOR_8(v); + + *output++ = v; + } + + if (!ExtraFirst) { + output += Extra; + } + + if (Extra == 0 && SwapFirst) { + + memmove(swap1 + 1, swap1, nChan-1); + *swap1 = v; + } + + + return output; + + cmsUNUSED_PARAMETER(Stride); +} + + + +static +cmsUInt8Number* PackAnyWords(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + int nChan = T_CHANNELS(info -> OutputFormat); + int SwapEndian = T_ENDIAN16(info -> InputFormat); + int DoSwap = T_DOSWAP(info ->OutputFormat); + int Reverse = T_FLAVOR(info ->OutputFormat); + int Extra = T_EXTRA(info -> OutputFormat); + int SwapFirst = T_SWAPFIRST(info -> OutputFormat); + int ExtraFirst = DoSwap ^ SwapFirst; + cmsUInt16Number* swap1; + cmsUInt16Number v = 0; + int i; + + swap1 = (cmsUInt16Number*) output; + + if (ExtraFirst) { + output += Extra * sizeof(cmsUInt16Number); + } + + for (i=0; i < nChan; i++) { + + int index = DoSwap ? (nChan - i - 1) : i; + + v = wOut[index]; + + if (SwapEndian) + v = CHANGE_ENDIAN(v); + + if (Reverse) + v = REVERSE_FLAVOR_16(v); + + *(cmsUInt16Number*) output = v; + + output += sizeof(cmsUInt16Number); + } + + if (!ExtraFirst) { + output += Extra * sizeof(cmsUInt16Number); + } + + if (Extra == 0 && SwapFirst) { + + memmove(swap1 + 1, swap1, (nChan-1)* sizeof(cmsUInt16Number)); + *swap1 = v; + } + + + return output; + + cmsUNUSED_PARAMETER(Stride); +} + + +static +cmsUInt8Number* PackPlanarBytes(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + int nChan = T_CHANNELS(info -> OutputFormat); + int DoSwap = T_DOSWAP(info ->OutputFormat); + int SwapFirst = T_SWAPFIRST(info ->OutputFormat); + int Reverse = T_FLAVOR(info ->OutputFormat); + int i; + cmsUInt8Number* Init = output; + + + if (DoSwap ^ SwapFirst) { + output += T_EXTRA(info -> OutputFormat) * Stride; + } + + + for (i=0; i < nChan; i++) { + + int index = DoSwap ? (nChan - i - 1) : i; + cmsUInt8Number v = FROM_16_TO_8(wOut[index]); + + *(cmsUInt8Number*) output = (cmsUInt8Number) (Reverse ? REVERSE_FLAVOR_8(v) : v); + output += Stride; + } + + return (Init + 1); + + cmsUNUSED_PARAMETER(Stride); +} + + +static +cmsUInt8Number* PackPlanarWords(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + int nChan = T_CHANNELS(info -> OutputFormat); + int DoSwap = T_DOSWAP(info ->OutputFormat); + int Reverse= T_FLAVOR(info ->OutputFormat); + int SwapEndian = T_ENDIAN16(info -> OutputFormat); + int i; + cmsUInt8Number* Init = output; + cmsUInt16Number v; + + if (DoSwap) { + output += T_EXTRA(info -> OutputFormat) * Stride * sizeof(cmsUInt16Number); + } + + for (i=0; i < nChan; i++) { + + int index = DoSwap ? (nChan - i - 1) : i; + + v = wOut[index]; + + if (SwapEndian) + v = CHANGE_ENDIAN(v); + + if (Reverse) + v = REVERSE_FLAVOR_16(v); + + *(cmsUInt16Number*) output = v; + output += (Stride * sizeof(cmsUInt16Number)); + } + + return (Init + sizeof(cmsUInt16Number)); +} + +// CMYKcm (unrolled for speed) + +static +cmsUInt8Number* Pack6Bytes(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + *output++ = FROM_16_TO_8(wOut[0]); + *output++ = FROM_16_TO_8(wOut[1]); + *output++ = FROM_16_TO_8(wOut[2]); + *output++ = FROM_16_TO_8(wOut[3]); + *output++ = FROM_16_TO_8(wOut[4]); + *output++ = FROM_16_TO_8(wOut[5]); + + return output; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +// KCMYcm + +static +cmsUInt8Number* Pack6BytesSwap(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + *output++ = FROM_16_TO_8(wOut[5]); + *output++ = FROM_16_TO_8(wOut[4]); + *output++ = FROM_16_TO_8(wOut[3]); + *output++ = FROM_16_TO_8(wOut[2]); + *output++ = FROM_16_TO_8(wOut[1]); + *output++ = FROM_16_TO_8(wOut[0]); + + return output; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +// CMYKcm +static +cmsUInt8Number* Pack6Words(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + *(cmsUInt16Number*) output = wOut[0]; + output+= 2; + *(cmsUInt16Number*) output = wOut[1]; + output+= 2; + *(cmsUInt16Number*) output = wOut[2]; + output+= 2; + *(cmsUInt16Number*) output = wOut[3]; + output+= 2; + *(cmsUInt16Number*) output = wOut[4]; + output+= 2; + *(cmsUInt16Number*) output = wOut[5]; + output+= 2; + + return output; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +// KCMYcm +static +cmsUInt8Number* Pack6WordsSwap(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + *(cmsUInt16Number*) output = wOut[5]; + output+= 2; + *(cmsUInt16Number*) output = wOut[4]; + output+= 2; + *(cmsUInt16Number*) output = wOut[3]; + output+= 2; + *(cmsUInt16Number*) output = wOut[2]; + output+= 2; + *(cmsUInt16Number*) output = wOut[1]; + output+= 2; + *(cmsUInt16Number*) output = wOut[0]; + output+= 2; + + return output; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + + +static +cmsUInt8Number* Pack4Bytes(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + *output++ = FROM_16_TO_8(wOut[0]); + *output++ = FROM_16_TO_8(wOut[1]); + *output++ = FROM_16_TO_8(wOut[2]); + *output++ = FROM_16_TO_8(wOut[3]); + + return output; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +static +cmsUInt8Number* Pack4BytesReverse(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + *output++ = REVERSE_FLAVOR_8(FROM_16_TO_8(wOut[0])); + *output++ = REVERSE_FLAVOR_8(FROM_16_TO_8(wOut[1])); + *output++ = REVERSE_FLAVOR_8(FROM_16_TO_8(wOut[2])); + *output++ = REVERSE_FLAVOR_8(FROM_16_TO_8(wOut[3])); + + return output; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + + +static +cmsUInt8Number* Pack4BytesSwapFirst(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + *output++ = FROM_16_TO_8(wOut[3]); + *output++ = FROM_16_TO_8(wOut[0]); + *output++ = FROM_16_TO_8(wOut[1]); + *output++ = FROM_16_TO_8(wOut[2]); + + return output; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +// ABGR +static +cmsUInt8Number* Pack4BytesSwap(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + *output++ = FROM_16_TO_8(wOut[3]); + *output++ = FROM_16_TO_8(wOut[2]); + *output++ = FROM_16_TO_8(wOut[1]); + *output++ = FROM_16_TO_8(wOut[0]); + + return output; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +static +cmsUInt8Number* Pack4BytesSwapSwapFirst(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + *output++ = FROM_16_TO_8(wOut[2]); + *output++ = FROM_16_TO_8(wOut[1]); + *output++ = FROM_16_TO_8(wOut[0]); + *output++ = FROM_16_TO_8(wOut[3]); + + return output; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +static +cmsUInt8Number* Pack4Words(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + *(cmsUInt16Number*) output = wOut[0]; + output+= 2; + *(cmsUInt16Number*) output = wOut[1]; + output+= 2; + *(cmsUInt16Number*) output = wOut[2]; + output+= 2; + *(cmsUInt16Number*) output = wOut[3]; + output+= 2; + + return output; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +static +cmsUInt8Number* Pack4WordsReverse(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + *(cmsUInt16Number*) output = REVERSE_FLAVOR_16(wOut[0]); + output+= 2; + *(cmsUInt16Number*) output = REVERSE_FLAVOR_16(wOut[1]); + output+= 2; + *(cmsUInt16Number*) output = REVERSE_FLAVOR_16(wOut[2]); + output+= 2; + *(cmsUInt16Number*) output = REVERSE_FLAVOR_16(wOut[3]); + output+= 2; + + return output; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +// ABGR +static +cmsUInt8Number* Pack4WordsSwap(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + *(cmsUInt16Number*) output = wOut[3]; + output+= 2; + *(cmsUInt16Number*) output = wOut[2]; + output+= 2; + *(cmsUInt16Number*) output = wOut[1]; + output+= 2; + *(cmsUInt16Number*) output = wOut[0]; + output+= 2; + + return output; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +// CMYK +static +cmsUInt8Number* Pack4WordsBigEndian(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[0]); + output+= 2; + *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[1]); + output+= 2; + *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[2]); + output+= 2; + *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[3]); + output+= 2; + + return output; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + + +static +cmsUInt8Number* PackLabV2_8(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + *output++ = FROM_16_TO_8(FomLabV4ToLabV2(wOut[0])); + *output++ = FROM_16_TO_8(FomLabV4ToLabV2(wOut[1])); + *output++ = FROM_16_TO_8(FomLabV4ToLabV2(wOut[2])); + + return output; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +static +cmsUInt8Number* PackALabV2_8(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + output++; + *output++ = FROM_16_TO_8(FomLabV4ToLabV2(wOut[0])); + *output++ = FROM_16_TO_8(FomLabV4ToLabV2(wOut[1])); + *output++ = FROM_16_TO_8(FomLabV4ToLabV2(wOut[2])); + + return output; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +static +cmsUInt8Number* PackLabV2_16(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + *(cmsUInt16Number*) output = FomLabV4ToLabV2(wOut[0]); + output += 2; + *(cmsUInt16Number*) output = FomLabV4ToLabV2(wOut[1]); + output += 2; + *(cmsUInt16Number*) output = FomLabV4ToLabV2(wOut[2]); + output += 2; + + return output; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +static +cmsUInt8Number* Pack3Bytes(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + *output++ = FROM_16_TO_8(wOut[0]); + *output++ = FROM_16_TO_8(wOut[1]); + *output++ = FROM_16_TO_8(wOut[2]); + + return output; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +static +cmsUInt8Number* Pack3BytesOptimized(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + *output++ = (wOut[0] & 0xFF); + *output++ = (wOut[1] & 0xFF); + *output++ = (wOut[2] & 0xFF); + + return output; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +static +cmsUInt8Number* Pack3BytesSwap(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + *output++ = FROM_16_TO_8(wOut[2]); + *output++ = FROM_16_TO_8(wOut[1]); + *output++ = FROM_16_TO_8(wOut[0]); + + return output; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +static +cmsUInt8Number* Pack3BytesSwapOptimized(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + *output++ = (wOut[2] & 0xFF); + *output++ = (wOut[1] & 0xFF); + *output++ = (wOut[0] & 0xFF); + + return output; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + + +static +cmsUInt8Number* Pack3Words(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + *(cmsUInt16Number*) output = wOut[0]; + output+= 2; + *(cmsUInt16Number*) output = wOut[1]; + output+= 2; + *(cmsUInt16Number*) output = wOut[2]; + output+= 2; + + return output; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +static +cmsUInt8Number* Pack3WordsSwap(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + *(cmsUInt16Number*) output = wOut[2]; + output+= 2; + *(cmsUInt16Number*) output = wOut[1]; + output+= 2; + *(cmsUInt16Number*) output = wOut[0]; + output+= 2; + + return output; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +static +cmsUInt8Number* Pack3WordsBigEndian(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[0]); + output+= 2; + *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[1]); + output+= 2; + *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[2]); + output+= 2; + + return output; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +static +cmsUInt8Number* Pack3BytesAndSkip1(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + *output++ = FROM_16_TO_8(wOut[0]); + *output++ = FROM_16_TO_8(wOut[1]); + *output++ = FROM_16_TO_8(wOut[2]); + output++; + + return output; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +static +cmsUInt8Number* Pack3BytesAndSkip1Optimized(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + *output++ = (wOut[0] & 0xFF); + *output++ = (wOut[1] & 0xFF); + *output++ = (wOut[2] & 0xFF); + output++; + + return output; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + + +static +cmsUInt8Number* Pack3BytesAndSkip1SwapFirst(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + output++; + *output++ = FROM_16_TO_8(wOut[0]); + *output++ = FROM_16_TO_8(wOut[1]); + *output++ = FROM_16_TO_8(wOut[2]); + + return output; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +static +cmsUInt8Number* Pack3BytesAndSkip1SwapFirstOptimized(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + output++; + *output++ = (wOut[0] & 0xFF); + *output++ = (wOut[1] & 0xFF); + *output++ = (wOut[2] & 0xFF); + + return output; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +static +cmsUInt8Number* Pack3BytesAndSkip1Swap(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + output++; + *output++ = FROM_16_TO_8(wOut[2]); + *output++ = FROM_16_TO_8(wOut[1]); + *output++ = FROM_16_TO_8(wOut[0]); + + return output; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +static +cmsUInt8Number* Pack3BytesAndSkip1SwapOptimized(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + output++; + *output++ = (wOut[2] & 0xFF); + *output++ = (wOut[1] & 0xFF); + *output++ = (wOut[0] & 0xFF); + + return output; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + + +static +cmsUInt8Number* Pack3BytesAndSkip1SwapSwapFirst(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + *output++ = FROM_16_TO_8(wOut[2]); + *output++ = FROM_16_TO_8(wOut[1]); + *output++ = FROM_16_TO_8(wOut[0]); + output++; + + return output; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +static +cmsUInt8Number* Pack3BytesAndSkip1SwapSwapFirstOptimized(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + *output++ = (wOut[2] & 0xFF); + *output++ = (wOut[1] & 0xFF); + *output++ = (wOut[0] & 0xFF); + output++; + + return output; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +static +cmsUInt8Number* Pack3WordsAndSkip1(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + *(cmsUInt16Number*) output = wOut[0]; + output+= 2; + *(cmsUInt16Number*) output = wOut[1]; + output+= 2; + *(cmsUInt16Number*) output = wOut[2]; + output+= 2; + output+= 2; + + return output; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +static +cmsUInt8Number* Pack3WordsAndSkip1Swap(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + output+= 2; + *(cmsUInt16Number*) output = wOut[2]; + output+= 2; + *(cmsUInt16Number*) output = wOut[1]; + output+= 2; + *(cmsUInt16Number*) output = wOut[0]; + output+= 2; + + return output; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + + +static +cmsUInt8Number* Pack3WordsAndSkip1SwapFirst(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + output+= 2; + *(cmsUInt16Number*) output = wOut[0]; + output+= 2; + *(cmsUInt16Number*) output = wOut[1]; + output+= 2; + *(cmsUInt16Number*) output = wOut[2]; + output+= 2; + + return output; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + + +static +cmsUInt8Number* Pack3WordsAndSkip1SwapSwapFirst(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + *(cmsUInt16Number*) output = wOut[2]; + output+= 2; + *(cmsUInt16Number*) output = wOut[1]; + output+= 2; + *(cmsUInt16Number*) output = wOut[0]; + output+= 2; + output+= 2; + + return output; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + + + +static +cmsUInt8Number* Pack1Byte(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + *output++ = FROM_16_TO_8(wOut[0]); + + return output; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + + +static +cmsUInt8Number* Pack1ByteReversed(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + *output++ = FROM_16_TO_8(REVERSE_FLAVOR_16(wOut[0])); + + return output; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + + +static +cmsUInt8Number* Pack1ByteSkip1(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + *output++ = FROM_16_TO_8(wOut[0]); + output++; + + return output; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + + +static +cmsUInt8Number* Pack1ByteSkip1SwapFirst(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + output++; + *output++ = FROM_16_TO_8(wOut[0]); + + return output; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +static +cmsUInt8Number* Pack1Word(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + *(cmsUInt16Number*) output = wOut[0]; + output+= 2; + + return output; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + + +static +cmsUInt8Number* Pack1WordReversed(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + *(cmsUInt16Number*) output = REVERSE_FLAVOR_16(wOut[0]); + output+= 2; + + return output; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +static +cmsUInt8Number* Pack1WordBigEndian(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[0]); + output+= 2; + + return output; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + + +static +cmsUInt8Number* Pack1WordSkip1(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + *(cmsUInt16Number*) output = wOut[0]; + output+= 4; + + return output; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + +static +cmsUInt8Number* Pack1WordSkip1SwapFirst(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + output += 2; + *(cmsUInt16Number*) output = wOut[0]; + output+= 2; + + return output; + + cmsUNUSED_PARAMETER(info); + cmsUNUSED_PARAMETER(Stride); +} + + +// Unencoded Float values -- don't try optimize speed +static +cmsUInt8Number* PackLabDoubleFrom16(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + + if (T_PLANAR(info -> OutputFormat)) { + + cmsCIELab Lab; + cmsFloat64Number* Out = (cmsFloat64Number*) output; + cmsLabEncoded2Float(&Lab, wOut); + + Out[0] = Lab.L; + Out[Stride] = Lab.a; + Out[Stride*2] = Lab.b; + + return output + sizeof(cmsFloat64Number); + } + else { + + cmsLabEncoded2Float((cmsCIELab*) output, wOut); + return output + (sizeof(cmsCIELab) + T_EXTRA(info ->OutputFormat) * sizeof(cmsFloat64Number)); + } +} + + +static +cmsUInt8Number* PackLabFloatFrom16(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + cmsCIELab Lab; + cmsLabEncoded2Float(&Lab, wOut); + + if (T_PLANAR(info -> OutputFormat)) { + + cmsFloat32Number* Out = (cmsFloat32Number*) output; + + Out[0] = (cmsFloat32Number)Lab.L; + Out[Stride] = (cmsFloat32Number)Lab.a; + Out[Stride*2] = (cmsFloat32Number)Lab.b; + + return output + sizeof(cmsFloat32Number); + } + else { + + ((cmsFloat32Number*) output)[0] = (cmsFloat32Number) Lab.L; + ((cmsFloat32Number*) output)[1] = (cmsFloat32Number) Lab.a; + ((cmsFloat32Number*) output)[2] = (cmsFloat32Number) Lab.b; + + return output + (3 + T_EXTRA(info ->OutputFormat)) * sizeof(cmsFloat32Number); + } +} + +static +cmsUInt8Number* PackXYZDoubleFrom16(register _cmsTRANSFORM* Info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + if (T_PLANAR(Info -> OutputFormat)) { + + cmsCIEXYZ XYZ; + cmsFloat64Number* Out = (cmsFloat64Number*) output; + cmsXYZEncoded2Float(&XYZ, wOut); + + Out[0] = XYZ.X; + Out[Stride] = XYZ.Y; + Out[Stride*2] = XYZ.Z; + + return output + sizeof(cmsFloat64Number); + + } + else { + + cmsXYZEncoded2Float((cmsCIEXYZ*) output, wOut); + + return output + (sizeof(cmsCIEXYZ) + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat64Number)); + } +} + +static +cmsUInt8Number* PackDoubleFrom16(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + int nChan = T_CHANNELS(info -> OutputFormat); + int DoSwap = T_DOSWAP(info ->OutputFormat); + int Reverse = T_FLAVOR(info ->OutputFormat); + int Extra = T_EXTRA(info -> OutputFormat); + int SwapFirst = T_SWAPFIRST(info -> OutputFormat); + int Planar = T_PLANAR(info -> OutputFormat); + int ExtraFirst = DoSwap ^ SwapFirst; + cmsFloat64Number maximum = IsInkSpace(info ->OutputFormat) ? 655.35 : 65535.0; + cmsFloat64Number v = 0; + cmsFloat64Number* swap1 = (cmsFloat64Number*) output; + int i, start = 0; + + if (ExtraFirst) + start = Extra; + + for (i=0; i < nChan; i++) { + + int index = DoSwap ? (nChan - i - 1) : i; + + v = (cmsFloat64Number) wOut[index] / maximum; + + if (Reverse) + v = maximum - v; + + if (Planar) + ((cmsFloat64Number*) output)[(i + start) * Stride]= v; + else + ((cmsFloat64Number*) output)[i + start] = v; + } + + if (!ExtraFirst) { + output += Extra * sizeof(cmsFloat64Number); + } + + if (Extra == 0 && SwapFirst) { + + memmove(swap1 + 1, swap1, (nChan-1)* sizeof(cmsFloat64Number)); + *swap1 = v; + } + + if (T_PLANAR(info -> OutputFormat)) + return output + sizeof(cmsFloat64Number); + else + return output + nChan * sizeof(cmsFloat64Number); + +} + + +static +cmsUInt8Number* PackFloatFrom16(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + int nChan = T_CHANNELS(info -> OutputFormat); + int DoSwap = T_DOSWAP(info ->OutputFormat); + int Reverse = T_FLAVOR(info ->OutputFormat); + int Extra = T_EXTRA(info -> OutputFormat); + int SwapFirst = T_SWAPFIRST(info -> OutputFormat); + int Planar = T_PLANAR(info -> OutputFormat); + int ExtraFirst = DoSwap ^ SwapFirst; + cmsFloat64Number maximum = IsInkSpace(info ->OutputFormat) ? 655.35 : 65535.0; + cmsFloat64Number v = 0; + cmsFloat32Number* swap1 = (cmsFloat32Number*) output; + int i, start = 0; + + if (ExtraFirst) + start = Extra; + + for (i=0; i < nChan; i++) { + + int index = DoSwap ? (nChan - i - 1) : i; + + v = (cmsFloat64Number) wOut[index] / maximum; + + if (Reverse) + v = maximum - v; + + if (Planar) + ((cmsFloat32Number*) output)[(i + start ) * Stride]= (cmsFloat32Number) v; + else + ((cmsFloat32Number*) output)[i + start] = (cmsFloat32Number) v; + } + + if (!ExtraFirst) { + output += Extra * sizeof(cmsFloat32Number); + } + + if (Extra == 0 && SwapFirst) { + + memmove(swap1 + 1, swap1, (nChan-1)* sizeof(cmsFloat32Number)); + *swap1 = (cmsFloat32Number) v; + } + + if (T_PLANAR(info -> OutputFormat)) + return output + sizeof(cmsFloat32Number); + else + return output + nChan * sizeof(cmsFloat32Number); +} + + + +// -------------------------------------------------------------------------------------------------------- + +static +cmsUInt8Number* PackFloatsFromFloat(_cmsTRANSFORM* info, + cmsFloat32Number wOut[], + cmsUInt8Number* output, + cmsUInt32Number Stride) +{ + int nChan = T_CHANNELS(info -> OutputFormat); + int DoSwap = T_DOSWAP(info ->OutputFormat); + int Reverse = T_FLAVOR(info ->OutputFormat); + int Extra = T_EXTRA(info -> OutputFormat); + int SwapFirst = T_SWAPFIRST(info -> OutputFormat); + int Planar = T_PLANAR(info -> OutputFormat); + int ExtraFirst = DoSwap ^ SwapFirst; + cmsFloat64Number maximum = IsInkSpace(info ->OutputFormat) ? 100.0 : 1.0; + cmsFloat32Number* swap1 = (cmsFloat32Number*) output; + cmsFloat64Number v = 0; + int i, start = 0; + + if (ExtraFirst) + start = Extra; + + for (i=0; i < nChan; i++) { + + int index = DoSwap ? (nChan - i - 1) : i; + + v = wOut[index] * maximum; + + if (Reverse) + v = maximum - v; + + if (Planar) + ((cmsFloat32Number*) output)[(i + start)* Stride]= (cmsFloat32Number) v; + else + ((cmsFloat32Number*) output)[i + start] = (cmsFloat32Number) v; + } + + if (!ExtraFirst) { + output += Extra * sizeof(cmsFloat32Number); + } + + if (Extra == 0 && SwapFirst) { + + memmove(swap1 + 1, swap1, (nChan-1)* sizeof(cmsFloat32Number)); + *swap1 = (cmsFloat32Number) v; + } + + if (T_PLANAR(info -> OutputFormat)) + return output + sizeof(cmsFloat32Number); + else + return output + nChan * sizeof(cmsFloat32Number); +} + +static +cmsUInt8Number* PackDoublesFromFloat(_cmsTRANSFORM* info, + cmsFloat32Number wOut[], + cmsUInt8Number* output, + cmsUInt32Number Stride) +{ + int nChan = T_CHANNELS(info -> OutputFormat); + int DoSwap = T_DOSWAP(info ->OutputFormat); + int Reverse = T_FLAVOR(info ->OutputFormat); + int Extra = T_EXTRA(info -> OutputFormat); + int SwapFirst = T_SWAPFIRST(info -> OutputFormat); + int Planar = T_PLANAR(info -> OutputFormat); + int ExtraFirst = DoSwap ^ SwapFirst; + cmsFloat64Number maximum = IsInkSpace(info ->OutputFormat) ? 100.0 : 1.0; + cmsFloat64Number v = 0; + cmsFloat64Number* swap1 = (cmsFloat64Number*) output; + int i, start = 0; + + if (ExtraFirst) + start = Extra; + + for (i=0; i < nChan; i++) { + + int index = DoSwap ? (nChan - i - 1) : i; + + v = wOut[index] * maximum; + + if (Reverse) + v = maximum - v; + + if (Planar) + ((cmsFloat64Number*) output)[(i + start) * Stride] = v; + else + ((cmsFloat64Number*) output)[i + start] = v; + } + + if (!ExtraFirst) { + output += Extra * sizeof(cmsFloat64Number); + } + + if (Extra == 0 && SwapFirst) { + + memmove(swap1 + 1, swap1, (nChan-1)* sizeof(cmsFloat64Number)); + *swap1 = v; + } + + + if (T_PLANAR(info -> OutputFormat)) + return output + sizeof(cmsFloat64Number); + else + return output + nChan * sizeof(cmsFloat64Number); + +} + + + + + +static +cmsUInt8Number* PackLabFloatFromFloat(_cmsTRANSFORM* Info, + cmsFloat32Number wOut[], + cmsUInt8Number* output, + cmsUInt32Number Stride) +{ + cmsFloat32Number* Out = (cmsFloat32Number*) output; + + if (T_PLANAR(Info -> OutputFormat)) { + + Out[0] = (cmsFloat32Number) (wOut[0] * 100.0); + Out[Stride] = (cmsFloat32Number) (wOut[1] * 255.0 - 128.0); + Out[Stride*2] = (cmsFloat32Number) (wOut[2] * 255.0 - 128.0); + + return output + sizeof(cmsFloat32Number); + } + else { + + Out[0] = (cmsFloat32Number) (wOut[0] * 100.0); + Out[1] = (cmsFloat32Number) (wOut[1] * 255.0 - 128.0); + Out[2] = (cmsFloat32Number) (wOut[2] * 255.0 - 128.0); + + return output + (sizeof(cmsFloat32Number)*3 + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat32Number)); + } + +} + + +static +cmsUInt8Number* PackLabDoubleFromFloat(_cmsTRANSFORM* Info, + cmsFloat32Number wOut[], + cmsUInt8Number* output, + cmsUInt32Number Stride) +{ + cmsFloat64Number* Out = (cmsFloat64Number*) output; + + if (T_PLANAR(Info -> OutputFormat)) { + + Out[0] = (cmsFloat64Number) (wOut[0] * 100.0); + Out[Stride] = (cmsFloat64Number) (wOut[1] * 255.0 - 128.0); + Out[Stride*2] = (cmsFloat64Number) (wOut[2] * 255.0 - 128.0); + + return output + sizeof(cmsFloat64Number); + } + else { + + Out[0] = (cmsFloat64Number) (wOut[0] * 100.0); + Out[1] = (cmsFloat64Number) (wOut[1] * 255.0 - 128.0); + Out[2] = (cmsFloat64Number) (wOut[2] * 255.0 - 128.0); + + return output + (sizeof(cmsFloat64Number)*3 + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat64Number)); + } + +} + + +// From 0..1 range to 0..MAX_ENCODEABLE_XYZ +static +cmsUInt8Number* PackXYZFloatFromFloat(_cmsTRANSFORM* Info, + cmsFloat32Number wOut[], + cmsUInt8Number* output, + cmsUInt32Number Stride) +{ + cmsFloat32Number* Out = (cmsFloat32Number*) output; + + if (T_PLANAR(Info -> OutputFormat)) { + + Out[0] = (cmsFloat32Number) (wOut[0] * MAX_ENCODEABLE_XYZ); + Out[Stride] = (cmsFloat32Number) (wOut[1] * MAX_ENCODEABLE_XYZ); + Out[Stride*2] = (cmsFloat32Number) (wOut[2] * MAX_ENCODEABLE_XYZ); + + return output + sizeof(cmsFloat32Number); + } + else { + + Out[0] = (cmsFloat32Number) (wOut[0] * MAX_ENCODEABLE_XYZ); + Out[1] = (cmsFloat32Number) (wOut[1] * MAX_ENCODEABLE_XYZ); + Out[2] = (cmsFloat32Number) (wOut[2] * MAX_ENCODEABLE_XYZ); + + return output + (sizeof(cmsFloat32Number)*3 + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat32Number)); + } + +} + +// Same, but convert to double +static +cmsUInt8Number* PackXYZDoubleFromFloat(_cmsTRANSFORM* Info, + cmsFloat32Number wOut[], + cmsUInt8Number* output, + cmsUInt32Number Stride) +{ + cmsFloat64Number* Out = (cmsFloat64Number*) output; + + if (T_PLANAR(Info -> OutputFormat)) { + + Out[0] = (cmsFloat64Number) (wOut[0] * MAX_ENCODEABLE_XYZ); + Out[Stride] = (cmsFloat64Number) (wOut[1] * MAX_ENCODEABLE_XYZ); + Out[Stride*2] = (cmsFloat64Number) (wOut[2] * MAX_ENCODEABLE_XYZ); + + return output + sizeof(cmsFloat64Number); + } + else { + + Out[0] = (cmsFloat64Number) (wOut[0] * MAX_ENCODEABLE_XYZ); + Out[1] = (cmsFloat64Number) (wOut[1] * MAX_ENCODEABLE_XYZ); + Out[2] = (cmsFloat64Number) (wOut[2] * MAX_ENCODEABLE_XYZ); + + return output + (sizeof(cmsFloat64Number)*3 + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat64Number)); + } + +} + + +// ---------------------------------------------------------------------------------------------------------------- + +#ifndef CMS_NO_HALF_SUPPORT + +// Decodes an stream of half floats to wIn[] described by input format + +static +cmsUInt8Number* UnrollHalfTo16(register _cmsTRANSFORM* info, + register cmsUInt16Number wIn[], + register cmsUInt8Number* accum, + register cmsUInt32Number Stride) +{ + + int nChan = T_CHANNELS(info -> InputFormat); + int DoSwap = T_DOSWAP(info ->InputFormat); + int Reverse = T_FLAVOR(info ->InputFormat); + int SwapFirst = T_SWAPFIRST(info -> InputFormat); + int Extra = T_EXTRA(info -> InputFormat); + int ExtraFirst = DoSwap ^ SwapFirst; + int Planar = T_PLANAR(info -> InputFormat); + cmsFloat32Number v; + int i, start = 0; + cmsFloat32Number maximum = IsInkSpace(info ->InputFormat) ? 655.35F : 65535.0F; + + + if (ExtraFirst) + start = Extra; + + for (i=0; i < nChan; i++) { + + int index = DoSwap ? (nChan - i - 1) : i; + + if (Planar) + v = _cmsHalf2Float ( ((cmsUInt16Number*) accum)[(i + start) * Stride] ); + else + v = _cmsHalf2Float ( ((cmsUInt16Number*) accum)[i + start] ) ; + + if (Reverse) v = maximum - v; + + wIn[index] = _cmsQuickSaturateWord(v * maximum); + } + + + if (Extra == 0 && SwapFirst) { + cmsUInt16Number tmp = wIn[0]; + + memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsUInt16Number)); + wIn[nChan-1] = tmp; + } + + if (T_PLANAR(info -> InputFormat)) + return accum + sizeof(cmsUInt16Number); + else + return accum + (nChan + Extra) * sizeof(cmsUInt16Number); +} + +// Decodes an stream of half floats to wIn[] described by input format + +static +cmsUInt8Number* UnrollHalfToFloat(_cmsTRANSFORM* info, + cmsFloat32Number wIn[], + cmsUInt8Number* accum, + cmsUInt32Number Stride) +{ + + int nChan = T_CHANNELS(info -> InputFormat); + int DoSwap = T_DOSWAP(info ->InputFormat); + int Reverse = T_FLAVOR(info ->InputFormat); + int SwapFirst = T_SWAPFIRST(info -> InputFormat); + int Extra = T_EXTRA(info -> InputFormat); + int ExtraFirst = DoSwap ^ SwapFirst; + int Planar = T_PLANAR(info -> InputFormat); + cmsFloat32Number v; + int i, start = 0; + cmsFloat32Number maximum = IsInkSpace(info ->InputFormat) ? 100.0F : 1.0F; + + + if (ExtraFirst) + start = Extra; + + for (i=0; i < nChan; i++) { + + int index = DoSwap ? (nChan - i - 1) : i; + + if (Planar) + v = _cmsHalf2Float ( ((cmsUInt16Number*) accum)[(i + start) * Stride] ); + else + v = _cmsHalf2Float ( ((cmsUInt16Number*) accum)[i + start] ) ; + + v /= maximum; + + wIn[index] = Reverse ? 1 - v : v; + } + + + if (Extra == 0 && SwapFirst) { + cmsFloat32Number tmp = wIn[0]; + + memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsFloat32Number)); + wIn[nChan-1] = tmp; + } + + if (T_PLANAR(info -> InputFormat)) + return accum + sizeof(cmsUInt16Number); + else + return accum + (nChan + Extra) * sizeof(cmsUInt16Number); +} + + +static +cmsUInt8Number* PackHalfFrom16(register _cmsTRANSFORM* info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + int nChan = T_CHANNELS(info -> OutputFormat); + int DoSwap = T_DOSWAP(info ->OutputFormat); + int Reverse = T_FLAVOR(info ->OutputFormat); + int Extra = T_EXTRA(info -> OutputFormat); + int SwapFirst = T_SWAPFIRST(info -> OutputFormat); + int Planar = T_PLANAR(info -> OutputFormat); + int ExtraFirst = DoSwap ^ SwapFirst; + cmsFloat32Number maximum = IsInkSpace(info ->OutputFormat) ? 655.35F : 65535.0F; + cmsFloat32Number v = 0; + cmsUInt16Number* swap1 = (cmsUInt16Number*) output; + int i, start = 0; + + if (ExtraFirst) + start = Extra; + + for (i=0; i < nChan; i++) { + + int index = DoSwap ? (nChan - i - 1) : i; + + v = (cmsFloat32Number) wOut[index] / maximum; + + if (Reverse) + v = maximum - v; + + if (Planar) + ((cmsUInt16Number*) output)[(i + start ) * Stride]= _cmsFloat2Half(v); + else + ((cmsUInt16Number*) output)[i + start] = _cmsFloat2Half(v); + } + + if (!ExtraFirst) { + output += Extra * sizeof(cmsUInt16Number); + } + + if (Extra == 0 && SwapFirst) { + + memmove(swap1 + 1, swap1, (nChan-1)* sizeof(cmsUInt16Number)); + *swap1 = _cmsFloat2Half(v); + } + + if (T_PLANAR(info -> OutputFormat)) + return output + sizeof(cmsUInt16Number); + else + return output + nChan * sizeof(cmsUInt16Number); +} + + + +static +cmsUInt8Number* PackHalfFromFloat(_cmsTRANSFORM* info, + cmsFloat32Number wOut[], + cmsUInt8Number* output, + cmsUInt32Number Stride) +{ + int nChan = T_CHANNELS(info -> OutputFormat); + int DoSwap = T_DOSWAP(info ->OutputFormat); + int Reverse = T_FLAVOR(info ->OutputFormat); + int Extra = T_EXTRA(info -> OutputFormat); + int SwapFirst = T_SWAPFIRST(info -> OutputFormat); + int Planar = T_PLANAR(info -> OutputFormat); + int ExtraFirst = DoSwap ^ SwapFirst; + cmsFloat32Number maximum = IsInkSpace(info ->OutputFormat) ? 100.0F : 1.0F; + cmsUInt16Number* swap1 = (cmsUInt16Number*) output; + cmsFloat32Number v = 0; + int i, start = 0; + + if (ExtraFirst) + start = Extra; + + for (i=0; i < nChan; i++) { + + int index = DoSwap ? (nChan - i - 1) : i; + + v = wOut[index] * maximum; + + if (Reverse) + v = maximum - v; + + if (Planar) + ((cmsUInt16Number*) output)[(i + start)* Stride]= _cmsFloat2Half( v ); + else + ((cmsUInt16Number*) output)[i + start] = _cmsFloat2Half( v ); + } + + if (!ExtraFirst) { + output += Extra * sizeof(cmsUInt16Number); + } + + if (Extra == 0 && SwapFirst) { + + memmove(swap1 + 1, swap1, (nChan-1)* sizeof(cmsUInt16Number)); + *swap1 = (cmsUInt16Number) _cmsFloat2Half( v ); + } + + if (T_PLANAR(info -> OutputFormat)) + return output + sizeof(cmsUInt16Number); + else + return output + nChan * sizeof(cmsUInt16Number); +} + +#endif + +// ---------------------------------------------------------------------------------------------------------------- + + +static cmsFormatters16 InputFormatters16[] = { + + // Type Mask Function + // ---------------------------- ------------------------------------ ---------------------------- + { TYPE_Lab_DBL, ANYPLANAR|ANYEXTRA, UnrollLabDoubleTo16}, + { TYPE_XYZ_DBL, ANYPLANAR|ANYEXTRA, UnrollXYZDoubleTo16}, + { TYPE_Lab_FLT, ANYPLANAR|ANYEXTRA, UnrollLabFloatTo16}, + { TYPE_GRAY_DBL, 0, UnrollDouble1Chan}, + { FLOAT_SH(1)|BYTES_SH(0), ANYCHANNELS|ANYPLANAR|ANYSWAPFIRST|ANYFLAVOR| + ANYSWAP|ANYEXTRA|ANYSPACE, UnrollDoubleTo16}, + { FLOAT_SH(1)|BYTES_SH(4), ANYCHANNELS|ANYPLANAR|ANYSWAPFIRST|ANYFLAVOR| + ANYSWAP|ANYEXTRA|ANYSPACE, UnrollFloatTo16}, +#ifndef CMS_NO_HALF_SUPPORT + { FLOAT_SH(1)|BYTES_SH(2), ANYCHANNELS|ANYPLANAR|ANYSWAPFIRST|ANYFLAVOR| + ANYEXTRA|ANYSWAP|ANYSPACE, UnrollHalfTo16}, +#endif + + { CHANNELS_SH(1)|BYTES_SH(1), ANYSPACE, Unroll1Byte}, + { CHANNELS_SH(1)|BYTES_SH(1)|EXTRA_SH(1), ANYSPACE, Unroll1ByteSkip1}, + { CHANNELS_SH(1)|BYTES_SH(1)|EXTRA_SH(2), ANYSPACE, Unroll1ByteSkip2}, + { CHANNELS_SH(1)|BYTES_SH(1)|FLAVOR_SH(1), ANYSPACE, Unroll1ByteReversed}, + { COLORSPACE_SH(PT_MCH2)|CHANNELS_SH(2)|BYTES_SH(1), 0, Unroll2Bytes}, + + { TYPE_LabV2_8, 0, UnrollLabV2_8 }, + { TYPE_ALabV2_8, 0, UnrollALabV2_8 }, + { TYPE_LabV2_16, 0, UnrollLabV2_16 }, + + { CHANNELS_SH(3)|BYTES_SH(1), ANYSPACE, Unroll3Bytes}, + { CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1), ANYSPACE, Unroll3BytesSwap}, + { CHANNELS_SH(3)|EXTRA_SH(1)|BYTES_SH(1)|DOSWAP_SH(1), ANYSPACE, Unroll3BytesSkip1Swap}, + { CHANNELS_SH(3)|EXTRA_SH(1)|BYTES_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Unroll3BytesSkip1SwapFirst}, + + { CHANNELS_SH(3)|EXTRA_SH(1)|BYTES_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1), + ANYSPACE, Unroll3BytesSkip1SwapSwapFirst}, + + { CHANNELS_SH(4)|BYTES_SH(1), ANYSPACE, Unroll4Bytes}, + { CHANNELS_SH(4)|BYTES_SH(1)|FLAVOR_SH(1), ANYSPACE, Unroll4BytesReverse}, + { CHANNELS_SH(4)|BYTES_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Unroll4BytesSwapFirst}, + { CHANNELS_SH(4)|BYTES_SH(1)|DOSWAP_SH(1), ANYSPACE, Unroll4BytesSwap}, + { CHANNELS_SH(4)|BYTES_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Unroll4BytesSwapSwapFirst}, + + { BYTES_SH(1)|PLANAR_SH(1), ANYFLAVOR|ANYSWAPFIRST| + ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, UnrollPlanarBytes}, + + { BYTES_SH(1), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP| + ANYEXTRA|ANYCHANNELS|ANYSPACE, UnrollChunkyBytes}, + + { CHANNELS_SH(1)|BYTES_SH(2), ANYSPACE, Unroll1Word}, + { CHANNELS_SH(1)|BYTES_SH(2)|FLAVOR_SH(1), ANYSPACE, Unroll1WordReversed}, + { CHANNELS_SH(1)|BYTES_SH(2)|EXTRA_SH(3), ANYSPACE, Unroll1WordSkip3}, + + { CHANNELS_SH(2)|BYTES_SH(2), ANYSPACE, Unroll2Words}, + { CHANNELS_SH(3)|BYTES_SH(2), ANYSPACE, Unroll3Words}, + { CHANNELS_SH(4)|BYTES_SH(2), ANYSPACE, Unroll4Words}, + + { CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1), ANYSPACE, Unroll3WordsSwap}, + { CHANNELS_SH(3)|BYTES_SH(2)|EXTRA_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Unroll3WordsSkip1SwapFirst}, + { CHANNELS_SH(3)|BYTES_SH(2)|EXTRA_SH(1)|DOSWAP_SH(1), ANYSPACE, Unroll3WordsSkip1Swap}, + { CHANNELS_SH(4)|BYTES_SH(2)|FLAVOR_SH(1), ANYSPACE, Unroll4WordsReverse}, + { CHANNELS_SH(4)|BYTES_SH(2)|SWAPFIRST_SH(1), ANYSPACE, Unroll4WordsSwapFirst}, + { CHANNELS_SH(4)|BYTES_SH(2)|DOSWAP_SH(1), ANYSPACE, Unroll4WordsSwap}, + { CHANNELS_SH(4)|BYTES_SH(2)|DOSWAP_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Unroll4WordsSwapSwapFirst}, + + + { BYTES_SH(2)|PLANAR_SH(1), ANYFLAVOR|ANYSWAP|ANYENDIAN|ANYEXTRA|ANYCHANNELS|ANYSPACE, UnrollPlanarWords}, + { BYTES_SH(2), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYENDIAN|ANYEXTRA|ANYCHANNELS|ANYSPACE, UnrollAnyWords}, +}; + + + +static cmsFormattersFloat InputFormattersFloat[] = { + + // Type Mask Function + // ---------------------------- ------------------------------------ ---------------------------- + { TYPE_Lab_DBL, ANYPLANAR|ANYEXTRA, UnrollLabDoubleToFloat}, + { TYPE_Lab_FLT, ANYPLANAR|ANYEXTRA, UnrollLabFloatToFloat}, + + { TYPE_XYZ_DBL, ANYPLANAR|ANYEXTRA, UnrollXYZDoubleToFloat}, + { TYPE_XYZ_FLT, ANYPLANAR|ANYEXTRA, UnrollXYZFloatToFloat}, + + { FLOAT_SH(1)|BYTES_SH(4), ANYPLANAR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA| + ANYCHANNELS|ANYSPACE, UnrollFloatsToFloat}, + + { FLOAT_SH(1)|BYTES_SH(0), ANYPLANAR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA| + ANYCHANNELS|ANYSPACE, UnrollDoublesToFloat}, +#ifndef CMS_NO_HALF_SUPPORT + { FLOAT_SH(1)|BYTES_SH(2), ANYPLANAR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA| + ANYCHANNELS|ANYSPACE, UnrollHalfToFloat}, +#endif +}; + + +// Bit fields set to one in the mask are not compared +static +cmsFormatter _cmsGetStockInputFormatter(cmsUInt32Number dwInput, cmsUInt32Number dwFlags) +{ + cmsUInt32Number i; + cmsFormatter fr; + + switch (dwFlags) { + + case CMS_PACK_FLAGS_16BITS: { + for (i=0; i < sizeof(InputFormatters16) / sizeof(cmsFormatters16); i++) { + cmsFormatters16* f = InputFormatters16 + i; + + if ((dwInput & ~f ->Mask) == f ->Type) { + fr.Fmt16 = f ->Frm; + return fr; + } + } + } + break; + + case CMS_PACK_FLAGS_FLOAT: { + for (i=0; i < sizeof(InputFormattersFloat) / sizeof(cmsFormattersFloat); i++) { + cmsFormattersFloat* f = InputFormattersFloat + i; + + if ((dwInput & ~f ->Mask) == f ->Type) { + fr.FmtFloat = f ->Frm; + return fr; + } + } + } + break; + + default:; + + } + + fr.Fmt16 = NULL; + return fr; +} + +static cmsFormatters16 OutputFormatters16[] = { + // Type Mask Function + // ---------------------------- ------------------------------------ ---------------------------- + + { TYPE_Lab_DBL, ANYPLANAR|ANYEXTRA, PackLabDoubleFrom16}, + { TYPE_XYZ_DBL, ANYPLANAR|ANYEXTRA, PackXYZDoubleFrom16}, + + { TYPE_Lab_FLT, ANYPLANAR|ANYEXTRA, PackLabFloatFrom16}, + + { FLOAT_SH(1)|BYTES_SH(0), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP| + ANYCHANNELS|ANYPLANAR|ANYEXTRA|ANYSPACE, PackDoubleFrom16}, + { FLOAT_SH(1)|BYTES_SH(4), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP| + ANYCHANNELS|ANYPLANAR|ANYEXTRA|ANYSPACE, PackFloatFrom16}, +#ifndef CMS_NO_HALF_SUPPORT + { FLOAT_SH(1)|BYTES_SH(2), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP| + ANYCHANNELS|ANYPLANAR|ANYEXTRA|ANYSPACE, PackHalfFrom16}, +#endif + + { CHANNELS_SH(1)|BYTES_SH(1), ANYSPACE, Pack1Byte}, + { CHANNELS_SH(1)|BYTES_SH(1)|EXTRA_SH(1), ANYSPACE, Pack1ByteSkip1}, + { CHANNELS_SH(1)|BYTES_SH(1)|EXTRA_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Pack1ByteSkip1SwapFirst}, + + { CHANNELS_SH(1)|BYTES_SH(1)|FLAVOR_SH(1), ANYSPACE, Pack1ByteReversed}, + + { TYPE_LabV2_8, 0, PackLabV2_8 }, + { TYPE_ALabV2_8, 0, PackALabV2_8 }, + { TYPE_LabV2_16, 0, PackLabV2_16 }, + + { CHANNELS_SH(3)|BYTES_SH(1)|OPTIMIZED_SH(1), ANYSPACE, Pack3BytesOptimized}, + { CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1)|OPTIMIZED_SH(1), ANYSPACE, Pack3BytesAndSkip1Optimized}, + { CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1)|SWAPFIRST_SH(1)|OPTIMIZED_SH(1), + ANYSPACE, Pack3BytesAndSkip1SwapFirstOptimized}, + { CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1)|OPTIMIZED_SH(1), + ANYSPACE, Pack3BytesAndSkip1SwapSwapFirstOptimized}, + { CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1)|EXTRA_SH(1)|OPTIMIZED_SH(1), + ANYSPACE, Pack3BytesAndSkip1SwapOptimized}, + { CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1)|OPTIMIZED_SH(1), ANYSPACE, Pack3BytesSwapOptimized}, + + + + { CHANNELS_SH(3)|BYTES_SH(1), ANYSPACE, Pack3Bytes}, + { CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1), ANYSPACE, Pack3BytesAndSkip1}, + { CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Pack3BytesAndSkip1SwapFirst}, + { CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1), + ANYSPACE, Pack3BytesAndSkip1SwapSwapFirst}, + { CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1)|EXTRA_SH(1), ANYSPACE, Pack3BytesAndSkip1Swap}, + { CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1), ANYSPACE, Pack3BytesSwap}, + { CHANNELS_SH(6)|BYTES_SH(1), ANYSPACE, Pack6Bytes}, + { CHANNELS_SH(6)|BYTES_SH(1)|DOSWAP_SH(1), ANYSPACE, Pack6BytesSwap}, + { CHANNELS_SH(4)|BYTES_SH(1), ANYSPACE, Pack4Bytes}, + { CHANNELS_SH(4)|BYTES_SH(1)|FLAVOR_SH(1), ANYSPACE, Pack4BytesReverse}, + { CHANNELS_SH(4)|BYTES_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Pack4BytesSwapFirst}, + { CHANNELS_SH(4)|BYTES_SH(1)|DOSWAP_SH(1), ANYSPACE, Pack4BytesSwap}, + { CHANNELS_SH(4)|BYTES_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Pack4BytesSwapSwapFirst}, + + { BYTES_SH(1), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, PackAnyBytes}, + { BYTES_SH(1)|PLANAR_SH(1), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, PackPlanarBytes}, + + { CHANNELS_SH(1)|BYTES_SH(2), ANYSPACE, Pack1Word}, + { CHANNELS_SH(1)|BYTES_SH(2)|EXTRA_SH(1), ANYSPACE, Pack1WordSkip1}, + { CHANNELS_SH(1)|BYTES_SH(2)|EXTRA_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Pack1WordSkip1SwapFirst}, + { CHANNELS_SH(1)|BYTES_SH(2)|FLAVOR_SH(1), ANYSPACE, Pack1WordReversed}, + { CHANNELS_SH(1)|BYTES_SH(2)|ENDIAN16_SH(1), ANYSPACE, Pack1WordBigEndian}, + { CHANNELS_SH(3)|BYTES_SH(2), ANYSPACE, Pack3Words}, + { CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1), ANYSPACE, Pack3WordsSwap}, + { CHANNELS_SH(3)|BYTES_SH(2)|ENDIAN16_SH(1), ANYSPACE, Pack3WordsBigEndian}, + { CHANNELS_SH(3)|BYTES_SH(2)|EXTRA_SH(1), ANYSPACE, Pack3WordsAndSkip1}, + { CHANNELS_SH(3)|BYTES_SH(2)|EXTRA_SH(1)|DOSWAP_SH(1), ANYSPACE, Pack3WordsAndSkip1Swap}, + { CHANNELS_SH(3)|BYTES_SH(2)|EXTRA_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Pack3WordsAndSkip1SwapFirst}, + + { CHANNELS_SH(3)|BYTES_SH(2)|EXTRA_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1), + ANYSPACE, Pack3WordsAndSkip1SwapSwapFirst}, + + { CHANNELS_SH(4)|BYTES_SH(2), ANYSPACE, Pack4Words}, + { CHANNELS_SH(4)|BYTES_SH(2)|FLAVOR_SH(1), ANYSPACE, Pack4WordsReverse}, + { CHANNELS_SH(4)|BYTES_SH(2)|DOSWAP_SH(1), ANYSPACE, Pack4WordsSwap}, + { CHANNELS_SH(4)|BYTES_SH(2)|ENDIAN16_SH(1), ANYSPACE, Pack4WordsBigEndian}, + + { CHANNELS_SH(6)|BYTES_SH(2), ANYSPACE, Pack6Words}, + { CHANNELS_SH(6)|BYTES_SH(2)|DOSWAP_SH(1), ANYSPACE, Pack6WordsSwap}, + + { BYTES_SH(2)|PLANAR_SH(1), ANYFLAVOR|ANYENDIAN|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, PackPlanarWords}, + { BYTES_SH(2), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYENDIAN|ANYEXTRA|ANYCHANNELS|ANYSPACE, PackAnyWords} + +}; + + +static cmsFormattersFloat OutputFormattersFloat[] = { + // Type Mask Function + // ---------------------------- --------------------------------------------------- ---------------------------- + { TYPE_Lab_FLT, ANYPLANAR|ANYEXTRA, PackLabFloatFromFloat}, + { TYPE_XYZ_FLT, ANYPLANAR|ANYEXTRA, PackXYZFloatFromFloat}, + + { TYPE_Lab_DBL, ANYPLANAR|ANYEXTRA, PackLabDoubleFromFloat}, + { TYPE_XYZ_DBL, ANYPLANAR|ANYEXTRA, PackXYZDoubleFromFloat}, + + { FLOAT_SH(1)|BYTES_SH(4), ANYPLANAR| + ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, PackFloatsFromFloat }, + { FLOAT_SH(1)|BYTES_SH(0), ANYPLANAR| + ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, PackDoublesFromFloat }, +#ifndef CMS_NO_HALF_SUPPORT + { FLOAT_SH(1)|BYTES_SH(2), + ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, PackHalfFromFloat }, +#endif + + + +}; + + +// Bit fields set to one in the mask are not compared +static +cmsFormatter _cmsGetStockOutputFormatter(cmsUInt32Number dwInput, cmsUInt32Number dwFlags) +{ + cmsUInt32Number i; + cmsFormatter fr; + + + switch (dwFlags) + { + + case CMS_PACK_FLAGS_16BITS: { + + for (i=0; i < sizeof(OutputFormatters16) / sizeof(cmsFormatters16); i++) { + cmsFormatters16* f = OutputFormatters16 + i; + + if ((dwInput & ~f ->Mask) == f ->Type) { + fr.Fmt16 = f ->Frm; + return fr; + } + } + } + break; + + case CMS_PACK_FLAGS_FLOAT: { + + for (i=0; i < sizeof(OutputFormattersFloat) / sizeof(cmsFormattersFloat); i++) { + cmsFormattersFloat* f = OutputFormattersFloat + i; + + if ((dwInput & ~f ->Mask) == f ->Type) { + fr.FmtFloat = f ->Frm; + return fr; + } + } + } + break; + + default:; + + } + + fr.Fmt16 = NULL; + return fr; +} + + +typedef struct _cms_formatters_factory_list { + + cmsFormatterFactory Factory; + struct _cms_formatters_factory_list *Next; + +} cmsFormattersFactoryList; + +static cmsFormattersFactoryList* FactoryList = NULL; + + +// Formatters management +cmsBool _cmsRegisterFormattersPlugin(cmsContext id, cmsPluginBase* Data) +{ + cmsPluginFormatters* Plugin = (cmsPluginFormatters*) Data; + cmsFormattersFactoryList* fl ; + + // Reset + if (Data == NULL) { + + FactoryList = NULL; + return TRUE; + } + + fl = (cmsFormattersFactoryList*) _cmsPluginMalloc(id, sizeof(cmsFormattersFactoryList)); + if (fl == NULL) return FALSE; + + fl ->Factory = Plugin ->FormattersFactory; + + fl ->Next = FactoryList; + FactoryList = fl; + + return TRUE; +} + +cmsFormatter _cmsGetFormatter(cmsUInt32Number Type, // Specific type, i.e. TYPE_RGB_8 + cmsFormatterDirection Dir, + cmsUInt32Number dwFlags) +{ + cmsFormattersFactoryList* f; + + for (f = FactoryList; f != NULL; f = f ->Next) { + + cmsFormatter fn = f ->Factory(Type, Dir, dwFlags); + if (fn.Fmt16 != NULL) return fn; + } + + // Revert to default + if (Dir == cmsFormatterInput) + return _cmsGetStockInputFormatter(Type, dwFlags); + else + return _cmsGetStockOutputFormatter(Type, dwFlags); +} + + +// Return whatever given formatter refers to float values +cmsBool _cmsFormatterIsFloat(cmsUInt32Number Type) +{ + return T_FLOAT(Type) ? TRUE : FALSE; +} + +// Return whatever given formatter refers to 8 bits +cmsBool _cmsFormatterIs8bit(cmsUInt32Number Type) +{ + int Bytes = T_BYTES(Type); + + return (Bytes == 1); +} + +// Build a suitable formatter for the colorspace of this profile +cmsUInt32Number CMSEXPORT cmsFormatterForColorspaceOfProfile(cmsHPROFILE hProfile, cmsUInt32Number nBytes, cmsBool lIsFloat) +{ + + cmsColorSpaceSignature ColorSpace = cmsGetColorSpace(hProfile); + cmsUInt32Number ColorSpaceBits = _cmsLCMScolorSpace(ColorSpace); + cmsUInt32Number nOutputChans = cmsChannelsOf(ColorSpace); + cmsUInt32Number Float = lIsFloat ? 1 : 0; + + // Create a fake formatter for result + return FLOAT_SH(Float) | COLORSPACE_SH(ColorSpaceBits) | BYTES_SH(nBytes) | CHANNELS_SH(nOutputChans); +} + +// Build a suitable formatter for the colorspace of this profile +cmsUInt32Number CMSEXPORT cmsFormatterForPCSOfProfile(cmsHPROFILE hProfile, cmsUInt32Number nBytes, cmsBool lIsFloat) +{ + + cmsColorSpaceSignature ColorSpace = cmsGetPCS(hProfile); + int ColorSpaceBits = _cmsLCMScolorSpace(ColorSpace); + cmsUInt32Number nOutputChans = cmsChannelsOf(ColorSpace); + cmsUInt32Number Float = lIsFloat ? 1 : 0; + + // Create a fake formatter for result + return FLOAT_SH(Float) | COLORSPACE_SH(ColorSpaceBits) | BYTES_SH(nBytes) | CHANNELS_SH(nOutputChans); +} + diff --git a/jni/lcms2-2.5/src/cmspcs.c b/jni/lcms2-2.5/src/cmspcs.c new file mode 100644 index 00000000..102cd7d2 --- /dev/null +++ b/jni/lcms2-2.5/src/cmspcs.c @@ -0,0 +1,931 @@ +//--------------------------------------------------------------------------------- +// +// Little Color Management System +// Copyright (c) 1998-2010 Marti Maria Saguer +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//--------------------------------------------------------------------------------- +// + +#include "lcms2_internal.h" + +// inter PCS conversions XYZ <-> CIE L* a* b* +/* + + + CIE 15:2004 CIELab is defined as: + + L* = 116*f(Y/Yn) - 16 0 <= L* <= 100 + a* = 500*[f(X/Xn) - f(Y/Yn)] + b* = 200*[f(Y/Yn) - f(Z/Zn)] + + and + + f(t) = t^(1/3) 1 >= t > (24/116)^3 + (841/108)*t + (16/116) 0 <= t <= (24/116)^3 + + + Reverse transform is: + + X = Xn*[a* / 500 + (L* + 16) / 116] ^ 3 if (X/Xn) > (24/116) + = Xn*(a* / 500 + L* / 116) / 7.787 if (X/Xn) <= (24/116) + + + + PCS in Lab2 is encoded as: + + 8 bit Lab PCS: + + L* 0..100 into a 0..ff byte. + a* t + 128 range is -128.0 +127.0 + b* + + 16 bit Lab PCS: + + L* 0..100 into a 0..ff00 word. + a* t + 128 range is -128.0 +127.9961 + b* + + + +Interchange Space Component Actual Range Encoded Range +CIE XYZ X 0 -> 1.99997 0x0000 -> 0xffff +CIE XYZ Y 0 -> 1.99997 0x0000 -> 0xffff +CIE XYZ Z 0 -> 1.99997 0x0000 -> 0xffff + +Version 2,3 +----------- + +CIELAB (16 bit) L* 0 -> 100.0 0x0000 -> 0xff00 +CIELAB (16 bit) a* -128.0 -> +127.996 0x0000 -> 0x8000 -> 0xffff +CIELAB (16 bit) b* -128.0 -> +127.996 0x0000 -> 0x8000 -> 0xffff + + +Version 4 +--------- + +CIELAB (16 bit) L* 0 -> 100.0 0x0000 -> 0xffff +CIELAB (16 bit) a* -128.0 -> +127 0x0000 -> 0x8080 -> 0xffff +CIELAB (16 bit) b* -128.0 -> +127 0x0000 -> 0x8080 -> 0xffff + +*/ + +// Conversions +void CMSEXPORT cmsXYZ2xyY(cmsCIExyY* Dest, const cmsCIEXYZ* Source) +{ + cmsFloat64Number ISum; + + ISum = 1./(Source -> X + Source -> Y + Source -> Z); + + Dest -> x = (Source -> X) * ISum; + Dest -> y = (Source -> Y) * ISum; + Dest -> Y = Source -> Y; +} + +void CMSEXPORT cmsxyY2XYZ(cmsCIEXYZ* Dest, const cmsCIExyY* Source) +{ + Dest -> X = (Source -> x / Source -> y) * Source -> Y; + Dest -> Y = Source -> Y; + Dest -> Z = ((1 - Source -> x - Source -> y) / Source -> y) * Source -> Y; +} + +static +cmsFloat64Number f(cmsFloat64Number t) +{ + const cmsFloat64Number Limit = (24.0/116.0) * (24.0/116.0) * (24.0/116.0); + + if (t <= Limit) + return (841.0/108.0) * t + (16.0/116.0); + else + return pow(t, 1.0/3.0); +} + +static +cmsFloat64Number f_1(cmsFloat64Number t) +{ + const cmsFloat64Number Limit = (24.0/116.0); + + if (t <= Limit) { + return (108.0/841.0) * (t - (16.0/116.0)); + } + + return t * t * t; +} + + +// Standard XYZ to Lab. it can handle negative XZY numbers in some cases +void CMSEXPORT cmsXYZ2Lab(const cmsCIEXYZ* WhitePoint, cmsCIELab* Lab, const cmsCIEXYZ* xyz) +{ + cmsFloat64Number fx, fy, fz; + + if (WhitePoint == NULL) + WhitePoint = cmsD50_XYZ(); + + fx = f(xyz->X / WhitePoint->X); + fy = f(xyz->Y / WhitePoint->Y); + fz = f(xyz->Z / WhitePoint->Z); + + Lab->L = 116.0*fy - 16.0; + Lab->a = 500.0*(fx - fy); + Lab->b = 200.0*(fy - fz); +} + + +// Standard XYZ to Lab. It can return negative XYZ in some cases +void CMSEXPORT cmsLab2XYZ(const cmsCIEXYZ* WhitePoint, cmsCIEXYZ* xyz, const cmsCIELab* Lab) +{ + cmsFloat64Number x, y, z; + + if (WhitePoint == NULL) + WhitePoint = cmsD50_XYZ(); + + y = (Lab-> L + 16.0) / 116.0; + x = y + 0.002 * Lab -> a; + z = y - 0.005 * Lab -> b; + + xyz -> X = f_1(x) * WhitePoint -> X; + xyz -> Y = f_1(y) * WhitePoint -> Y; + xyz -> Z = f_1(z) * WhitePoint -> Z; + +} + +static +cmsFloat64Number L2float2(cmsUInt16Number v) +{ + return (cmsFloat64Number) v / 652.800; +} + +// the a/b part +static +cmsFloat64Number ab2float2(cmsUInt16Number v) +{ + return ((cmsFloat64Number) v / 256.0) - 128.0; +} + +static +cmsUInt16Number L2Fix2(cmsFloat64Number L) +{ + return _cmsQuickSaturateWord(L * 652.8); +} + +static +cmsUInt16Number ab2Fix2(cmsFloat64Number ab) +{ + return _cmsQuickSaturateWord((ab + 128.0) * 256.0); +} + + +static +cmsFloat64Number L2float4(cmsUInt16Number v) +{ + return (cmsFloat64Number) v / 655.35; +} + +// the a/b part +static +cmsFloat64Number ab2float4(cmsUInt16Number v) +{ + return ((cmsFloat64Number) v / 257.0) - 128.0; +} + + +void CMSEXPORT cmsLabEncoded2FloatV2(cmsCIELab* Lab, const cmsUInt16Number wLab[3]) +{ + Lab->L = L2float2(wLab[0]); + Lab->a = ab2float2(wLab[1]); + Lab->b = ab2float2(wLab[2]); +} + + +void CMSEXPORT cmsLabEncoded2Float(cmsCIELab* Lab, const cmsUInt16Number wLab[3]) +{ + Lab->L = L2float4(wLab[0]); + Lab->a = ab2float4(wLab[1]); + Lab->b = ab2float4(wLab[2]); +} + +static +cmsFloat64Number Clamp_L_doubleV2(cmsFloat64Number L) +{ + const cmsFloat64Number L_max = (cmsFloat64Number) (0xFFFF * 100.0) / 0xFF00; + + if (L < 0) L = 0; + if (L > L_max) L = L_max; + + return L; +} + + +static +cmsFloat64Number Clamp_ab_doubleV2(cmsFloat64Number ab) +{ + if (ab < MIN_ENCODEABLE_ab2) ab = MIN_ENCODEABLE_ab2; + if (ab > MAX_ENCODEABLE_ab2) ab = MAX_ENCODEABLE_ab2; + + return ab; +} + +void CMSEXPORT cmsFloat2LabEncodedV2(cmsUInt16Number wLab[3], const cmsCIELab* fLab) +{ + cmsCIELab Lab; + + Lab.L = Clamp_L_doubleV2(fLab ->L); + Lab.a = Clamp_ab_doubleV2(fLab ->a); + Lab.b = Clamp_ab_doubleV2(fLab ->b); + + wLab[0] = L2Fix2(Lab.L); + wLab[1] = ab2Fix2(Lab.a); + wLab[2] = ab2Fix2(Lab.b); +} + + +static +cmsFloat64Number Clamp_L_doubleV4(cmsFloat64Number L) +{ + if (L < 0) L = 0; + if (L > 100.0) L = 100.0; + + return L; +} + +static +cmsFloat64Number Clamp_ab_doubleV4(cmsFloat64Number ab) +{ + if (ab < MIN_ENCODEABLE_ab4) ab = MIN_ENCODEABLE_ab4; + if (ab > MAX_ENCODEABLE_ab4) ab = MAX_ENCODEABLE_ab4; + + return ab; +} + +static +cmsUInt16Number L2Fix4(cmsFloat64Number L) +{ + return _cmsQuickSaturateWord(L * 655.35); +} + +static +cmsUInt16Number ab2Fix4(cmsFloat64Number ab) +{ + return _cmsQuickSaturateWord((ab + 128.0) * 257.0); +} + +void CMSEXPORT cmsFloat2LabEncoded(cmsUInt16Number wLab[3], const cmsCIELab* fLab) +{ + cmsCIELab Lab; + + Lab.L = Clamp_L_doubleV4(fLab ->L); + Lab.a = Clamp_ab_doubleV4(fLab ->a); + Lab.b = Clamp_ab_doubleV4(fLab ->b); + + wLab[0] = L2Fix4(Lab.L); + wLab[1] = ab2Fix4(Lab.a); + wLab[2] = ab2Fix4(Lab.b); +} + +// Auxiliar: convert to Radians +static +cmsFloat64Number RADIANS(cmsFloat64Number deg) +{ + return (deg * M_PI) / 180.; +} + + +// Auxiliar: atan2 but operating in degrees and returning 0 if a==b==0 +static +cmsFloat64Number atan2deg(cmsFloat64Number a, cmsFloat64Number b) +{ + cmsFloat64Number h; + + if (a == 0 && b == 0) + h = 0; + else + h = atan2(a, b); + + h *= (180. / M_PI); + + while (h > 360.) + h -= 360.; + + while ( h < 0) + h += 360.; + + return h; +} + + +// Auxiliar: Square +static +cmsFloat64Number Sqr(cmsFloat64Number v) +{ + return v * v; +} +// From cylindrical coordinates. No check is performed, then negative values are allowed +void CMSEXPORT cmsLab2LCh(cmsCIELCh* LCh, const cmsCIELab* Lab) +{ + LCh -> L = Lab -> L; + LCh -> C = pow(Sqr(Lab ->a) + Sqr(Lab ->b), 0.5); + LCh -> h = atan2deg(Lab ->b, Lab ->a); +} + + +// To cylindrical coordinates. No check is performed, then negative values are allowed +void CMSEXPORT cmsLCh2Lab(cmsCIELab* Lab, const cmsCIELCh* LCh) +{ + cmsFloat64Number h = (LCh -> h * M_PI) / 180.0; + + Lab -> L = LCh -> L; + Lab -> a = LCh -> C * cos(h); + Lab -> b = LCh -> C * sin(h); +} + +// In XYZ All 3 components are encoded using 1.15 fixed point +static +cmsUInt16Number XYZ2Fix(cmsFloat64Number d) +{ + return _cmsQuickSaturateWord(d * 32768.0); +} + +void CMSEXPORT cmsFloat2XYZEncoded(cmsUInt16Number XYZ[3], const cmsCIEXYZ* fXYZ) +{ + cmsCIEXYZ xyz; + + xyz.X = fXYZ -> X; + xyz.Y = fXYZ -> Y; + xyz.Z = fXYZ -> Z; + + // Clamp to encodeable values. + if (xyz.Y <= 0) { + + xyz.X = 0; + xyz.Y = 0; + xyz.Z = 0; + } + + if (xyz.X > MAX_ENCODEABLE_XYZ) + xyz.X = MAX_ENCODEABLE_XYZ; + + if (xyz.X < 0) + xyz.X = 0; + + if (xyz.Y > MAX_ENCODEABLE_XYZ) + xyz.Y = MAX_ENCODEABLE_XYZ; + + if (xyz.Y < 0) + xyz.Y = 0; + + if (xyz.Z > MAX_ENCODEABLE_XYZ) + xyz.Z = MAX_ENCODEABLE_XYZ; + + if (xyz.Z < 0) + xyz.Z = 0; + + + XYZ[0] = XYZ2Fix(xyz.X); + XYZ[1] = XYZ2Fix(xyz.Y); + XYZ[2] = XYZ2Fix(xyz.Z); +} + + +// To convert from Fixed 1.15 point to cmsFloat64Number +static +cmsFloat64Number XYZ2float(cmsUInt16Number v) +{ + cmsS15Fixed16Number fix32; + + // From 1.15 to 15.16 + fix32 = v << 1; + + // From fixed 15.16 to cmsFloat64Number + return _cms15Fixed16toDouble(fix32); +} + + +void CMSEXPORT cmsXYZEncoded2Float(cmsCIEXYZ* fXYZ, const cmsUInt16Number XYZ[3]) +{ + fXYZ -> X = XYZ2float(XYZ[0]); + fXYZ -> Y = XYZ2float(XYZ[1]); + fXYZ -> Z = XYZ2float(XYZ[2]); +} + + +// Returns dE on two Lab values +cmsFloat64Number CMSEXPORT cmsDeltaE(const cmsCIELab* Lab1, const cmsCIELab* Lab2) +{ + cmsFloat64Number dL, da, db; + + dL = fabs(Lab1 -> L - Lab2 -> L); + da = fabs(Lab1 -> a - Lab2 -> a); + db = fabs(Lab1 -> b - Lab2 -> b); + + return pow(Sqr(dL) + Sqr(da) + Sqr(db), 0.5); +} + + +// Return the CIE94 Delta E +cmsFloat64Number CMSEXPORT cmsCIE94DeltaE(const cmsCIELab* Lab1, const cmsCIELab* Lab2) +{ + cmsCIELCh LCh1, LCh2; + cmsFloat64Number dE, dL, dC, dh, dhsq; + cmsFloat64Number c12, sc, sh; + + dL = fabs(Lab1 ->L - Lab2 ->L); + + cmsLab2LCh(&LCh1, Lab1); + cmsLab2LCh(&LCh2, Lab2); + + dC = fabs(LCh1.C - LCh2.C); + dE = cmsDeltaE(Lab1, Lab2); + + dhsq = Sqr(dE) - Sqr(dL) - Sqr(dC); + if (dhsq < 0) + dh = 0; + else + dh = pow(dhsq, 0.5); + + c12 = sqrt(LCh1.C * LCh2.C); + + sc = 1.0 + (0.048 * c12); + sh = 1.0 + (0.014 * c12); + + return sqrt(Sqr(dL) + Sqr(dC) / Sqr(sc) + Sqr(dh) / Sqr(sh)); +} + + +// Auxiliary +static +cmsFloat64Number ComputeLBFD(const cmsCIELab* Lab) +{ + cmsFloat64Number yt; + + if (Lab->L > 7.996969) + yt = (Sqr((Lab->L+16)/116)*((Lab->L+16)/116))*100; + else + yt = 100 * (Lab->L / 903.3); + + return (54.6 * (M_LOG10E * (log(yt + 1.5))) - 9.6); +} + + + +// bfd - gets BFD(1:1) difference between Lab1, Lab2 +cmsFloat64Number CMSEXPORT cmsBFDdeltaE(const cmsCIELab* Lab1, const cmsCIELab* Lab2) +{ + cmsFloat64Number lbfd1,lbfd2,AveC,Aveh,dE,deltaL, + deltaC,deltah,dc,t,g,dh,rh,rc,rt,bfd; + cmsCIELCh LCh1, LCh2; + + + lbfd1 = ComputeLBFD(Lab1); + lbfd2 = ComputeLBFD(Lab2); + deltaL = lbfd2 - lbfd1; + + cmsLab2LCh(&LCh1, Lab1); + cmsLab2LCh(&LCh2, Lab2); + + deltaC = LCh2.C - LCh1.C; + AveC = (LCh1.C+LCh2.C)/2; + Aveh = (LCh1.h+LCh2.h)/2; + + dE = cmsDeltaE(Lab1, Lab2); + + if (Sqr(dE)>(Sqr(Lab2->L-Lab1->L)+Sqr(deltaC))) + deltah = sqrt(Sqr(dE)-Sqr(Lab2->L-Lab1->L)-Sqr(deltaC)); + else + deltah =0; + + + dc = 0.035 * AveC / (1 + 0.00365 * AveC)+0.521; + g = sqrt(Sqr(Sqr(AveC))/(Sqr(Sqr(AveC))+14000)); + t = 0.627+(0.055*cos((Aveh-254)/(180/M_PI))- + 0.040*cos((2*Aveh-136)/(180/M_PI))+ + 0.070*cos((3*Aveh-31)/(180/M_PI))+ + 0.049*cos((4*Aveh+114)/(180/M_PI))- + 0.015*cos((5*Aveh-103)/(180/M_PI))); + + dh = dc*(g*t+1-g); + rh = -0.260*cos((Aveh-308)/(180/M_PI))- + 0.379*cos((2*Aveh-160)/(180/M_PI))- + 0.636*cos((3*Aveh+254)/(180/M_PI))+ + 0.226*cos((4*Aveh+140)/(180/M_PI))- + 0.194*cos((5*Aveh+280)/(180/M_PI)); + + rc = sqrt((AveC*AveC*AveC*AveC*AveC*AveC)/((AveC*AveC*AveC*AveC*AveC*AveC)+70000000)); + rt = rh*rc; + + bfd = sqrt(Sqr(deltaL)+Sqr(deltaC/dc)+Sqr(deltah/dh)+(rt*(deltaC/dc)*(deltah/dh))); + + return bfd; +} + + +// cmc - CMC(l:c) difference between Lab1, Lab2 +cmsFloat64Number CMSEXPORT cmsCMCdeltaE(const cmsCIELab* Lab1, const cmsCIELab* Lab2, cmsFloat64Number l, cmsFloat64Number c) +{ + cmsFloat64Number dE,dL,dC,dh,sl,sc,sh,t,f,cmc; + cmsCIELCh LCh1, LCh2; + + if (Lab1 ->L == 0 && Lab2 ->L == 0) return 0; + + cmsLab2LCh(&LCh1, Lab1); + cmsLab2LCh(&LCh2, Lab2); + + + dL = Lab2->L-Lab1->L; + dC = LCh2.C-LCh1.C; + + dE = cmsDeltaE(Lab1, Lab2); + + if (Sqr(dE)>(Sqr(dL)+Sqr(dC))) + dh = sqrt(Sqr(dE)-Sqr(dL)-Sqr(dC)); + else + dh =0; + + if ((LCh1.h > 164) && (LCh1.h < 345)) + t = 0.56 + fabs(0.2 * cos(((LCh1.h + 168)/(180/M_PI)))); + else + t = 0.36 + fabs(0.4 * cos(((LCh1.h + 35 )/(180/M_PI)))); + + sc = 0.0638 * LCh1.C / (1 + 0.0131 * LCh1.C) + 0.638; + sl = 0.040975 * Lab1->L /(1 + 0.01765 * Lab1->L); + + if (Lab1->L<16) + sl = 0.511; + + f = sqrt((LCh1.C * LCh1.C * LCh1.C * LCh1.C)/((LCh1.C * LCh1.C * LCh1.C * LCh1.C)+1900)); + sh = sc*(t*f+1-f); + cmc = sqrt(Sqr(dL/(l*sl))+Sqr(dC/(c*sc))+Sqr(dh/sh)); + + return cmc; +} + +// dE2000 The weightings KL, KC and KH can be modified to reflect the relative +// importance of lightness, chroma and hue in different industrial applications +cmsFloat64Number CMSEXPORT cmsCIE2000DeltaE(const cmsCIELab* Lab1, const cmsCIELab* Lab2, + cmsFloat64Number Kl, cmsFloat64Number Kc, cmsFloat64Number Kh) +{ + cmsFloat64Number L1 = Lab1->L; + cmsFloat64Number a1 = Lab1->a; + cmsFloat64Number b1 = Lab1->b; + cmsFloat64Number C = sqrt( Sqr(a1) + Sqr(b1) ); + + cmsFloat64Number Ls = Lab2 ->L; + cmsFloat64Number as = Lab2 ->a; + cmsFloat64Number bs = Lab2 ->b; + cmsFloat64Number Cs = sqrt( Sqr(as) + Sqr(bs) ); + + cmsFloat64Number G = 0.5 * ( 1 - sqrt(pow((C + Cs) / 2 , 7.0) / (pow((C + Cs) / 2, 7.0) + pow(25.0, 7.0) ) )); + + cmsFloat64Number a_p = (1 + G ) * a1; + cmsFloat64Number b_p = b1; + cmsFloat64Number C_p = sqrt( Sqr(a_p) + Sqr(b_p)); + cmsFloat64Number h_p = atan2deg(b_p, a_p); + + + cmsFloat64Number a_ps = (1 + G) * as; + cmsFloat64Number b_ps = bs; + cmsFloat64Number C_ps = sqrt(Sqr(a_ps) + Sqr(b_ps)); + cmsFloat64Number h_ps = atan2deg(b_ps, a_ps); + + cmsFloat64Number meanC_p =(C_p + C_ps) / 2; + + cmsFloat64Number hps_plus_hp = h_ps + h_p; + cmsFloat64Number hps_minus_hp = h_ps - h_p; + + cmsFloat64Number meanh_p = fabs(hps_minus_hp) <= 180.000001 ? (hps_plus_hp)/2 : + (hps_plus_hp) < 360 ? (hps_plus_hp + 360)/2 : + (hps_plus_hp - 360)/2; + + cmsFloat64Number delta_h = (hps_minus_hp) <= -180.000001 ? (hps_minus_hp + 360) : + (hps_minus_hp) > 180 ? (hps_minus_hp - 360) : + (hps_minus_hp); + cmsFloat64Number delta_L = (Ls - L1); + cmsFloat64Number delta_C = (C_ps - C_p ); + + + cmsFloat64Number delta_H =2 * sqrt(C_ps*C_p) * sin(RADIANS(delta_h) / 2); + + cmsFloat64Number T = 1 - 0.17 * cos(RADIANS(meanh_p-30)) + + 0.24 * cos(RADIANS(2*meanh_p)) + + 0.32 * cos(RADIANS(3*meanh_p + 6)) + - 0.2 * cos(RADIANS(4*meanh_p - 63)); + + cmsFloat64Number Sl = 1 + (0.015 * Sqr((Ls + L1) /2- 50) )/ sqrt(20 + Sqr( (Ls+L1)/2 - 50) ); + + cmsFloat64Number Sc = 1 + 0.045 * (C_p + C_ps)/2; + cmsFloat64Number Sh = 1 + 0.015 * ((C_ps + C_p)/2) * T; + + cmsFloat64Number delta_ro = 30 * exp( -Sqr(((meanh_p - 275 ) / 25))); + + cmsFloat64Number Rc = 2 * sqrt(( pow(meanC_p, 7.0) )/( pow(meanC_p, 7.0) + pow(25.0, 7.0))); + + cmsFloat64Number Rt = -sin(2 * RADIANS(delta_ro)) * Rc; + + cmsFloat64Number deltaE00 = sqrt( Sqr(delta_L /(Sl * Kl)) + + Sqr(delta_C/(Sc * Kc)) + + Sqr(delta_H/(Sh * Kh)) + + Rt*(delta_C/(Sc * Kc)) * (delta_H / (Sh * Kh))); + + return deltaE00; +} + +// This function returns a number of gridpoints to be used as LUT table. It assumes same number +// of gripdpoints in all dimensions. Flags may override the choice. +int _cmsReasonableGridpointsByColorspace(cmsColorSpaceSignature Colorspace, cmsUInt32Number dwFlags) +{ + int nChannels; + + // Already specified? + if (dwFlags & 0x00FF0000) { + // Yes, grab'em + return (dwFlags >> 16) & 0xFF; + } + + nChannels = cmsChannelsOf(Colorspace); + + // HighResPrecalc is maximum resolution + if (dwFlags & cmsFLAGS_HIGHRESPRECALC) { + + if (nChannels > 4) + return 7; // 7 for Hifi + + if (nChannels == 4) // 23 for CMYK + return 23; + + return 49; // 49 for RGB and others + } + + + // LowResPrecal is lower resolution + if (dwFlags & cmsFLAGS_LOWRESPRECALC) { + + if (nChannels > 4) + return 6; // 6 for more than 4 channels + + if (nChannels == 1) + return 33; // For monochrome + + return 17; // 17 for remaining + } + + // Default values + if (nChannels > 4) + return 7; // 7 for Hifi + + if (nChannels == 4) + return 17; // 17 for CMYK + + return 33; // 33 for RGB +} + + +cmsBool _cmsEndPointsBySpace(cmsColorSpaceSignature Space, + cmsUInt16Number **White, + cmsUInt16Number **Black, + cmsUInt32Number *nOutputs) +{ + // Only most common spaces + + static cmsUInt16Number RGBblack[4] = { 0, 0, 0 }; + static cmsUInt16Number RGBwhite[4] = { 0xffff, 0xffff, 0xffff }; + static cmsUInt16Number CMYKblack[4] = { 0xffff, 0xffff, 0xffff, 0xffff }; // 400% of ink + static cmsUInt16Number CMYKwhite[4] = { 0, 0, 0, 0 }; + static cmsUInt16Number LABblack[4] = { 0, 0x8080, 0x8080 }; // V4 Lab encoding + static cmsUInt16Number LABwhite[4] = { 0xFFFF, 0x8080, 0x8080 }; + static cmsUInt16Number CMYblack[4] = { 0xffff, 0xffff, 0xffff }; + static cmsUInt16Number CMYwhite[4] = { 0, 0, 0 }; + static cmsUInt16Number Grayblack[4] = { 0 }; + static cmsUInt16Number GrayWhite[4] = { 0xffff }; + + switch (Space) { + + case cmsSigGrayData: if (White) *White = GrayWhite; + if (Black) *Black = Grayblack; + if (nOutputs) *nOutputs = 1; + return TRUE; + + case cmsSigRgbData: if (White) *White = RGBwhite; + if (Black) *Black = RGBblack; + if (nOutputs) *nOutputs = 3; + return TRUE; + + case cmsSigLabData: if (White) *White = LABwhite; + if (Black) *Black = LABblack; + if (nOutputs) *nOutputs = 3; + return TRUE; + + case cmsSigCmykData: if (White) *White = CMYKwhite; + if (Black) *Black = CMYKblack; + if (nOutputs) *nOutputs = 4; + return TRUE; + + case cmsSigCmyData: if (White) *White = CMYwhite; + if (Black) *Black = CMYblack; + if (nOutputs) *nOutputs = 3; + return TRUE; + + default:; + } + + return FALSE; +} + + + +// Several utilities ------------------------------------------------------- + +// Translate from our colorspace to ICC representation + +cmsColorSpaceSignature CMSEXPORT _cmsICCcolorSpace(int OurNotation) +{ + switch (OurNotation) { + + case 1: + case PT_GRAY: return cmsSigGrayData; + + case 2: + case PT_RGB: return cmsSigRgbData; + + case PT_CMY: return cmsSigCmyData; + case PT_CMYK: return cmsSigCmykData; + case PT_YCbCr:return cmsSigYCbCrData; + case PT_YUV: return cmsSigLuvData; + case PT_XYZ: return cmsSigXYZData; + + case PT_LabV2: + case PT_Lab: return cmsSigLabData; + + case PT_YUVK: return cmsSigLuvKData; + case PT_HSV: return cmsSigHsvData; + case PT_HLS: return cmsSigHlsData; + case PT_Yxy: return cmsSigYxyData; + + case PT_MCH1: return cmsSigMCH1Data; + case PT_MCH2: return cmsSigMCH2Data; + case PT_MCH3: return cmsSigMCH3Data; + case PT_MCH4: return cmsSigMCH4Data; + case PT_MCH5: return cmsSigMCH5Data; + case PT_MCH6: return cmsSigMCH6Data; + case PT_MCH7: return cmsSigMCH7Data; + case PT_MCH8: return cmsSigMCH8Data; + + case PT_MCH9: return cmsSigMCH9Data; + case PT_MCH10: return cmsSigMCHAData; + case PT_MCH11: return cmsSigMCHBData; + case PT_MCH12: return cmsSigMCHCData; + case PT_MCH13: return cmsSigMCHDData; + case PT_MCH14: return cmsSigMCHEData; + case PT_MCH15: return cmsSigMCHFData; + + default: return (cmsColorSpaceSignature) (-1); + } +} + + +int CMSEXPORT _cmsLCMScolorSpace(cmsColorSpaceSignature ProfileSpace) +{ + switch (ProfileSpace) { + + case cmsSigGrayData: return PT_GRAY; + case cmsSigRgbData: return PT_RGB; + case cmsSigCmyData: return PT_CMY; + case cmsSigCmykData: return PT_CMYK; + case cmsSigYCbCrData:return PT_YCbCr; + case cmsSigLuvData: return PT_YUV; + case cmsSigXYZData: return PT_XYZ; + case cmsSigLabData: return PT_Lab; + case cmsSigLuvKData: return PT_YUVK; + case cmsSigHsvData: return PT_HSV; + case cmsSigHlsData: return PT_HLS; + case cmsSigYxyData: return PT_Yxy; + + case cmsSig1colorData: + case cmsSigMCH1Data: return PT_MCH1; + + case cmsSig2colorData: + case cmsSigMCH2Data: return PT_MCH2; + + case cmsSig3colorData: + case cmsSigMCH3Data: return PT_MCH3; + + case cmsSig4colorData: + case cmsSigMCH4Data: return PT_MCH4; + + case cmsSig5colorData: + case cmsSigMCH5Data: return PT_MCH5; + + case cmsSig6colorData: + case cmsSigMCH6Data: return PT_MCH6; + + case cmsSigMCH7Data: + case cmsSig7colorData:return PT_MCH7; + + case cmsSigMCH8Data: + case cmsSig8colorData:return PT_MCH8; + + case cmsSigMCH9Data: + case cmsSig9colorData:return PT_MCH9; + + case cmsSigMCHAData: + case cmsSig10colorData:return PT_MCH10; + + case cmsSigMCHBData: + case cmsSig11colorData:return PT_MCH11; + + case cmsSigMCHCData: + case cmsSig12colorData:return PT_MCH12; + + case cmsSigMCHDData: + case cmsSig13colorData:return PT_MCH13; + + case cmsSigMCHEData: + case cmsSig14colorData:return PT_MCH14; + + case cmsSigMCHFData: + case cmsSig15colorData:return PT_MCH15; + + default: return (cmsColorSpaceSignature) (-1); + } +} + + +cmsUInt32Number CMSEXPORT cmsChannelsOf(cmsColorSpaceSignature ColorSpace) +{ + switch (ColorSpace) { + + case cmsSigMCH1Data: + case cmsSig1colorData: + case cmsSigGrayData: return 1; + + case cmsSigMCH2Data: + case cmsSig2colorData: return 2; + + case cmsSigXYZData: + case cmsSigLabData: + case cmsSigLuvData: + case cmsSigYCbCrData: + case cmsSigYxyData: + case cmsSigRgbData: + case cmsSigHsvData: + case cmsSigHlsData: + case cmsSigCmyData: + case cmsSigMCH3Data: + case cmsSig3colorData: return 3; + + case cmsSigLuvKData: + case cmsSigCmykData: + case cmsSigMCH4Data: + case cmsSig4colorData: return 4; + + case cmsSigMCH5Data: + case cmsSig5colorData: return 5; + + case cmsSigMCH6Data: + case cmsSig6colorData: return 6; + + case cmsSigMCH7Data: + case cmsSig7colorData: return 7; + + case cmsSigMCH8Data: + case cmsSig8colorData: return 8; + + case cmsSigMCH9Data: + case cmsSig9colorData: return 9; + + case cmsSigMCHAData: + case cmsSig10colorData: return 10; + + case cmsSigMCHBData: + case cmsSig11colorData: return 11; + + case cmsSigMCHCData: + case cmsSig12colorData: return 12; + + case cmsSigMCHDData: + case cmsSig13colorData: return 13; + + case cmsSigMCHEData: + case cmsSig14colorData: return 14; + + case cmsSigMCHFData: + case cmsSig15colorData: return 15; + + default: return 3; + } +} diff --git a/jni/lcms2-2.5/src/cmsplugin.c b/jni/lcms2-2.5/src/cmsplugin.c new file mode 100644 index 00000000..e334fac6 --- /dev/null +++ b/jni/lcms2-2.5/src/cmsplugin.c @@ -0,0 +1,626 @@ +//--------------------------------------------------------------------------------- +// +// Little Color Management System +// Copyright (c) 1998-2010 Marti Maria Saguer +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//--------------------------------------------------------------------------------- +// + +#include "lcms2_internal.h" + + +// ---------------------------------------------------------------------------------- +// Encoding & Decoding support functions +// ---------------------------------------------------------------------------------- + +// Little-Endian to Big-Endian + +// Adjust a word value after being readed/ before being written from/to an ICC profile +cmsUInt16Number CMSEXPORT _cmsAdjustEndianess16(cmsUInt16Number Word) +{ +#ifndef CMS_USE_BIG_ENDIAN + + cmsUInt8Number* pByte = (cmsUInt8Number*) &Word; + cmsUInt8Number tmp; + + tmp = pByte[0]; + pByte[0] = pByte[1]; + pByte[1] = tmp; +#endif + + return Word; +} + + +// Transports to properly encoded values - note that icc profiles does use big endian notation. + +// 1 2 3 4 +// 4 3 2 1 + +cmsUInt32Number CMSEXPORT _cmsAdjustEndianess32(cmsUInt32Number DWord) +{ +#ifndef CMS_USE_BIG_ENDIAN + + cmsUInt8Number* pByte = (cmsUInt8Number*) &DWord; + cmsUInt8Number temp1; + cmsUInt8Number temp2; + + temp1 = *pByte++; + temp2 = *pByte++; + *(pByte-1) = *pByte; + *pByte++ = temp2; + *(pByte-3) = *pByte; + *pByte = temp1; +#endif + return DWord; +} + +// 1 2 3 4 5 6 7 8 +// 8 7 6 5 4 3 2 1 + +void CMSEXPORT _cmsAdjustEndianess64(cmsUInt64Number* Result, cmsUInt64Number* QWord) +{ + +#ifndef CMS_USE_BIG_ENDIAN + + cmsUInt8Number* pIn = (cmsUInt8Number*) QWord; + cmsUInt8Number* pOut = (cmsUInt8Number*) Result; + + _cmsAssert(Result != NULL); + + pOut[7] = pIn[0]; + pOut[6] = pIn[1]; + pOut[5] = pIn[2]; + pOut[4] = pIn[3]; + pOut[3] = pIn[4]; + pOut[2] = pIn[5]; + pOut[1] = pIn[6]; + pOut[0] = pIn[7]; + +#else + _cmsAssert(Result != NULL); + +# ifdef CMS_DONT_USE_INT64 + (*Result)[0] = QWord[0]; + (*Result)[1] = QWord[1]; +# else + *Result = *QWord; +# endif +#endif +} + +// Auxiliar -- read 8, 16 and 32-bit numbers +cmsBool CMSEXPORT _cmsReadUInt8Number(cmsIOHANDLER* io, cmsUInt8Number* n) +{ + cmsUInt8Number tmp; + + _cmsAssert(io != NULL); + + if (io -> Read(io, &tmp, sizeof(cmsUInt8Number), 1) != 1) + return FALSE; + + if (n != NULL) *n = tmp; + return TRUE; +} + +cmsBool CMSEXPORT _cmsReadUInt16Number(cmsIOHANDLER* io, cmsUInt16Number* n) +{ + cmsUInt16Number tmp; + + _cmsAssert(io != NULL); + + if (io -> Read(io, &tmp, sizeof(cmsUInt16Number), 1) != 1) + return FALSE; + + if (n != NULL) *n = _cmsAdjustEndianess16(tmp); + return TRUE; +} + +cmsBool CMSEXPORT _cmsReadUInt16Array(cmsIOHANDLER* io, cmsUInt32Number n, cmsUInt16Number* Array) +{ + cmsUInt32Number i; + + _cmsAssert(io != NULL); + + for (i=0; i < n; i++) { + + if (Array != NULL) { + if (!_cmsReadUInt16Number(io, Array + i)) return FALSE; + } + else { + if (!_cmsReadUInt16Number(io, NULL)) return FALSE; + } + + } + return TRUE; +} + +cmsBool CMSEXPORT _cmsReadUInt32Number(cmsIOHANDLER* io, cmsUInt32Number* n) +{ + cmsUInt32Number tmp; + + _cmsAssert(io != NULL); + + if (io -> Read(io, &tmp, sizeof(cmsUInt32Number), 1) != 1) + return FALSE; + + if (n != NULL) *n = _cmsAdjustEndianess32(tmp); + return TRUE; +} + +cmsBool CMSEXPORT _cmsReadFloat32Number(cmsIOHANDLER* io, cmsFloat32Number* n) +{ + cmsUInt32Number tmp; + + _cmsAssert(io != NULL); + + if (io -> Read(io, &tmp, sizeof(cmsFloat32Number), 1) != 1) + return FALSE; + + if (n != NULL) { + + tmp = _cmsAdjustEndianess32(tmp); + *n = *(cmsFloat32Number*) &tmp; + } + return TRUE; +} + + +cmsBool CMSEXPORT _cmsReadUInt64Number(cmsIOHANDLER* io, cmsUInt64Number* n) +{ + cmsUInt64Number tmp; + + _cmsAssert(io != NULL); + + if (io -> Read(io, &tmp, sizeof(cmsUInt64Number), 1) != 1) + return FALSE; + + if (n != NULL) _cmsAdjustEndianess64(n, &tmp); + return TRUE; +} + + +cmsBool CMSEXPORT _cmsRead15Fixed16Number(cmsIOHANDLER* io, cmsFloat64Number* n) +{ + cmsUInt32Number tmp; + + _cmsAssert(io != NULL); + + if (io -> Read(io, &tmp, sizeof(cmsUInt32Number), 1) != 1) + return FALSE; + + if (n != NULL) { + *n = _cms15Fixed16toDouble(_cmsAdjustEndianess32(tmp)); + } + + return TRUE; +} + + +// Jun-21-2000: Some profiles (those that comes with W2K) comes +// with the media white (media black?) x 100. Add a sanity check + +static +void NormalizeXYZ(cmsCIEXYZ* Dest) +{ + while (Dest -> X > 2. && + Dest -> Y > 2. && + Dest -> Z > 2.) { + + Dest -> X /= 10.; + Dest -> Y /= 10.; + Dest -> Z /= 10.; + } +} + +cmsBool CMSEXPORT _cmsReadXYZNumber(cmsIOHANDLER* io, cmsCIEXYZ* XYZ) +{ + cmsEncodedXYZNumber xyz; + + _cmsAssert(io != NULL); + + if (io ->Read(io, &xyz, sizeof(cmsEncodedXYZNumber), 1) != 1) return FALSE; + + if (XYZ != NULL) { + + XYZ->X = _cms15Fixed16toDouble(_cmsAdjustEndianess32(xyz.X)); + XYZ->Y = _cms15Fixed16toDouble(_cmsAdjustEndianess32(xyz.Y)); + XYZ->Z = _cms15Fixed16toDouble(_cmsAdjustEndianess32(xyz.Z)); + + NormalizeXYZ(XYZ); + } + return TRUE; +} + +cmsBool CMSEXPORT _cmsWriteUInt8Number(cmsIOHANDLER* io, cmsUInt8Number n) +{ + _cmsAssert(io != NULL); + + if (io -> Write(io, sizeof(cmsUInt8Number), &n) != 1) + return FALSE; + + return TRUE; +} + +cmsBool CMSEXPORT _cmsWriteUInt16Number(cmsIOHANDLER* io, cmsUInt16Number n) +{ + cmsUInt16Number tmp; + + _cmsAssert(io != NULL); + + tmp = _cmsAdjustEndianess16(n); + if (io -> Write(io, sizeof(cmsUInt16Number), &tmp) != 1) + return FALSE; + + return TRUE; +} + +cmsBool CMSEXPORT _cmsWriteUInt16Array(cmsIOHANDLER* io, cmsUInt32Number n, const cmsUInt16Number* Array) +{ + cmsUInt32Number i; + + _cmsAssert(io != NULL); + _cmsAssert(Array != NULL); + + for (i=0; i < n; i++) { + if (!_cmsWriteUInt16Number(io, Array[i])) return FALSE; + } + + return TRUE; +} + +cmsBool CMSEXPORT _cmsWriteUInt32Number(cmsIOHANDLER* io, cmsUInt32Number n) +{ + cmsUInt32Number tmp; + + _cmsAssert(io != NULL); + + tmp = _cmsAdjustEndianess32(n); + if (io -> Write(io, sizeof(cmsUInt32Number), &tmp) != 1) + return FALSE; + + return TRUE; +} + + +cmsBool CMSEXPORT _cmsWriteFloat32Number(cmsIOHANDLER* io, cmsFloat32Number n) +{ + cmsUInt32Number tmp; + + _cmsAssert(io != NULL); + + tmp = *(cmsUInt32Number*) &n; + tmp = _cmsAdjustEndianess32(tmp); + if (io -> Write(io, sizeof(cmsUInt32Number), &tmp) != 1) + return FALSE; + + return TRUE; +} + +cmsBool CMSEXPORT _cmsWriteUInt64Number(cmsIOHANDLER* io, cmsUInt64Number* n) +{ + cmsUInt64Number tmp; + + _cmsAssert(io != NULL); + + _cmsAdjustEndianess64(&tmp, n); + if (io -> Write(io, sizeof(cmsUInt64Number), &tmp) != 1) + return FALSE; + + return TRUE; +} + +cmsBool CMSEXPORT _cmsWrite15Fixed16Number(cmsIOHANDLER* io, cmsFloat64Number n) +{ + cmsUInt32Number tmp; + + _cmsAssert(io != NULL); + + tmp = _cmsAdjustEndianess32(_cmsDoubleTo15Fixed16(n)); + if (io -> Write(io, sizeof(cmsUInt32Number), &tmp) != 1) + return FALSE; + + return TRUE; +} + +cmsBool CMSEXPORT _cmsWriteXYZNumber(cmsIOHANDLER* io, const cmsCIEXYZ* XYZ) +{ + cmsEncodedXYZNumber xyz; + + _cmsAssert(io != NULL); + _cmsAssert(XYZ != NULL); + + xyz.X = _cmsAdjustEndianess32(_cmsDoubleTo15Fixed16(XYZ->X)); + xyz.Y = _cmsAdjustEndianess32(_cmsDoubleTo15Fixed16(XYZ->Y)); + xyz.Z = _cmsAdjustEndianess32(_cmsDoubleTo15Fixed16(XYZ->Z)); + + return io -> Write(io, sizeof(cmsEncodedXYZNumber), &xyz); +} + +// from Fixed point 8.8 to double +cmsFloat64Number CMSEXPORT _cms8Fixed8toDouble(cmsUInt16Number fixed8) +{ + cmsUInt8Number msb, lsb; + + lsb = (cmsUInt8Number) (fixed8 & 0xff); + msb = (cmsUInt8Number) (((cmsUInt16Number) fixed8 >> 8) & 0xff); + + return (cmsFloat64Number) ((cmsFloat64Number) msb + ((cmsFloat64Number) lsb / 256.0)); +} + +cmsUInt16Number CMSEXPORT _cmsDoubleTo8Fixed8(cmsFloat64Number val) +{ + cmsS15Fixed16Number GammaFixed32 = _cmsDoubleTo15Fixed16(val); + return (cmsUInt16Number) ((GammaFixed32 >> 8) & 0xFFFF); +} + +// from Fixed point 15.16 to double +cmsFloat64Number CMSEXPORT _cms15Fixed16toDouble(cmsS15Fixed16Number fix32) +{ + cmsFloat64Number floater, sign, mid; + int Whole, FracPart; + + sign = (fix32 < 0 ? -1 : 1); + fix32 = abs(fix32); + + Whole = (cmsUInt16Number)(fix32 >> 16) & 0xffff; + FracPart = (cmsUInt16Number)(fix32 & 0xffff); + + mid = (cmsFloat64Number) FracPart / 65536.0; + floater = (cmsFloat64Number) Whole + mid; + + return sign * floater; +} + +// from double to Fixed point 15.16 +cmsS15Fixed16Number CMSEXPORT _cmsDoubleTo15Fixed16(cmsFloat64Number v) +{ + return ((cmsS15Fixed16Number) floor((v)*65536.0 + 0.5)); +} + +// Date/Time functions + +void CMSEXPORT _cmsDecodeDateTimeNumber(const cmsDateTimeNumber *Source, struct tm *Dest) +{ + + _cmsAssert(Dest != NULL); + _cmsAssert(Source != NULL); + + Dest->tm_sec = _cmsAdjustEndianess16(Source->seconds); + Dest->tm_min = _cmsAdjustEndianess16(Source->minutes); + Dest->tm_hour = _cmsAdjustEndianess16(Source->hours); + Dest->tm_mday = _cmsAdjustEndianess16(Source->day); + Dest->tm_mon = _cmsAdjustEndianess16(Source->month) - 1; + Dest->tm_year = _cmsAdjustEndianess16(Source->year) - 1900; + Dest->tm_wday = -1; + Dest->tm_yday = -1; + Dest->tm_isdst = 0; +} + +void CMSEXPORT _cmsEncodeDateTimeNumber(cmsDateTimeNumber *Dest, const struct tm *Source) +{ + _cmsAssert(Dest != NULL); + _cmsAssert(Source != NULL); + + Dest->seconds = _cmsAdjustEndianess16((cmsUInt16Number) Source->tm_sec); + Dest->minutes = _cmsAdjustEndianess16((cmsUInt16Number) Source->tm_min); + Dest->hours = _cmsAdjustEndianess16((cmsUInt16Number) Source->tm_hour); + Dest->day = _cmsAdjustEndianess16((cmsUInt16Number) Source->tm_mday); + Dest->month = _cmsAdjustEndianess16((cmsUInt16Number) (Source->tm_mon + 1)); + Dest->year = _cmsAdjustEndianess16((cmsUInt16Number) (Source->tm_year + 1900)); +} + +// Read base and return type base +cmsTagTypeSignature CMSEXPORT _cmsReadTypeBase(cmsIOHANDLER* io) +{ + _cmsTagBase Base; + + _cmsAssert(io != NULL); + + if (io -> Read(io, &Base, sizeof(_cmsTagBase), 1) != 1) + return (cmsTagTypeSignature) 0; + + return (cmsTagTypeSignature) _cmsAdjustEndianess32(Base.sig); +} + +// Setup base marker +cmsBool CMSEXPORT _cmsWriteTypeBase(cmsIOHANDLER* io, cmsTagTypeSignature sig) +{ + _cmsTagBase Base; + + _cmsAssert(io != NULL); + + Base.sig = (cmsTagTypeSignature) _cmsAdjustEndianess32(sig); + memset(&Base.reserved, 0, sizeof(Base.reserved)); + return io -> Write(io, sizeof(_cmsTagBase), &Base); +} + +cmsBool CMSEXPORT _cmsReadAlignment(cmsIOHANDLER* io) +{ + cmsUInt8Number Buffer[4]; + cmsUInt32Number NextAligned, At; + cmsUInt32Number BytesToNextAlignedPos; + + _cmsAssert(io != NULL); + + At = io -> Tell(io); + NextAligned = _cmsALIGNLONG(At); + BytesToNextAlignedPos = NextAligned - At; + if (BytesToNextAlignedPos == 0) return TRUE; + if (BytesToNextAlignedPos > 4) return FALSE; + + return (io ->Read(io, Buffer, BytesToNextAlignedPos, 1) == 1); +} + +cmsBool CMSEXPORT _cmsWriteAlignment(cmsIOHANDLER* io) +{ + cmsUInt8Number Buffer[4]; + cmsUInt32Number NextAligned, At; + cmsUInt32Number BytesToNextAlignedPos; + + _cmsAssert(io != NULL); + + At = io -> Tell(io); + NextAligned = _cmsALIGNLONG(At); + BytesToNextAlignedPos = NextAligned - At; + if (BytesToNextAlignedPos == 0) return TRUE; + if (BytesToNextAlignedPos > 4) return FALSE; + + memset(Buffer, 0, BytesToNextAlignedPos); + return io -> Write(io, BytesToNextAlignedPos, Buffer); +} + + +// To deal with text streams. 2K at most +cmsBool CMSEXPORT _cmsIOPrintf(cmsIOHANDLER* io, const char* frm, ...) +{ + va_list args; + int len; + cmsUInt8Number Buffer[2048]; + cmsBool rc; + + _cmsAssert(io != NULL); + _cmsAssert(frm != NULL); + + va_start(args, frm); + + len = vsnprintf((char*) Buffer, 2047, frm, args); + if (len < 0) return FALSE; // Truncated, which is a fatal error for us + + rc = io ->Write(io, len, Buffer); + + va_end(args); + + return rc; +} + + +// Plugin memory management ------------------------------------------------------------------------------------------------- + +static _cmsSubAllocator* PluginPool = NULL; + +// Specialized malloc for plug-ins, that is freed upon exit. +void* _cmsPluginMalloc(cmsContext id, cmsUInt32Number size) +{ + if (PluginPool == NULL) + PluginPool = _cmsCreateSubAlloc(id, 4*1024); + + return _cmsSubAlloc(PluginPool, size); +} + + +// Main plug-in dispatcher +cmsBool CMSEXPORT cmsPlugin(void* Plug_in) +{ + return cmsPluginTHR(NULL, Plug_in); +} + +cmsBool CMSEXPORT cmsPluginTHR(cmsContext id, void* Plug_in) +{ + cmsPluginBase* Plugin; + + for (Plugin = (cmsPluginBase*) Plug_in; + Plugin != NULL; + Plugin = Plugin -> Next) { + + if (Plugin -> Magic != cmsPluginMagicNumber) { + cmsSignalError(0, cmsERROR_UNKNOWN_EXTENSION, "Unrecognized plugin"); + return FALSE; + } + + if (Plugin ->ExpectedVersion > LCMS_VERSION) { + cmsSignalError(0, cmsERROR_UNKNOWN_EXTENSION, "plugin needs Little CMS %d, current version is %d", + Plugin ->ExpectedVersion, LCMS_VERSION); + return FALSE; + } + + switch (Plugin -> Type) { + + case cmsPluginMemHandlerSig: + if (!_cmsRegisterMemHandlerPlugin(Plugin)) return FALSE; + break; + + case cmsPluginInterpolationSig: + if (!_cmsRegisterInterpPlugin(Plugin)) return FALSE; + break; + + case cmsPluginTagTypeSig: + if (!_cmsRegisterTagTypePlugin(id, Plugin)) return FALSE; + break; + + case cmsPluginTagSig: + if (!_cmsRegisterTagPlugin(id, Plugin)) return FALSE; + break; + + case cmsPluginFormattersSig: + if (!_cmsRegisterFormattersPlugin(id, Plugin)) return FALSE; + break; + + case cmsPluginRenderingIntentSig: + if (!_cmsRegisterRenderingIntentPlugin(id, Plugin)) return FALSE; + break; + + case cmsPluginParametricCurveSig: + if (!_cmsRegisterParametricCurvesPlugin(id, Plugin)) return FALSE; + break; + + case cmsPluginMultiProcessElementSig: + if (!_cmsRegisterMultiProcessElementPlugin(id, Plugin)) return FALSE; + break; + + case cmsPluginOptimizationSig: + if (!_cmsRegisterOptimizationPlugin(id, Plugin)) return FALSE; + break; + + case cmsPluginTransformSig: + if (!_cmsRegisterTransformPlugin(id, Plugin)) return FALSE; + break; + + default: + cmsSignalError(0, cmsERROR_UNKNOWN_EXTENSION, "Unrecognized plugin type '%X'", Plugin -> Type); + return FALSE; + } + } + + // Keep a reference to the plug-in + return TRUE; +} + + +// Revert all plug-ins to default +void CMSEXPORT cmsUnregisterPlugins(void) +{ + _cmsRegisterMemHandlerPlugin(NULL); + _cmsRegisterInterpPlugin(NULL); + _cmsRegisterTagTypePlugin(NULL, NULL); + _cmsRegisterTagPlugin(NULL, NULL); + _cmsRegisterFormattersPlugin(NULL, NULL); + _cmsRegisterRenderingIntentPlugin(NULL, NULL); + _cmsRegisterParametricCurvesPlugin(NULL, NULL); + _cmsRegisterMultiProcessElementPlugin(NULL, NULL); + _cmsRegisterOptimizationPlugin(NULL, NULL); + _cmsRegisterTransformPlugin(NULL, NULL); + + if (PluginPool != NULL) + _cmsSubAllocDestroy(PluginPool); + + PluginPool = NULL; +} diff --git a/jni/lcms2-2.5/src/cmsps2.c b/jni/lcms2-2.5/src/cmsps2.c new file mode 100644 index 00000000..fe915003 --- /dev/null +++ b/jni/lcms2-2.5/src/cmsps2.c @@ -0,0 +1,1597 @@ +//--------------------------------------------------------------------------------- +// +// Little Color Management System +// Copyright (c) 1998-2011 Marti Maria Saguer +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//--------------------------------------------------------------------------------- +// + +#include "lcms2_internal.h" + +// PostScript ColorRenderingDictionary and ColorSpaceArray + + +#define MAXPSCOLS 60 // Columns on tables + +/* + Implementation + -------------- + + PostScript does use XYZ as its internal PCS. But since PostScript + interpolation tables are limited to 8 bits, I use Lab as a way to + improve the accuracy, favoring perceptual results. So, for the creation + of each CRD, CSA the profiles are converted to Lab via a device + link between profile -> Lab or Lab -> profile. The PS code necessary to + convert Lab <-> XYZ is also included. + + + + Color Space Arrays (CSA) + ================================================================================== + + In order to obtain precision, code chooses between three ways to implement + the device -> XYZ transform. These cases identifies monochrome profiles (often + implemented as a set of curves), matrix-shaper and Pipeline-based. + + Monochrome + ----------- + + This is implemented as /CIEBasedA CSA. The prelinearization curve is + placed into /DecodeA section, and matrix equals to D50. Since here is + no interpolation tables, I do the conversion directly to XYZ + + NOTE: CLUT-based monochrome profiles are NOT supported. So, cmsFLAGS_MATRIXINPUT + flag is forced on such profiles. + + [ /CIEBasedA + << + /DecodeA { transfer function } bind + /MatrixA [D50] + /RangeLMN [ 0.0 cmsD50X 0.0 cmsD50Y 0.0 cmsD50Z ] + /WhitePoint [D50] + /BlackPoint [BP] + /RenderingIntent (intent) + >> + ] + + On simpler profiles, the PCS is already XYZ, so no conversion is required. + + + Matrix-shaper based + ------------------- + + This is implemented both with /CIEBasedABC or /CIEBasedDEF on dependig + of profile implementation. Since here there are no interpolation tables, I do + the conversion directly to XYZ + + + + [ /CIEBasedABC + << + /DecodeABC [ {transfer1} {transfer2} {transfer3} ] + /MatrixABC [Matrix] + /RangeLMN [ 0.0 cmsD50X 0.0 cmsD50Y 0.0 cmsD50Z ] + /DecodeLMN [ { / 2} dup dup ] + /WhitePoint [D50] + /BlackPoint [BP] + /RenderingIntent (intent) + >> + ] + + + CLUT based + ---------- + + Lab is used in such cases. + + [ /CIEBasedDEF + << + /DecodeDEF [ ] + /Table [ p p p [<...>]] + /RangeABC [ 0 1 0 1 0 1] + /DecodeABC[ ] + /RangeLMN [ -0.236 1.254 0 1 -0.635 1.640 ] + % -128/500 1+127/500 0 1 -127/200 1+128/200 + /MatrixABC [ 1 1 1 1 0 0 0 0 -1] + /WhitePoint [D50] + /BlackPoint [BP] + /RenderingIntent (intent) + ] + + + Color Rendering Dictionaries (CRD) + ================================== + These are always implemented as CLUT, and always are using Lab. Since CRD are expected to + be used as resources, the code adds the definition as well. + + << + /ColorRenderingType 1 + /WhitePoint [ D50 ] + /BlackPoint [BP] + /MatrixPQR [ Bradford ] + /RangePQR [-0.125 1.375 -0.125 1.375 -0.125 1.375 ] + /TransformPQR [ + {4 index 3 get div 2 index 3 get mul exch pop exch pop exch pop exch pop } bind + {4 index 4 get div 2 index 4 get mul exch pop exch pop exch pop exch pop } bind + {4 index 5 get div 2 index 5 get mul exch pop exch pop exch pop exch pop } bind + ] + /MatrixABC <...> + /EncodeABC <...> + /RangeABC <.. used for XYZ -> Lab> + /EncodeLMN + /RenderTable [ p p p [<...>]] + + /RenderingIntent (Perceptual) + >> + /Current exch /ColorRendering defineresource pop + + + The following stages are used to convert from XYZ to Lab + -------------------------------------------------------- + + Input is given at LMN stage on X, Y, Z + + Encode LMN gives us f(X/Xn), f(Y/Yn), f(Z/Zn) + + /EncodeLMN [ + + { 0.964200 div dup 0.008856 le {7.787 mul 16 116 div add}{1 3 div exp} ifelse } bind + { 1.000000 div dup 0.008856 le {7.787 mul 16 116 div add}{1 3 div exp} ifelse } bind + { 0.824900 div dup 0.008856 le {7.787 mul 16 116 div add}{1 3 div exp} ifelse } bind + + ] + + + MatrixABC is used to compute f(Y/Yn), f(X/Xn) - f(Y/Yn), f(Y/Yn) - f(Z/Zn) + + | 0 1 0| + | 1 -1 0| + | 0 1 -1| + + /MatrixABC [ 0 1 0 1 -1 1 0 0 -1 ] + + EncodeABC finally gives Lab values. + + /EncodeABC [ + { 116 mul 16 sub 100 div } bind + { 500 mul 128 add 255 div } bind + { 200 mul 128 add 255 div } bind + ] + + The following stages are used to convert Lab to XYZ + ---------------------------------------------------- + + /RangeABC [ 0 1 0 1 0 1] + /DecodeABC [ { 100 mul 16 add 116 div } bind + { 255 mul 128 sub 500 div } bind + { 255 mul 128 sub 200 div } bind + ] + + /MatrixABC [ 1 1 1 1 0 0 0 0 -1] + /DecodeLMN [ + {dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse 0.964200 mul} bind + {dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse } bind + {dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse 0.824900 mul} bind + ] + + +*/ + +/* + + PostScript algorithms discussion. + ========================================================================================================= + + 1D interpolation algorithm + + + 1D interpolation (float) + ------------------------ + + val2 = Domain * Value; + + cell0 = (int) floor(val2); + cell1 = (int) ceil(val2); + + rest = val2 - cell0; + + y0 = LutTable[cell0] ; + y1 = LutTable[cell1] ; + + y = y0 + (y1 - y0) * rest; + + + + PostScript code Stack + ================================================ + + { % v + + [array] % v tab + dup % v tab tab + length 1 sub % v tab dom + + 3 -1 roll % tab dom v + + mul % tab val2 + dup % tab val2 val2 + dup % tab val2 val2 val2 + floor cvi % tab val2 val2 cell0 + exch % tab val2 cell0 val2 + ceiling cvi % tab val2 cell0 cell1 + + 3 index % tab val2 cell0 cell1 tab + exch % tab val2 cell0 tab cell1 + get % tab val2 cell0 y1 + + 4 -1 roll % val2 cell0 y1 tab + 3 -1 roll % val2 y1 tab cell0 + get % val2 y1 y0 + + dup % val2 y1 y0 y0 + 3 1 roll % val2 y0 y1 y0 + + sub % val2 y0 (y1-y0) + 3 -1 roll % y0 (y1-y0) val2 + dup % y0 (y1-y0) val2 val2 + floor cvi % y0 (y1-y0) val2 floor(val2) + sub % y0 (y1-y0) rest + mul % y0 t1 + add % y + 65535 div % result + + } bind + + +*/ + + +// This struct holds the memory block currently being write +typedef struct { + _cmsStageCLutData* Pipeline; + cmsIOHANDLER* m; + + int FirstComponent; + int SecondComponent; + + const char* PreMaj; + const char* PostMaj; + const char* PreMin; + const char* PostMin; + + int FixWhite; // Force mapping of pure white + + cmsColorSpaceSignature ColorSpace; // ColorSpace of profile + + +} cmsPsSamplerCargo; + +static int _cmsPSActualColumn = 0; + + +// Convert to byte +static +cmsUInt8Number Word2Byte(cmsUInt16Number w) +{ + return (cmsUInt8Number) floor((cmsFloat64Number) w / 257.0 + 0.5); +} + + +// Convert to byte (using ICC2 notation) +/* +static +cmsUInt8Number L2Byte(cmsUInt16Number w) +{ + int ww = w + 0x0080; + + if (ww > 0xFFFF) return 0xFF; + + return (cmsUInt8Number) ((cmsUInt16Number) (ww >> 8) & 0xFF); +} +*/ + +// Write a cooked byte + +static +void WriteByte(cmsIOHANDLER* m, cmsUInt8Number b) +{ + _cmsIOPrintf(m, "%02x", b); + _cmsPSActualColumn += 2; + + if (_cmsPSActualColumn > MAXPSCOLS) { + + _cmsIOPrintf(m, "\n"); + _cmsPSActualColumn = 0; + } +} + +// ----------------------------------------------------------------- PostScript generation + + +// Removes offending Carriage returns +static +char* RemoveCR(const char* txt) +{ + static char Buffer[2048]; + char* pt; + + strncpy(Buffer, txt, 2047); + Buffer[2047] = 0; + for (pt = Buffer; *pt; pt++) + if (*pt == '\n' || *pt == '\r') *pt = ' '; + + return Buffer; + +} + +static +void EmitHeader(cmsIOHANDLER* m, const char* Title, cmsHPROFILE hProfile) +{ + time_t timer; + cmsMLU *Description, *Copyright; + char DescASCII[256], CopyrightASCII[256]; + + time(&timer); + + Description = (cmsMLU*) cmsReadTag(hProfile, cmsSigProfileDescriptionTag); + Copyright = (cmsMLU*) cmsReadTag(hProfile, cmsSigCopyrightTag); + + DescASCII[0] = DescASCII[255] = 0; + CopyrightASCII[0] = CopyrightASCII[255] = 0; + + if (Description != NULL) cmsMLUgetASCII(Description, cmsNoLanguage, cmsNoCountry, DescASCII, 255); + if (Copyright != NULL) cmsMLUgetASCII(Copyright, cmsNoLanguage, cmsNoCountry, CopyrightASCII, 255); + + _cmsIOPrintf(m, "%%!PS-Adobe-3.0\n"); + _cmsIOPrintf(m, "%%\n"); + _cmsIOPrintf(m, "%% %s\n", Title); + _cmsIOPrintf(m, "%% Source: %s\n", RemoveCR(DescASCII)); + _cmsIOPrintf(m, "%% %s\n", RemoveCR(CopyrightASCII)); + _cmsIOPrintf(m, "%% Created: %s", ctime(&timer)); // ctime appends a \n!!! + _cmsIOPrintf(m, "%%\n"); + _cmsIOPrintf(m, "%%%%BeginResource\n"); + +} + + +// Emits White & Black point. White point is always D50, Black point is the device +// Black point adapted to D50. + +static +void EmitWhiteBlackD50(cmsIOHANDLER* m, cmsCIEXYZ* BlackPoint) +{ + + _cmsIOPrintf(m, "/BlackPoint [%f %f %f]\n", BlackPoint -> X, + BlackPoint -> Y, + BlackPoint -> Z); + + _cmsIOPrintf(m, "/WhitePoint [%f %f %f]\n", cmsD50_XYZ()->X, + cmsD50_XYZ()->Y, + cmsD50_XYZ()->Z); +} + + +static +void EmitRangeCheck(cmsIOHANDLER* m) +{ + _cmsIOPrintf(m, "dup 0.0 lt { pop 0.0 } if " + "dup 1.0 gt { pop 1.0 } if "); + +} + +// Does write the intent + +static +void EmitIntent(cmsIOHANDLER* m, int RenderingIntent) +{ + const char *intent; + + switch (RenderingIntent) { + + case INTENT_PERCEPTUAL: intent = "Perceptual"; break; + case INTENT_RELATIVE_COLORIMETRIC: intent = "RelativeColorimetric"; break; + case INTENT_ABSOLUTE_COLORIMETRIC: intent = "AbsoluteColorimetric"; break; + case INTENT_SATURATION: intent = "Saturation"; break; + + default: intent = "Undefined"; break; + } + + _cmsIOPrintf(m, "/RenderingIntent (%s)\n", intent ); +} + +// +// Convert L* to Y +// +// Y = Yn*[ (L* + 16) / 116] ^ 3 if (L*) >= 6 / 29 +// = Yn*( L* / 116) / 7.787 if (L*) < 6 / 29 +// + +/* +static +void EmitL2Y(cmsIOHANDLER* m) +{ + _cmsIOPrintf(m, + "{ " + "100 mul 16 add 116 div " // (L * 100 + 16) / 116 + "dup 6 29 div ge " // >= 6 / 29 ? + "{ dup dup mul mul } " // yes, ^3 and done + "{ 4 29 div sub 108 841 div mul } " // no, slope limiting + "ifelse } bind "); +} +*/ + + +// Lab -> XYZ, see the discussion above + +static +void EmitLab2XYZ(cmsIOHANDLER* m) +{ + _cmsIOPrintf(m, "/RangeABC [ 0 1 0 1 0 1]\n"); + _cmsIOPrintf(m, "/DecodeABC [\n"); + _cmsIOPrintf(m, "{100 mul 16 add 116 div } bind\n"); + _cmsIOPrintf(m, "{255 mul 128 sub 500 div } bind\n"); + _cmsIOPrintf(m, "{255 mul 128 sub 200 div } bind\n"); + _cmsIOPrintf(m, "]\n"); + _cmsIOPrintf(m, "/MatrixABC [ 1 1 1 1 0 0 0 0 -1]\n"); + _cmsIOPrintf(m, "/RangeLMN [ -0.236 1.254 0 1 -0.635 1.640 ]\n"); + _cmsIOPrintf(m, "/DecodeLMN [\n"); + _cmsIOPrintf(m, "{dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse 0.964200 mul} bind\n"); + _cmsIOPrintf(m, "{dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse } bind\n"); + _cmsIOPrintf(m, "{dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse 0.824900 mul} bind\n"); + _cmsIOPrintf(m, "]\n"); +} + + + +// Outputs a table of words. It does use 16 bits + +static +void Emit1Gamma(cmsIOHANDLER* m, cmsToneCurve* Table) +{ + cmsUInt32Number i; + cmsFloat64Number gamma; + + if (Table == NULL) return; // Error + + if (Table ->nEntries <= 0) return; // Empty table + + // Suppress whole if identity + if (cmsIsToneCurveLinear(Table)) return; + + // Check if is really an exponential. If so, emit "exp" + gamma = cmsEstimateGamma(Table, 0.001); + if (gamma > 0) { + _cmsIOPrintf(m, "{ %g exp } bind ", gamma); + return; + } + + _cmsIOPrintf(m, "{ "); + + // Bounds check + EmitRangeCheck(m); + + // Emit intepolation code + + // PostScript code Stack + // =============== ======================== + // v + _cmsIOPrintf(m, " ["); + + for (i=0; i < Table->nEntries; i++) { + _cmsIOPrintf(m, "%d ", Table->Table16[i]); + } + + _cmsIOPrintf(m, "] "); // v tab + + _cmsIOPrintf(m, "dup "); // v tab tab + _cmsIOPrintf(m, "length 1 sub "); // v tab dom + _cmsIOPrintf(m, "3 -1 roll "); // tab dom v + _cmsIOPrintf(m, "mul "); // tab val2 + _cmsIOPrintf(m, "dup "); // tab val2 val2 + _cmsIOPrintf(m, "dup "); // tab val2 val2 val2 + _cmsIOPrintf(m, "floor cvi "); // tab val2 val2 cell0 + _cmsIOPrintf(m, "exch "); // tab val2 cell0 val2 + _cmsIOPrintf(m, "ceiling cvi "); // tab val2 cell0 cell1 + _cmsIOPrintf(m, "3 index "); // tab val2 cell0 cell1 tab + _cmsIOPrintf(m, "exch "); // tab val2 cell0 tab cell1 + _cmsIOPrintf(m, "get "); // tab val2 cell0 y1 + _cmsIOPrintf(m, "4 -1 roll "); // val2 cell0 y1 tab + _cmsIOPrintf(m, "3 -1 roll "); // val2 y1 tab cell0 + _cmsIOPrintf(m, "get "); // val2 y1 y0 + _cmsIOPrintf(m, "dup "); // val2 y1 y0 y0 + _cmsIOPrintf(m, "3 1 roll "); // val2 y0 y1 y0 + _cmsIOPrintf(m, "sub "); // val2 y0 (y1-y0) + _cmsIOPrintf(m, "3 -1 roll "); // y0 (y1-y0) val2 + _cmsIOPrintf(m, "dup "); // y0 (y1-y0) val2 val2 + _cmsIOPrintf(m, "floor cvi "); // y0 (y1-y0) val2 floor(val2) + _cmsIOPrintf(m, "sub "); // y0 (y1-y0) rest + _cmsIOPrintf(m, "mul "); // y0 t1 + _cmsIOPrintf(m, "add "); // y + _cmsIOPrintf(m, "65535 div "); // result + + _cmsIOPrintf(m, " } bind "); +} + + +// Compare gamma table + +static +cmsBool GammaTableEquals(cmsUInt16Number* g1, cmsUInt16Number* g2, int nEntries) +{ + return memcmp(g1, g2, nEntries* sizeof(cmsUInt16Number)) == 0; +} + + +// Does write a set of gamma curves + +static +void EmitNGamma(cmsIOHANDLER* m, int n, cmsToneCurve* g[]) +{ + int i; + + for( i=0; i < n; i++ ) + { + if (g[i] == NULL) return; // Error + + if (i > 0 && GammaTableEquals(g[i-1]->Table16, g[i]->Table16, g[i]->nEntries)) { + + _cmsIOPrintf(m, "dup "); + } + else { + Emit1Gamma(m, g[i]); + } + } + +} + + + + + +// Following code dumps a LUT onto memory stream + + +// This is the sampler. Intended to work in SAMPLER_INSPECT mode, +// that is, the callback will be called for each knot with +// +// In[] The grid location coordinates, normalized to 0..ffff +// Out[] The Pipeline values, normalized to 0..ffff +// +// Returning a value other than 0 does terminate the sampling process +// +// Each row contains Pipeline values for all but first component. So, I +// detect row changing by keeping a copy of last value of first +// component. -1 is used to mark begining of whole block. + +static +int OutputValueSampler(register const cmsUInt16Number In[], register cmsUInt16Number Out[], register void* Cargo) +{ + cmsPsSamplerCargo* sc = (cmsPsSamplerCargo*) Cargo; + cmsUInt32Number i; + + + if (sc -> FixWhite) { + + if (In[0] == 0xFFFF) { // Only in L* = 100, ab = [-8..8] + + if ((In[1] >= 0x7800 && In[1] <= 0x8800) && + (In[2] >= 0x7800 && In[2] <= 0x8800)) { + + cmsUInt16Number* Black; + cmsUInt16Number* White; + cmsUInt32Number nOutputs; + + if (!_cmsEndPointsBySpace(sc ->ColorSpace, &White, &Black, &nOutputs)) + return 0; + + for (i=0; i < nOutputs; i++) + Out[i] = White[i]; + } + + + } + } + + + // Hadle the parenthesis on rows + + if (In[0] != sc ->FirstComponent) { + + if (sc ->FirstComponent != -1) { + + _cmsIOPrintf(sc ->m, sc ->PostMin); + sc ->SecondComponent = -1; + _cmsIOPrintf(sc ->m, sc ->PostMaj); + } + + // Begin block + _cmsPSActualColumn = 0; + + _cmsIOPrintf(sc ->m, sc ->PreMaj); + sc ->FirstComponent = In[0]; + } + + + if (In[1] != sc ->SecondComponent) { + + if (sc ->SecondComponent != -1) { + + _cmsIOPrintf(sc ->m, sc ->PostMin); + } + + _cmsIOPrintf(sc ->m, sc ->PreMin); + sc ->SecondComponent = In[1]; + } + + // Dump table. + + for (i=0; i < sc -> Pipeline ->Params->nOutputs; i++) { + + cmsUInt16Number wWordOut = Out[i]; + cmsUInt8Number wByteOut; // Value as byte + + + // We always deal with Lab4 + + wByteOut = Word2Byte(wWordOut); + WriteByte(sc -> m, wByteOut); + } + + return 1; +} + +// Writes a Pipeline on memstream. Could be 8 or 16 bits based + +static +void WriteCLUT(cmsIOHANDLER* m, cmsStage* mpe, const char* PreMaj, + const char* PostMaj, + const char* PreMin, + const char* PostMin, + int FixWhite, + cmsColorSpaceSignature ColorSpace) +{ + cmsUInt32Number i; + cmsPsSamplerCargo sc; + + sc.FirstComponent = -1; + sc.SecondComponent = -1; + sc.Pipeline = (_cmsStageCLutData *) mpe ->Data; + sc.m = m; + sc.PreMaj = PreMaj; + sc.PostMaj= PostMaj; + + sc.PreMin = PreMin; + sc.PostMin = PostMin; + sc.FixWhite = FixWhite; + sc.ColorSpace = ColorSpace; + + _cmsIOPrintf(m, "["); + + for (i=0; i < sc.Pipeline->Params->nInputs; i++) + _cmsIOPrintf(m, " %d ", sc.Pipeline->Params->nSamples[i]); + + _cmsIOPrintf(m, " [\n"); + + cmsStageSampleCLut16bit(mpe, OutputValueSampler, (void*) &sc, SAMPLER_INSPECT); + + _cmsIOPrintf(m, PostMin); + _cmsIOPrintf(m, PostMaj); + _cmsIOPrintf(m, "] "); + +} + + +// Dumps CIEBasedA Color Space Array + +static +int EmitCIEBasedA(cmsIOHANDLER* m, cmsToneCurve* Curve, cmsCIEXYZ* BlackPoint) +{ + + _cmsIOPrintf(m, "[ /CIEBasedA\n"); + _cmsIOPrintf(m, " <<\n"); + + _cmsIOPrintf(m, "/DecodeA "); + + Emit1Gamma(m, Curve); + + _cmsIOPrintf(m, " \n"); + + _cmsIOPrintf(m, "/MatrixA [ 0.9642 1.0000 0.8249 ]\n"); + _cmsIOPrintf(m, "/RangeLMN [ 0.0 0.9642 0.0 1.0000 0.0 0.8249 ]\n"); + + EmitWhiteBlackD50(m, BlackPoint); + EmitIntent(m, INTENT_PERCEPTUAL); + + _cmsIOPrintf(m, ">>\n"); + _cmsIOPrintf(m, "]\n"); + + return 1; +} + + +// Dumps CIEBasedABC Color Space Array + +static +int EmitCIEBasedABC(cmsIOHANDLER* m, cmsFloat64Number* Matrix, cmsToneCurve** CurveSet, cmsCIEXYZ* BlackPoint) +{ + int i; + + _cmsIOPrintf(m, "[ /CIEBasedABC\n"); + _cmsIOPrintf(m, "<<\n"); + _cmsIOPrintf(m, "/DecodeABC [ "); + + EmitNGamma(m, 3, CurveSet); + + _cmsIOPrintf(m, "]\n"); + + _cmsIOPrintf(m, "/MatrixABC [ " ); + + for( i=0; i < 3; i++ ) { + + _cmsIOPrintf(m, "%.6f %.6f %.6f ", Matrix[i + 3*0], + Matrix[i + 3*1], + Matrix[i + 3*2]); + } + + + _cmsIOPrintf(m, "]\n"); + + _cmsIOPrintf(m, "/RangeLMN [ 0.0 0.9642 0.0 1.0000 0.0 0.8249 ]\n"); + + EmitWhiteBlackD50(m, BlackPoint); + EmitIntent(m, INTENT_PERCEPTUAL); + + _cmsIOPrintf(m, ">>\n"); + _cmsIOPrintf(m, "]\n"); + + + return 1; +} + + +static +int EmitCIEBasedDEF(cmsIOHANDLER* m, cmsPipeline* Pipeline, int Intent, cmsCIEXYZ* BlackPoint) +{ + const char* PreMaj; + const char* PostMaj; + const char* PreMin, *PostMin; + cmsStage* mpe; + + mpe = Pipeline ->Elements; + + switch (cmsStageInputChannels(mpe)) { + case 3: + + _cmsIOPrintf(m, "[ /CIEBasedDEF\n"); + PreMaj ="<"; + PostMaj= ">\n"; + PreMin = PostMin = ""; + break; + case 4: + _cmsIOPrintf(m, "[ /CIEBasedDEFG\n"); + PreMaj = "["; + PostMaj = "]\n"; + PreMin = "<"; + PostMin = ">\n"; + break; + default: + return 0; + + } + + _cmsIOPrintf(m, "<<\n"); + + if (cmsStageType(mpe) == cmsSigCurveSetElemType) { + + _cmsIOPrintf(m, "/DecodeDEF [ "); + EmitNGamma(m, cmsStageOutputChannels(mpe), _cmsStageGetPtrToCurveSet(mpe)); + _cmsIOPrintf(m, "]\n"); + + mpe = mpe ->Next; + } + + if (cmsStageType(mpe) == cmsSigCLutElemType) { + + _cmsIOPrintf(m, "/Table "); + WriteCLUT(m, mpe, PreMaj, PostMaj, PreMin, PostMin, FALSE, (cmsColorSpaceSignature) 0); + _cmsIOPrintf(m, "]\n"); + } + + EmitLab2XYZ(m); + EmitWhiteBlackD50(m, BlackPoint); + EmitIntent(m, Intent); + + _cmsIOPrintf(m, " >>\n"); + _cmsIOPrintf(m, "]\n"); + + return 1; +} + +// Generates a curve from a gray profile + +static + cmsToneCurve* ExtractGray2Y(cmsContext ContextID, cmsHPROFILE hProfile, int Intent) +{ + cmsToneCurve* Out = cmsBuildTabulatedToneCurve16(ContextID, 256, NULL); + cmsHPROFILE hXYZ = cmsCreateXYZProfile(); + cmsHTRANSFORM xform = cmsCreateTransformTHR(ContextID, hProfile, TYPE_GRAY_8, hXYZ, TYPE_XYZ_DBL, Intent, cmsFLAGS_NOOPTIMIZE); + int i; + + if (Out != NULL) { + for (i=0; i < 256; i++) { + + cmsUInt8Number Gray = (cmsUInt8Number) i; + cmsCIEXYZ XYZ; + + cmsDoTransform(xform, &Gray, &XYZ, 1); + + Out ->Table16[i] =_cmsQuickSaturateWord(XYZ.Y * 65535.0); + } + } + + cmsDeleteTransform(xform); + cmsCloseProfile(hXYZ); + return Out; +} + + + +// Because PostScript has only 8 bits in /Table, we should use +// a more perceptually uniform space... I do choose Lab. + +static +int WriteInputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, int Intent, cmsUInt32Number dwFlags) +{ + cmsHPROFILE hLab; + cmsHTRANSFORM xform; + cmsUInt32Number nChannels; + cmsUInt32Number InputFormat; + int rc; + cmsHPROFILE Profiles[2]; + cmsCIEXYZ BlackPointAdaptedToD50; + + // Does create a device-link based transform. + // The DeviceLink is next dumped as working CSA. + + InputFormat = cmsFormatterForColorspaceOfProfile(hProfile, 2, FALSE); + nChannels = T_CHANNELS(InputFormat); + + + cmsDetectBlackPoint(&BlackPointAdaptedToD50, hProfile, Intent, 0); + + // Adjust output to Lab4 + hLab = cmsCreateLab4ProfileTHR(m ->ContextID, NULL); + + Profiles[0] = hProfile; + Profiles[1] = hLab; + + xform = cmsCreateMultiprofileTransform(Profiles, 2, InputFormat, TYPE_Lab_DBL, Intent, 0); + cmsCloseProfile(hLab); + + if (xform == NULL) { + + cmsSignalError(m ->ContextID, cmsERROR_COLORSPACE_CHECK, "Cannot create transform Profile -> Lab"); + return 0; + } + + // Only 1, 3 and 4 channels are allowed + + switch (nChannels) { + + case 1: { + cmsToneCurve* Gray2Y = ExtractGray2Y(m ->ContextID, hProfile, Intent); + EmitCIEBasedA(m, Gray2Y, &BlackPointAdaptedToD50); + cmsFreeToneCurve(Gray2Y); + } + break; + + case 3: + case 4: { + cmsUInt32Number OutFrm = TYPE_Lab_16; + cmsPipeline* DeviceLink; + _cmsTRANSFORM* v = (_cmsTRANSFORM*) xform; + + DeviceLink = cmsPipelineDup(v ->Lut); + if (DeviceLink == NULL) return 0; + + dwFlags |= cmsFLAGS_FORCE_CLUT; + _cmsOptimizePipeline(&DeviceLink, Intent, &InputFormat, &OutFrm, &dwFlags); + + rc = EmitCIEBasedDEF(m, DeviceLink, Intent, &BlackPointAdaptedToD50); + cmsPipelineFree(DeviceLink); + if (rc == 0) return 0; + } + break; + + default: + + cmsSignalError(m ->ContextID, cmsERROR_COLORSPACE_CHECK, "Only 3, 4 channels supported for CSA. This profile has %d channels.", nChannels); + return 0; + } + + + cmsDeleteTransform(xform); + + return 1; +} + +static +cmsFloat64Number* GetPtrToMatrix(const cmsStage* mpe) +{ + _cmsStageMatrixData* Data = (_cmsStageMatrixData*) mpe ->Data; + + return Data -> Double; +} + + +// Does create CSA based on matrix-shaper. Allowed types are gray and RGB based + +static +int WriteInputMatrixShaper(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsStage* Matrix, cmsStage* Shaper) +{ + cmsColorSpaceSignature ColorSpace; + int rc; + cmsCIEXYZ BlackPointAdaptedToD50; + + ColorSpace = cmsGetColorSpace(hProfile); + + cmsDetectBlackPoint(&BlackPointAdaptedToD50, hProfile, INTENT_RELATIVE_COLORIMETRIC, 0); + + if (ColorSpace == cmsSigGrayData) { + + cmsToneCurve** ShaperCurve = _cmsStageGetPtrToCurveSet(Shaper); + rc = EmitCIEBasedA(m, ShaperCurve[0], &BlackPointAdaptedToD50); + + } + else + if (ColorSpace == cmsSigRgbData) { + + cmsMAT3 Mat; + int i, j; + + memmove(&Mat, GetPtrToMatrix(Matrix), sizeof(Mat)); + + for (i=0; i < 3; i++) + for (j=0; j < 3; j++) + Mat.v[i].n[j] *= MAX_ENCODEABLE_XYZ; + + rc = EmitCIEBasedABC(m, (cmsFloat64Number *) &Mat, + _cmsStageGetPtrToCurveSet(Shaper), + &BlackPointAdaptedToD50); + } + else { + + cmsSignalError(m ->ContextID, cmsERROR_COLORSPACE_CHECK, "Profile is not suitable for CSA. Unsupported colorspace."); + return 0; + } + + return rc; +} + + + +// Creates a PostScript color list from a named profile data. +// This is a HP extension, and it works in Lab instead of XYZ + +static +int WriteNamedColorCSA(cmsIOHANDLER* m, cmsHPROFILE hNamedColor, int Intent) +{ + cmsHTRANSFORM xform; + cmsHPROFILE hLab; + int i, nColors; + char ColorName[32]; + cmsNAMEDCOLORLIST* NamedColorList; + + hLab = cmsCreateLab4ProfileTHR(m ->ContextID, NULL); + xform = cmsCreateTransform(hNamedColor, TYPE_NAMED_COLOR_INDEX, hLab, TYPE_Lab_DBL, Intent, 0); + if (xform == NULL) return 0; + + NamedColorList = cmsGetNamedColorList(xform); + if (NamedColorList == NULL) return 0; + + _cmsIOPrintf(m, "<<\n"); + _cmsIOPrintf(m, "(colorlistcomment) (%s)\n", "Named color CSA"); + _cmsIOPrintf(m, "(Prefix) [ (Pantone ) (PANTONE ) ]\n"); + _cmsIOPrintf(m, "(Suffix) [ ( CV) ( CVC) ( C) ]\n"); + + nColors = cmsNamedColorCount(NamedColorList); + + + for (i=0; i < nColors; i++) { + + cmsUInt16Number In[1]; + cmsCIELab Lab; + + In[0] = (cmsUInt16Number) i; + + if (!cmsNamedColorInfo(NamedColorList, i, ColorName, NULL, NULL, NULL, NULL)) + continue; + + cmsDoTransform(xform, In, &Lab, 1); + _cmsIOPrintf(m, " (%s) [ %.3f %.3f %.3f ]\n", ColorName, Lab.L, Lab.a, Lab.b); + } + + + + _cmsIOPrintf(m, ">>\n"); + + cmsDeleteTransform(xform); + cmsCloseProfile(hLab); + return 1; +} + + +// Does create a Color Space Array on XYZ colorspace for PostScript usage +static +cmsUInt32Number GenerateCSA(cmsContext ContextID, + cmsHPROFILE hProfile, + cmsUInt32Number Intent, + cmsUInt32Number dwFlags, + cmsIOHANDLER* mem) +{ + cmsUInt32Number dwBytesUsed; + cmsPipeline* lut = NULL; + cmsStage* Matrix, *Shaper; + + + // Is a named color profile? + if (cmsGetDeviceClass(hProfile) == cmsSigNamedColorClass) { + + if (!WriteNamedColorCSA(mem, hProfile, Intent)) goto Error; + } + else { + + + // Any profile class are allowed (including devicelink), but + // output (PCS) colorspace must be XYZ or Lab + cmsColorSpaceSignature ColorSpace = cmsGetPCS(hProfile); + + if (ColorSpace != cmsSigXYZData && + ColorSpace != cmsSigLabData) { + + cmsSignalError(ContextID, cmsERROR_COLORSPACE_CHECK, "Invalid output color space"); + goto Error; + } + + + // Read the lut with all necessary conversion stages + lut = _cmsReadInputLUT(hProfile, Intent); + if (lut == NULL) goto Error; + + + // Tone curves + matrix can be implemented without any LUT + if (cmsPipelineCheckAndRetreiveStages(lut, 2, cmsSigCurveSetElemType, cmsSigMatrixElemType, &Shaper, &Matrix)) { + + if (!WriteInputMatrixShaper(mem, hProfile, Matrix, Shaper)) goto Error; + + } + else { + // We need a LUT for the rest + if (!WriteInputLUT(mem, hProfile, Intent, dwFlags)) goto Error; + } + } + + + // Done, keep memory usage + dwBytesUsed = mem ->UsedSpace; + + // Get rid of LUT + if (lut != NULL) cmsPipelineFree(lut); + + // Finally, return used byte count + return dwBytesUsed; + +Error: + if (lut != NULL) cmsPipelineFree(lut); + return 0; +} + +// ------------------------------------------------------ Color Rendering Dictionary (CRD) + + + +/* + + Black point compensation plus chromatic adaptation: + + Step 1 - Chromatic adaptation + ============================= + + WPout + X = ------- PQR + Wpin + + Step 2 - Black point compensation + ================================= + + (WPout - BPout)*X - WPout*(BPin - BPout) + out = --------------------------------------- + WPout - BPin + + + Algorithm discussion + ==================== + + TransformPQR(WPin, BPin, WPout, BPout, PQR) + + Wpin,etc= { Xws Yws Zws Pws Qws Rws } + + + Algorithm Stack 0...n + =========================================================== + PQR BPout WPout BPin WPin + 4 index 3 get WPin PQR BPout WPout BPin WPin + div (PQR/WPin) BPout WPout BPin WPin + 2 index 3 get WPout (PQR/WPin) BPout WPout BPin WPin + mult WPout*(PQR/WPin) BPout WPout BPin WPin + + 2 index 3 get WPout WPout*(PQR/WPin) BPout WPout BPin WPin + 2 index 3 get BPout WPout WPout*(PQR/WPin) BPout WPout BPin WPin + sub (WPout-BPout) WPout*(PQR/WPin) BPout WPout BPin WPin + mult (WPout-BPout)* WPout*(PQR/WPin) BPout WPout BPin WPin + + 2 index 3 get WPout (BPout-WPout)* WPout*(PQR/WPin) BPout WPout BPin WPin + 4 index 3 get BPin WPout (BPout-WPout)* WPout*(PQR/WPin) BPout WPout BPin WPin + 3 index 3 get BPout BPin WPout (BPout-WPout)* WPout*(PQR/WPin) BPout WPout BPin WPin + + sub (BPin-BPout) WPout (BPout-WPout)* WPout*(PQR/WPin) BPout WPout BPin WPin + mult (BPin-BPout)*WPout (BPout-WPout)* WPout*(PQR/WPin) BPout WPout BPin WPin + sub (BPout-WPout)* WPout*(PQR/WPin)-(BPin-BPout)*WPout BPout WPout BPin WPin + + 3 index 3 get BPin (BPout-WPout)* WPout*(PQR/WPin)-(BPin-BPout)*WPout BPout WPout BPin WPin + 3 index 3 get WPout BPin (BPout-WPout)* WPout*(PQR/WPin)-(BPin-BPout)*WPout BPout WPout BPin WPin + exch + sub (WPout-BPin) (BPout-WPout)* WPout*(PQR/WPin)-(BPin-BPout)*WPout BPout WPout BPin WPin + div + + exch pop + exch pop + exch pop + exch pop + +*/ + + +static +void EmitPQRStage(cmsIOHANDLER* m, cmsHPROFILE hProfile, int DoBPC, int lIsAbsolute) +{ + + + if (lIsAbsolute) { + + // For absolute colorimetric intent, encode back to relative + // and generate a relative Pipeline + + // Relative encoding is obtained across XYZpcs*(D50/WhitePoint) + + cmsCIEXYZ White; + + _cmsReadMediaWhitePoint(&White, hProfile); + + _cmsIOPrintf(m,"/MatrixPQR [1 0 0 0 1 0 0 0 1 ]\n"); + _cmsIOPrintf(m,"/RangePQR [ -0.5 2 -0.5 2 -0.5 2 ]\n"); + + _cmsIOPrintf(m, "%% Absolute colorimetric -- encode to relative to maximize LUT usage\n" + "/TransformPQR [\n" + "{0.9642 mul %g div exch pop exch pop exch pop exch pop} bind\n" + "{1.0000 mul %g div exch pop exch pop exch pop exch pop} bind\n" + "{0.8249 mul %g div exch pop exch pop exch pop exch pop} bind\n]\n", + White.X, White.Y, White.Z); + return; + } + + + _cmsIOPrintf(m,"%% Bradford Cone Space\n" + "/MatrixPQR [0.8951 -0.7502 0.0389 0.2664 1.7135 -0.0685 -0.1614 0.0367 1.0296 ] \n"); + + _cmsIOPrintf(m, "/RangePQR [ -0.5 2 -0.5 2 -0.5 2 ]\n"); + + + // No BPC + + if (!DoBPC) { + + _cmsIOPrintf(m, "%% VonKries-like transform in Bradford Cone Space\n" + "/TransformPQR [\n" + "{exch pop exch 3 get mul exch pop exch 3 get div} bind\n" + "{exch pop exch 4 get mul exch pop exch 4 get div} bind\n" + "{exch pop exch 5 get mul exch pop exch 5 get div} bind\n]\n"); + } else { + + // BPC + + _cmsIOPrintf(m, "%% VonKries-like transform in Bradford Cone Space plus BPC\n" + "/TransformPQR [\n"); + + _cmsIOPrintf(m, "{4 index 3 get div 2 index 3 get mul " + "2 index 3 get 2 index 3 get sub mul " + "2 index 3 get 4 index 3 get 3 index 3 get sub mul sub " + "3 index 3 get 3 index 3 get exch sub div " + "exch pop exch pop exch pop exch pop } bind\n"); + + _cmsIOPrintf(m, "{4 index 4 get div 2 index 4 get mul " + "2 index 4 get 2 index 4 get sub mul " + "2 index 4 get 4 index 4 get 3 index 4 get sub mul sub " + "3 index 4 get 3 index 4 get exch sub div " + "exch pop exch pop exch pop exch pop } bind\n"); + + _cmsIOPrintf(m, "{4 index 5 get div 2 index 5 get mul " + "2 index 5 get 2 index 5 get sub mul " + "2 index 5 get 4 index 5 get 3 index 5 get sub mul sub " + "3 index 5 get 3 index 5 get exch sub div " + "exch pop exch pop exch pop exch pop } bind\n]\n"); + + } + + +} + + +static +void EmitXYZ2Lab(cmsIOHANDLER* m) +{ + _cmsIOPrintf(m, "/RangeLMN [ -0.635 2.0 0 2 -0.635 2.0 ]\n"); + _cmsIOPrintf(m, "/EncodeLMN [\n"); + _cmsIOPrintf(m, "{ 0.964200 div dup 0.008856 le {7.787 mul 16 116 div add}{1 3 div exp} ifelse } bind\n"); + _cmsIOPrintf(m, "{ 1.000000 div dup 0.008856 le {7.787 mul 16 116 div add}{1 3 div exp} ifelse } bind\n"); + _cmsIOPrintf(m, "{ 0.824900 div dup 0.008856 le {7.787 mul 16 116 div add}{1 3 div exp} ifelse } bind\n"); + _cmsIOPrintf(m, "]\n"); + _cmsIOPrintf(m, "/MatrixABC [ 0 1 0 1 -1 1 0 0 -1 ]\n"); + _cmsIOPrintf(m, "/EncodeABC [\n"); + + + _cmsIOPrintf(m, "{ 116 mul 16 sub 100 div } bind\n"); + _cmsIOPrintf(m, "{ 500 mul 128 add 256 div } bind\n"); + _cmsIOPrintf(m, "{ 200 mul 128 add 256 div } bind\n"); + + + _cmsIOPrintf(m, "]\n"); + + +} + +// Due to impedance mismatch between XYZ and almost all RGB and CMYK spaces +// I choose to dump LUTS in Lab instead of XYZ. There is still a lot of wasted +// space on 3D CLUT, but since space seems not to be a problem here, 33 points +// would give a reasonable accurancy. Note also that CRD tables must operate in +// 8 bits. + +static +int WriteOutputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, int Intent, cmsUInt32Number dwFlags) +{ + cmsHPROFILE hLab; + cmsHTRANSFORM xform; + int i, nChannels; + cmsUInt32Number OutputFormat; + _cmsTRANSFORM* v; + cmsPipeline* DeviceLink; + cmsHPROFILE Profiles[3]; + cmsCIEXYZ BlackPointAdaptedToD50; + cmsBool lDoBPC = (dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION); + cmsBool lFixWhite = !(dwFlags & cmsFLAGS_NOWHITEONWHITEFIXUP); + cmsUInt32Number InFrm = TYPE_Lab_16; + int RelativeEncodingIntent; + cmsColorSpaceSignature ColorSpace; + + + hLab = cmsCreateLab4ProfileTHR(m ->ContextID, NULL); + if (hLab == NULL) return 0; + + OutputFormat = cmsFormatterForColorspaceOfProfile(hProfile, 2, FALSE); + nChannels = T_CHANNELS(OutputFormat); + + ColorSpace = cmsGetColorSpace(hProfile); + + // For absolute colorimetric, the LUT is encoded as relative in order to preserve precision. + + RelativeEncodingIntent = Intent; + if (RelativeEncodingIntent == INTENT_ABSOLUTE_COLORIMETRIC) + RelativeEncodingIntent = INTENT_RELATIVE_COLORIMETRIC; + + + // Use V4 Lab always + Profiles[0] = hLab; + Profiles[1] = hProfile; + + xform = cmsCreateMultiprofileTransformTHR(m ->ContextID, + Profiles, 2, TYPE_Lab_DBL, + OutputFormat, RelativeEncodingIntent, 0); + cmsCloseProfile(hLab); + + if (xform == NULL) { + + cmsSignalError(m ->ContextID, cmsERROR_COLORSPACE_CHECK, "Cannot create transform Lab -> Profile in CRD creation"); + return 0; + } + + // Get a copy of the internal devicelink + v = (_cmsTRANSFORM*) xform; + DeviceLink = cmsPipelineDup(v ->Lut); + if (DeviceLink == NULL) return 0; + + + // We need a CLUT + dwFlags |= cmsFLAGS_FORCE_CLUT; + _cmsOptimizePipeline(&DeviceLink, RelativeEncodingIntent, &InFrm, &OutputFormat, &dwFlags); + + _cmsIOPrintf(m, "<<\n"); + _cmsIOPrintf(m, "/ColorRenderingType 1\n"); + + + cmsDetectBlackPoint(&BlackPointAdaptedToD50, hProfile, Intent, 0); + + // Emit headers, etc. + EmitWhiteBlackD50(m, &BlackPointAdaptedToD50); + EmitPQRStage(m, hProfile, lDoBPC, Intent == INTENT_ABSOLUTE_COLORIMETRIC); + EmitXYZ2Lab(m); + + + // FIXUP: map Lab (100, 0, 0) to perfect white, because the particular encoding for Lab + // does map a=b=0 not falling into any specific node. Since range a,b goes -128..127, + // zero is slightly moved towards right, so assure next node (in L=100 slice) is mapped to + // zero. This would sacrifice a bit of highlights, but failure to do so would cause + // scum dot. Ouch. + + if (Intent == INTENT_ABSOLUTE_COLORIMETRIC) + lFixWhite = FALSE; + + _cmsIOPrintf(m, "/RenderTable "); + + + WriteCLUT(m, cmsPipelineGetPtrToFirstStage(DeviceLink), "<", ">\n", "", "", lFixWhite, ColorSpace); + + _cmsIOPrintf(m, " %d {} bind ", nChannels); + + for (i=1; i < nChannels; i++) + _cmsIOPrintf(m, "dup "); + + _cmsIOPrintf(m, "]\n"); + + + EmitIntent(m, Intent); + + _cmsIOPrintf(m, ">>\n"); + + if (!(dwFlags & cmsFLAGS_NODEFAULTRESOURCEDEF)) { + + _cmsIOPrintf(m, "/Current exch /ColorRendering defineresource pop\n"); + } + + cmsPipelineFree(DeviceLink); + cmsDeleteTransform(xform); + + return 1; +} + + +// Builds a ASCII string containing colorant list in 0..1.0 range +static +void BuildColorantList(char *Colorant, int nColorant, cmsUInt16Number Out[]) +{ + char Buff[32]; + int j; + + Colorant[0] = 0; + if (nColorant > cmsMAXCHANNELS) + nColorant = cmsMAXCHANNELS; + + for (j=0; j < nColorant; j++) { + + sprintf(Buff, "%.3f", Out[j] / 65535.0); + strcat(Colorant, Buff); + if (j < nColorant -1) + strcat(Colorant, " "); + + } +} + + +// Creates a PostScript color list from a named profile data. +// This is a HP extension. + +static +int WriteNamedColorCRD(cmsIOHANDLER* m, cmsHPROFILE hNamedColor, int Intent, cmsUInt32Number dwFlags) +{ + cmsHTRANSFORM xform; + int i, nColors, nColorant; + cmsUInt32Number OutputFormat; + char ColorName[32]; + char Colorant[128]; + cmsNAMEDCOLORLIST* NamedColorList; + + + OutputFormat = cmsFormatterForColorspaceOfProfile(hNamedColor, 2, FALSE); + nColorant = T_CHANNELS(OutputFormat); + + + xform = cmsCreateTransform(hNamedColor, TYPE_NAMED_COLOR_INDEX, NULL, OutputFormat, Intent, dwFlags); + if (xform == NULL) return 0; + + + NamedColorList = cmsGetNamedColorList(xform); + if (NamedColorList == NULL) return 0; + + _cmsIOPrintf(m, "<<\n"); + _cmsIOPrintf(m, "(colorlistcomment) (%s) \n", "Named profile"); + _cmsIOPrintf(m, "(Prefix) [ (Pantone ) (PANTONE ) ]\n"); + _cmsIOPrintf(m, "(Suffix) [ ( CV) ( CVC) ( C) ]\n"); + + nColors = cmsNamedColorCount(NamedColorList); + + for (i=0; i < nColors; i++) { + + cmsUInt16Number In[1]; + cmsUInt16Number Out[cmsMAXCHANNELS]; + + In[0] = (cmsUInt16Number) i; + + if (!cmsNamedColorInfo(NamedColorList, i, ColorName, NULL, NULL, NULL, NULL)) + continue; + + cmsDoTransform(xform, In, Out, 1); + BuildColorantList(Colorant, nColorant, Out); + _cmsIOPrintf(m, " (%s) [ %s ]\n", ColorName, Colorant); + } + + _cmsIOPrintf(m, " >>"); + + if (!(dwFlags & cmsFLAGS_NODEFAULTRESOURCEDEF)) { + + _cmsIOPrintf(m, " /Current exch /HPSpotTable defineresource pop\n"); + } + + cmsDeleteTransform(xform); + return 1; +} + + + +// This one does create a Color Rendering Dictionary. +// CRD are always LUT-Based, no matter if profile is +// implemented as matrix-shaper. + +static +cmsUInt32Number GenerateCRD(cmsContext ContextID, + cmsHPROFILE hProfile, + cmsUInt32Number Intent, cmsUInt32Number dwFlags, + cmsIOHANDLER* mem) +{ + cmsUInt32Number dwBytesUsed; + + if (!(dwFlags & cmsFLAGS_NODEFAULTRESOURCEDEF)) { + + EmitHeader(mem, "Color Rendering Dictionary (CRD)", hProfile); + } + + + // Is a named color profile? + if (cmsGetDeviceClass(hProfile) == cmsSigNamedColorClass) { + + if (!WriteNamedColorCRD(mem, hProfile, Intent, dwFlags)) { + return 0; + } + } + else { + + // CRD are always implemented as LUT + + if (!WriteOutputLUT(mem, hProfile, Intent, dwFlags)) { + return 0; + } + } + + if (!(dwFlags & cmsFLAGS_NODEFAULTRESOURCEDEF)) { + + _cmsIOPrintf(mem, "%%%%EndResource\n"); + _cmsIOPrintf(mem, "\n%% CRD End\n"); + } + + // Done, keep memory usage + dwBytesUsed = mem ->UsedSpace; + + // Finally, return used byte count + return dwBytesUsed; + + cmsUNUSED_PARAMETER(ContextID); +} + + + + +cmsUInt32Number CMSEXPORT cmsGetPostScriptColorResource(cmsContext ContextID, + cmsPSResourceType Type, + cmsHPROFILE hProfile, + cmsUInt32Number Intent, + cmsUInt32Number dwFlags, + cmsIOHANDLER* io) +{ + cmsUInt32Number rc; + + + switch (Type) { + + case cmsPS_RESOURCE_CSA: + rc = GenerateCSA(ContextID, hProfile, Intent, dwFlags, io); + break; + + default: + case cmsPS_RESOURCE_CRD: + rc = GenerateCRD(ContextID, hProfile, Intent, dwFlags, io); + break; + } + + return rc; +} + + + +cmsUInt32Number CMSEXPORT cmsGetPostScriptCRD(cmsContext ContextID, + cmsHPROFILE hProfile, + cmsUInt32Number Intent, cmsUInt32Number dwFlags, + void* Buffer, cmsUInt32Number dwBufferLen) +{ + cmsIOHANDLER* mem; + cmsUInt32Number dwBytesUsed; + + // Set up the serialization engine + if (Buffer == NULL) + mem = cmsOpenIOhandlerFromNULL(ContextID); + else + mem = cmsOpenIOhandlerFromMem(ContextID, Buffer, dwBufferLen, "w"); + + if (!mem) return 0; + + dwBytesUsed = cmsGetPostScriptColorResource(ContextID, cmsPS_RESOURCE_CRD, hProfile, Intent, dwFlags, mem); + + // Get rid of memory stream + cmsCloseIOhandler(mem); + + return dwBytesUsed; +} + + + +// Does create a Color Space Array on XYZ colorspace for PostScript usage +cmsUInt32Number CMSEXPORT cmsGetPostScriptCSA(cmsContext ContextID, + cmsHPROFILE hProfile, + cmsUInt32Number Intent, + cmsUInt32Number dwFlags, + void* Buffer, + cmsUInt32Number dwBufferLen) +{ + cmsIOHANDLER* mem; + cmsUInt32Number dwBytesUsed; + + if (Buffer == NULL) + mem = cmsOpenIOhandlerFromNULL(ContextID); + else + mem = cmsOpenIOhandlerFromMem(ContextID, Buffer, dwBufferLen, "w"); + + if (!mem) return 0; + + dwBytesUsed = cmsGetPostScriptColorResource(ContextID, cmsPS_RESOURCE_CSA, hProfile, Intent, dwFlags, mem); + + // Get rid of memory stream + cmsCloseIOhandler(mem); + + return dwBytesUsed; + +} diff --git a/jni/lcms2-2.5/src/cmssamp.c b/jni/lcms2-2.5/src/cmssamp.c new file mode 100644 index 00000000..70e46916 --- /dev/null +++ b/jni/lcms2-2.5/src/cmssamp.c @@ -0,0 +1,572 @@ +//--------------------------------------------------------------------------------- +// +// Little Color Management System +// Copyright (c) 1998-2010 Marti Maria Saguer +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//--------------------------------------------------------------------------------- +// + +#include "lcms2_internal.h" + + +#define cmsmin(a, b) (((a) < (b)) ? (a) : (b)) +#define cmsmax(a, b) (((a) > (b)) ? (a) : (b)) + +// This file contains routines for resampling and LUT optimization, black point detection +// and black preservation. + +// Black point detection ------------------------------------------------------------------------- + + +// PCS -> PCS round trip transform, always uses relative intent on the device -> pcs +static +cmsHTRANSFORM CreateRoundtripXForm(cmsHPROFILE hProfile, cmsUInt32Number nIntent) +{ + cmsContext ContextID = cmsGetProfileContextID(hProfile); + cmsHPROFILE hLab = cmsCreateLab4ProfileTHR(ContextID, NULL); + cmsHTRANSFORM xform; + cmsBool BPC[4] = { FALSE, FALSE, FALSE, FALSE }; + cmsFloat64Number States[4] = { 1.0, 1.0, 1.0, 1.0 }; + cmsHPROFILE hProfiles[4]; + cmsUInt32Number Intents[4]; + + hProfiles[0] = hLab; hProfiles[1] = hProfile; hProfiles[2] = hProfile; hProfiles[3] = hLab; + Intents[0] = INTENT_RELATIVE_COLORIMETRIC; Intents[1] = nIntent; Intents[2] = INTENT_RELATIVE_COLORIMETRIC; Intents[3] = INTENT_RELATIVE_COLORIMETRIC; + + xform = cmsCreateExtendedTransform(ContextID, 4, hProfiles, BPC, Intents, + States, NULL, 0, TYPE_Lab_DBL, TYPE_Lab_DBL, cmsFLAGS_NOCACHE|cmsFLAGS_NOOPTIMIZE); + + cmsCloseProfile(hLab); + return xform; +} + +// Use darker colorants to obtain black point. This works in the relative colorimetric intent and +// assumes more ink results in darker colors. No ink limit is assumed. +static +cmsBool BlackPointAsDarkerColorant(cmsHPROFILE hInput, + cmsUInt32Number Intent, + cmsCIEXYZ* BlackPoint, + cmsUInt32Number dwFlags) +{ + cmsUInt16Number *Black; + cmsHTRANSFORM xform; + cmsColorSpaceSignature Space; + cmsUInt32Number nChannels; + cmsUInt32Number dwFormat; + cmsHPROFILE hLab; + cmsCIELab Lab; + cmsCIEXYZ BlackXYZ; + cmsContext ContextID = cmsGetProfileContextID(hInput); + + // If the profile does not support input direction, assume Black point 0 + if (!cmsIsIntentSupported(hInput, Intent, LCMS_USED_AS_INPUT)) { + + BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0; + return FALSE; + } + + // Create a formatter which has n channels and floating point + dwFormat = cmsFormatterForColorspaceOfProfile(hInput, 2, FALSE); + + // Try to get black by using black colorant + Space = cmsGetColorSpace(hInput); + + // This function returns darker colorant in 16 bits for several spaces + if (!_cmsEndPointsBySpace(Space, NULL, &Black, &nChannels)) { + + BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0; + return FALSE; + } + + if (nChannels != T_CHANNELS(dwFormat)) { + BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0; + return FALSE; + } + + // Lab will be used as the output space, but lab2 will avoid recursion + hLab = cmsCreateLab2ProfileTHR(ContextID, NULL); + if (hLab == NULL) { + BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0; + return FALSE; + } + + // Create the transform + xform = cmsCreateTransformTHR(ContextID, hInput, dwFormat, + hLab, TYPE_Lab_DBL, Intent, cmsFLAGS_NOOPTIMIZE|cmsFLAGS_NOCACHE); + cmsCloseProfile(hLab); + + if (xform == NULL) { + + // Something went wrong. Get rid of open resources and return zero as black + BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0; + return FALSE; + } + + // Convert black to Lab + cmsDoTransform(xform, Black, &Lab, 1); + + // Force it to be neutral, clip to max. L* of 50 + Lab.a = Lab.b = 0; + if (Lab.L > 50) Lab.L = 50; + + // Free the resources + cmsDeleteTransform(xform); + + // Convert from Lab (which is now clipped) to XYZ. + cmsLab2XYZ(NULL, &BlackXYZ, &Lab); + + if (BlackPoint != NULL) + *BlackPoint = BlackXYZ; + + return TRUE; + + cmsUNUSED_PARAMETER(dwFlags); +} + +// Get a black point of output CMYK profile, discounting any ink-limiting embedded +// in the profile. For doing that, we use perceptual intent in input direction: +// Lab (0, 0, 0) -> [Perceptual] Profile -> CMYK -> [Rel. colorimetric] Profile -> Lab +static +cmsBool BlackPointUsingPerceptualBlack(cmsCIEXYZ* BlackPoint, cmsHPROFILE hProfile) +{ + cmsHTRANSFORM hRoundTrip; + cmsCIELab LabIn, LabOut; + cmsCIEXYZ BlackXYZ; + + // Is the intent supported by the profile? + if (!cmsIsIntentSupported(hProfile, INTENT_PERCEPTUAL, LCMS_USED_AS_INPUT)) { + + BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0; + return TRUE; + } + + hRoundTrip = CreateRoundtripXForm(hProfile, INTENT_PERCEPTUAL); + if (hRoundTrip == NULL) { + BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0; + return FALSE; + } + + LabIn.L = LabIn.a = LabIn.b = 0; + cmsDoTransform(hRoundTrip, &LabIn, &LabOut, 1); + + // Clip Lab to reasonable limits + if (LabOut.L > 50) LabOut.L = 50; + LabOut.a = LabOut.b = 0; + + cmsDeleteTransform(hRoundTrip); + + // Convert it to XYZ + cmsLab2XYZ(NULL, &BlackXYZ, &LabOut); + + if (BlackPoint != NULL) + *BlackPoint = BlackXYZ; + + return TRUE; +} + +// This function shouldn't exist at all -- there is such quantity of broken +// profiles on black point tag, that we must somehow fix chromaticity to +// avoid huge tint when doing Black point compensation. This function does +// just that. There is a special flag for using black point tag, but turned +// off by default because it is bogus on most profiles. The detection algorithm +// involves to turn BP to neutral and to use only L component. +cmsBool CMSEXPORT cmsDetectBlackPoint(cmsCIEXYZ* BlackPoint, cmsHPROFILE hProfile, cmsUInt32Number Intent, cmsUInt32Number dwFlags) +{ + cmsProfileClassSignature devClass; + + // Make sure the device class is adequate + devClass = cmsGetDeviceClass(hProfile); + if (devClass == cmsSigLinkClass || + devClass == cmsSigAbstractClass || + devClass == cmsSigNamedColorClass) { + BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0; + return FALSE; + } + + // Make sure intent is adequate + if (Intent != INTENT_PERCEPTUAL && + Intent != INTENT_RELATIVE_COLORIMETRIC && + Intent != INTENT_SATURATION) { + BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0; + return FALSE; + } + + // v4 + perceptual & saturation intents does have its own black point, and it is + // well specified enough to use it. Black point tag is deprecated in V4. + if ((cmsGetEncodedICCversion(hProfile) >= 0x4000000) && + (Intent == INTENT_PERCEPTUAL || Intent == INTENT_SATURATION)) { + + // Matrix shaper share MRC & perceptual intents + if (cmsIsMatrixShaper(hProfile)) + return BlackPointAsDarkerColorant(hProfile, INTENT_RELATIVE_COLORIMETRIC, BlackPoint, 0); + + // Get Perceptual black out of v4 profiles. That is fixed for perceptual & saturation intents + BlackPoint -> X = cmsPERCEPTUAL_BLACK_X; + BlackPoint -> Y = cmsPERCEPTUAL_BLACK_Y; + BlackPoint -> Z = cmsPERCEPTUAL_BLACK_Z; + + return TRUE; + } + + +#ifdef CMS_USE_PROFILE_BLACK_POINT_TAG + + // v2, v4 rel/abs colorimetric + if (cmsIsTag(hProfile, cmsSigMediaBlackPointTag) && + Intent == INTENT_RELATIVE_COLORIMETRIC) { + + cmsCIEXYZ *BlackPtr, BlackXYZ, UntrustedBlackPoint, TrustedBlackPoint, MediaWhite; + cmsCIELab Lab; + + // If black point is specified, then use it, + + BlackPtr = cmsReadTag(hProfile, cmsSigMediaBlackPointTag); + if (BlackPtr != NULL) { + + BlackXYZ = *BlackPtr; + _cmsReadMediaWhitePoint(&MediaWhite, hProfile); + + // Black point is absolute XYZ, so adapt to D50 to get PCS value + cmsAdaptToIlluminant(&UntrustedBlackPoint, &MediaWhite, cmsD50_XYZ(), &BlackXYZ); + + // Force a=b=0 to get rid of any chroma + cmsXYZ2Lab(NULL, &Lab, &UntrustedBlackPoint); + Lab.a = Lab.b = 0; + if (Lab.L > 50) Lab.L = 50; // Clip to L* <= 50 + cmsLab2XYZ(NULL, &TrustedBlackPoint, &Lab); + + if (BlackPoint != NULL) + *BlackPoint = TrustedBlackPoint; + + return TRUE; + } + } +#endif + + // That is about v2 profiles. + + // If output profile, discount ink-limiting and that's all + if (Intent == INTENT_RELATIVE_COLORIMETRIC && + (cmsGetDeviceClass(hProfile) == cmsSigOutputClass) && + (cmsGetColorSpace(hProfile) == cmsSigCmykData)) + return BlackPointUsingPerceptualBlack(BlackPoint, hProfile); + + // Nope, compute BP using current intent. + return BlackPointAsDarkerColorant(hProfile, Intent, BlackPoint, dwFlags); +} + + + +// --------------------------------------------------------------------------------------------------------- + +// Least Squares Fit of a Quadratic Curve to Data +// http://www.personal.psu.edu/jhm/f90/lectures/lsq2.html + +static +cmsFloat64Number RootOfLeastSquaresFitQuadraticCurve(int n, cmsFloat64Number x[], cmsFloat64Number y[]) +{ + double sum_x = 0, sum_x2 = 0, sum_x3 = 0, sum_x4 = 0; + double sum_y = 0, sum_yx = 0, sum_yx2 = 0; + double d, a, b, c; + int i; + cmsMAT3 m; + cmsVEC3 v, res; + + if (n < 4) return 0; + + for (i=0; i < n; i++) { + + double xn = x[i]; + double yn = y[i]; + + sum_x += xn; + sum_x2 += xn*xn; + sum_x3 += xn*xn*xn; + sum_x4 += xn*xn*xn*xn; + + sum_y += yn; + sum_yx += yn*xn; + sum_yx2 += yn*xn*xn; + } + + _cmsVEC3init(&m.v[0], n, sum_x, sum_x2); + _cmsVEC3init(&m.v[1], sum_x, sum_x2, sum_x3); + _cmsVEC3init(&m.v[2], sum_x2, sum_x3, sum_x4); + + _cmsVEC3init(&v, sum_y, sum_yx, sum_yx2); + + if (!_cmsMAT3solve(&res, &m, &v)) return 0; + + + a = res.n[2]; + b = res.n[1]; + c = res.n[0]; + + if (fabs(a) < 1.0E-10) { + + return cmsmin(0, cmsmax(50, -c/b )); + } + else { + + d = b*b - 4.0 * a * c; + if (d <= 0) { + return 0; + } + else { + + double rt = (-b + sqrt(d)) / (2.0 * a); + + return cmsmax(0, cmsmin(50, rt)); + } + } + +} + +/* +static +cmsBool IsMonotonic(int n, const cmsFloat64Number Table[]) +{ + int i; + cmsFloat64Number last; + + last = Table[n-1]; + + for (i = n-2; i >= 0; --i) { + + if (Table[i] > last) + + return FALSE; + else + last = Table[i]; + + } + + return TRUE; +} +*/ + +// Calculates the black point of a destination profile. +// This algorithm comes from the Adobe paper disclosing its black point compensation method. +cmsBool CMSEXPORT cmsDetectDestinationBlackPoint(cmsCIEXYZ* BlackPoint, cmsHPROFILE hProfile, cmsUInt32Number Intent, cmsUInt32Number dwFlags) +{ + cmsColorSpaceSignature ColorSpace; + cmsHTRANSFORM hRoundTrip = NULL; + cmsCIELab InitialLab, destLab, Lab; + cmsFloat64Number inRamp[256], outRamp[256]; + cmsFloat64Number MinL, MaxL; + cmsBool NearlyStraightMidrange = TRUE; + cmsFloat64Number yRamp[256]; + cmsFloat64Number x[256], y[256]; + cmsFloat64Number lo, hi; + int n, l; + cmsProfileClassSignature devClass; + + // Make sure the device class is adequate + devClass = cmsGetDeviceClass(hProfile); + if (devClass == cmsSigLinkClass || + devClass == cmsSigAbstractClass || + devClass == cmsSigNamedColorClass) { + BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0; + return FALSE; + } + + // Make sure intent is adequate + if (Intent != INTENT_PERCEPTUAL && + Intent != INTENT_RELATIVE_COLORIMETRIC && + Intent != INTENT_SATURATION) { + BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0; + return FALSE; + } + + + // v4 + perceptual & saturation intents does have its own black point, and it is + // well specified enough to use it. Black point tag is deprecated in V4. + if ((cmsGetEncodedICCversion(hProfile) >= 0x4000000) && + (Intent == INTENT_PERCEPTUAL || Intent == INTENT_SATURATION)) { + + // Matrix shaper share MRC & perceptual intents + if (cmsIsMatrixShaper(hProfile)) + return BlackPointAsDarkerColorant(hProfile, INTENT_RELATIVE_COLORIMETRIC, BlackPoint, 0); + + // Get Perceptual black out of v4 profiles. That is fixed for perceptual & saturation intents + BlackPoint -> X = cmsPERCEPTUAL_BLACK_X; + BlackPoint -> Y = cmsPERCEPTUAL_BLACK_Y; + BlackPoint -> Z = cmsPERCEPTUAL_BLACK_Z; + return TRUE; + } + + + // Check if the profile is lut based and gray, rgb or cmyk (7.2 in Adobe's document) + ColorSpace = cmsGetColorSpace(hProfile); + if (!cmsIsCLUT(hProfile, Intent, LCMS_USED_AS_OUTPUT ) || + (ColorSpace != cmsSigGrayData && + ColorSpace != cmsSigRgbData && + ColorSpace != cmsSigCmykData)) { + + // In this case, handle as input case + return cmsDetectBlackPoint(BlackPoint, hProfile, Intent, dwFlags); + } + + // It is one of the valid cases!, use Adobe algorithm + + + // Set a first guess, that should work on good profiles. + if (Intent == INTENT_RELATIVE_COLORIMETRIC) { + + cmsCIEXYZ IniXYZ; + + // calculate initial Lab as source black point + if (!cmsDetectBlackPoint(&IniXYZ, hProfile, Intent, dwFlags)) { + return FALSE; + } + + // convert the XYZ to lab + cmsXYZ2Lab(NULL, &InitialLab, &IniXYZ); + + } else { + + // set the initial Lab to zero, that should be the black point for perceptual and saturation + InitialLab.L = 0; + InitialLab.a = 0; + InitialLab.b = 0; + } + + + // Step 2 + // ====== + + // Create a roundtrip. Define a Transform BT for all x in L*a*b* + hRoundTrip = CreateRoundtripXForm(hProfile, Intent); + if (hRoundTrip == NULL) return FALSE; + + // Compute ramps + + for (l=0; l < 256; l++) { + + Lab.L = (cmsFloat64Number) (l * 100.0) / 255.0; + Lab.a = cmsmin(50, cmsmax(-50, InitialLab.a)); + Lab.b = cmsmin(50, cmsmax(-50, InitialLab.b)); + + cmsDoTransform(hRoundTrip, &Lab, &destLab, 1); + + inRamp[l] = Lab.L; + outRamp[l] = destLab.L; + } + + // Make monotonic + for (l = 254; l > 0; --l) { + outRamp[l] = cmsmin(outRamp[l], outRamp[l+1]); + } + + // Check + if (! (outRamp[0] < outRamp[255])) { + + cmsDeleteTransform(hRoundTrip); + BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0; + return FALSE; + } + + + // Test for mid range straight (only on relative colorimetric) + + NearlyStraightMidrange = TRUE; + MinL = outRamp[0]; MaxL = outRamp[255]; + if (Intent == INTENT_RELATIVE_COLORIMETRIC) { + + for (l=0; l < 256; l++) { + + if (! ((inRamp[l] <= MinL + 0.2 * (MaxL - MinL) ) || + (fabs(inRamp[l] - outRamp[l]) < 4.0 ))) + NearlyStraightMidrange = FALSE; + } + + // If the mid range is straight (as determined above) then the + // DestinationBlackPoint shall be the same as initialLab. + // Otherwise, the DestinationBlackPoint shall be determined + // using curve fitting. + + if (NearlyStraightMidrange) { + + cmsLab2XYZ(NULL, BlackPoint, &InitialLab); + cmsDeleteTransform(hRoundTrip); + return TRUE; + } + } + + + // curve fitting: The round-trip curve normally looks like a nearly constant section at the black point, + // with a corner and a nearly straight line to the white point. + + for (l=0; l < 256; l++) { + + yRamp[l] = (outRamp[l] - MinL) / (MaxL - MinL); + } + + // find the black point using the least squares error quadratic curve fitting + + if (Intent == INTENT_RELATIVE_COLORIMETRIC) { + lo = 0.1; + hi = 0.5; + } + else { + + // Perceptual and saturation + lo = 0.03; + hi = 0.25; + } + + // Capture shadow points for the fitting. + n = 0; + for (l=0; l < 256; l++) { + + cmsFloat64Number ff = yRamp[l]; + + if (ff >= lo && ff < hi) { + x[n] = inRamp[l]; + y[n] = yRamp[l]; + n++; + } + } + + + // No suitable points + if (n < 3 ) { + cmsDeleteTransform(hRoundTrip); + BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0; + return FALSE; + } + + + // fit and get the vertex of quadratic curve + Lab.L = RootOfLeastSquaresFitQuadraticCurve(n, x, y); + + if (Lab.L < 0.0) { // clip to zero L* if the vertex is negative + Lab.L = 0; + } + + Lab.a = InitialLab.a; + Lab.b = InitialLab.b; + + cmsLab2XYZ(NULL, BlackPoint, &Lab); + + cmsDeleteTransform(hRoundTrip); + return TRUE; +} diff --git a/jni/lcms2-2.5/src/cmssm.c b/jni/lcms2-2.5/src/cmssm.c new file mode 100644 index 00000000..e41cb68b --- /dev/null +++ b/jni/lcms2-2.5/src/cmssm.c @@ -0,0 +1,735 @@ +//--------------------------------------------------------------------------------- +// +// Little Color Management System +// Copyright (c) 1998-2011 Marti Maria Saguer +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//--------------------------------------------------------------------------------- +// + +#include "lcms2_internal.h" + + +// ------------------------------------------------------------------------ + +// Gamut boundary description by using Jan Morovic's Segment maxima method +// Many thanks to Jan for allowing me to use his algorithm. + +// r = C* +// alpha = Hab +// theta = L* + +#define SECTORS 16 // number of divisions in alpha and theta + +// Spherical coordinates +typedef struct { + + cmsFloat64Number r; + cmsFloat64Number alpha; + cmsFloat64Number theta; + +} cmsSpherical; + +typedef enum { + GP_EMPTY, + GP_SPECIFIED, + GP_MODELED + + } GDBPointType; + + +typedef struct { + + GDBPointType Type; + cmsSpherical p; // Keep also alpha & theta of maximum + +} cmsGDBPoint; + + +typedef struct { + + cmsContext ContextID; + cmsGDBPoint Gamut[SECTORS][SECTORS]; + +} cmsGDB; + + +// A line using the parametric form +// P = a + t*u +typedef struct { + + cmsVEC3 a; + cmsVEC3 u; + +} cmsLine; + + +// A plane using the parametric form +// Q = b + r*v + s*w +typedef struct { + + cmsVEC3 b; + cmsVEC3 v; + cmsVEC3 w; + +} cmsPlane; + + + +// -------------------------------------------------------------------------------------------- + +// ATAN2() which always returns degree positive numbers + +static +cmsFloat64Number _cmsAtan2(cmsFloat64Number y, cmsFloat64Number x) +{ + cmsFloat64Number a; + + // Deal with undefined case + if (x == 0.0 && y == 0.0) return 0; + + a = (atan2(y, x) * 180.0) / M_PI; + + while (a < 0) { + a += 360; + } + + return a; +} + +// Convert to spherical coordinates +static +void ToSpherical(cmsSpherical* sp, const cmsVEC3* v) +{ + + cmsFloat64Number L, a, b; + + L = v ->n[VX]; + a = v ->n[VY]; + b = v ->n[VZ]; + + sp ->r = sqrt( L*L + a*a + b*b ); + + if (sp ->r == 0) { + sp ->alpha = sp ->theta = 0; + return; + } + + sp ->alpha = _cmsAtan2(a, b); + sp ->theta = _cmsAtan2(sqrt(a*a + b*b), L); +} + + +// Convert to cartesian from spherical +static +void ToCartesian(cmsVEC3* v, const cmsSpherical* sp) +{ + cmsFloat64Number sin_alpha; + cmsFloat64Number cos_alpha; + cmsFloat64Number sin_theta; + cmsFloat64Number cos_theta; + cmsFloat64Number L, a, b; + + sin_alpha = sin((M_PI * sp ->alpha) / 180.0); + cos_alpha = cos((M_PI * sp ->alpha) / 180.0); + sin_theta = sin((M_PI * sp ->theta) / 180.0); + cos_theta = cos((M_PI * sp ->theta) / 180.0); + + a = sp ->r * sin_theta * sin_alpha; + b = sp ->r * sin_theta * cos_alpha; + L = sp ->r * cos_theta; + + v ->n[VX] = L; + v ->n[VY] = a; + v ->n[VZ] = b; +} + + +// Quantize sector of a spherical coordinate. Saturate 360, 180 to last sector +// The limits are the centers of each sector, so +static +void QuantizeToSector(const cmsSpherical* sp, int* alpha, int* theta) +{ + *alpha = (int) floor(((sp->alpha * (SECTORS)) / 360.0) ); + *theta = (int) floor(((sp->theta * (SECTORS)) / 180.0) ); + + if (*alpha >= SECTORS) + *alpha = SECTORS-1; + if (*theta >= SECTORS) + *theta = SECTORS-1; +} + + +// Line determined by 2 points +static +void LineOf2Points(cmsLine* line, cmsVEC3* a, cmsVEC3* b) +{ + + _cmsVEC3init(&line ->a, a ->n[VX], a ->n[VY], a ->n[VZ]); + _cmsVEC3init(&line ->u, b ->n[VX] - a ->n[VX], + b ->n[VY] - a ->n[VY], + b ->n[VZ] - a ->n[VZ]); +} + + +// Evaluate parametric line +static +void GetPointOfLine(cmsVEC3* p, const cmsLine* line, cmsFloat64Number t) +{ + p ->n[VX] = line ->a.n[VX] + t * line->u.n[VX]; + p ->n[VY] = line ->a.n[VY] + t * line->u.n[VY]; + p ->n[VZ] = line ->a.n[VZ] + t * line->u.n[VZ]; +} + + + +/* + Closest point in sector line1 to sector line2 (both are defined as 0 <=t <= 1) + http://softsurfer.com/Archive/algorithm_0106/algorithm_0106.htm + + Copyright 2001, softSurfer (www.softsurfer.com) + This code may be freely used and modified for any purpose + providing that this copyright notice is included with it. + SoftSurfer makes no warranty for this code, and cannot be held + liable for any real or imagined damage resulting from its use. + Users of this code must verify correctness for their application. + +*/ + +static +cmsBool ClosestLineToLine(cmsVEC3* r, const cmsLine* line1, const cmsLine* line2) +{ + cmsFloat64Number a, b, c, d, e, D; + cmsFloat64Number sc, sN, sD; + cmsFloat64Number tc, tN, tD; + cmsVEC3 w0; + + _cmsVEC3minus(&w0, &line1 ->a, &line2 ->a); + + a = _cmsVEC3dot(&line1 ->u, &line1 ->u); + b = _cmsVEC3dot(&line1 ->u, &line2 ->u); + c = _cmsVEC3dot(&line2 ->u, &line2 ->u); + d = _cmsVEC3dot(&line1 ->u, &w0); + e = _cmsVEC3dot(&line2 ->u, &w0); + + D = a*c - b * b; // Denominator + sD = tD = D; // default sD = D >= 0 + + if (D < MATRIX_DET_TOLERANCE) { // the lines are almost parallel + + sN = 0.0; // force using point P0 on segment S1 + sD = 1.0; // to prevent possible division by 0.0 later + tN = e; + tD = c; + } + else { // get the closest points on the infinite lines + + sN = (b*e - c*d); + tN = (a*e - b*d); + + if (sN < 0.0) { // sc < 0 => the s=0 edge is visible + + sN = 0.0; + tN = e; + tD = c; + } + else if (sN > sD) { // sc > 1 => the s=1 edge is visible + sN = sD; + tN = e + b; + tD = c; + } + } + + if (tN < 0.0) { // tc < 0 => the t=0 edge is visible + + tN = 0.0; + // recompute sc for this edge + if (-d < 0.0) + sN = 0.0; + else if (-d > a) + sN = sD; + else { + sN = -d; + sD = a; + } + } + else if (tN > tD) { // tc > 1 => the t=1 edge is visible + + tN = tD; + + // recompute sc for this edge + if ((-d + b) < 0.0) + sN = 0; + else if ((-d + b) > a) + sN = sD; + else { + sN = (-d + b); + sD = a; + } + } + // finally do the division to get sc and tc + sc = (fabs(sN) < MATRIX_DET_TOLERANCE ? 0.0 : sN / sD); + tc = (fabs(tN) < MATRIX_DET_TOLERANCE ? 0.0 : tN / tD); + + GetPointOfLine(r, line1, sc); + return TRUE; +} + + + +// ------------------------------------------------------------------ Wrapper + + +// Allocate & free structure +cmsHANDLE CMSEXPORT cmsGBDAlloc(cmsContext ContextID) +{ + cmsGDB* gbd = (cmsGDB*) _cmsMallocZero(ContextID, sizeof(cmsGDB)); + if (gbd == NULL) return NULL; + + gbd -> ContextID = ContextID; + + return (cmsHANDLE) gbd; +} + + +void CMSEXPORT cmsGBDFree(cmsHANDLE hGBD) +{ + cmsGDB* gbd = (cmsGDB*) hGBD; + if (hGBD != NULL) + _cmsFree(gbd->ContextID, (void*) gbd); +} + + +// Auxiliar to retrieve a pointer to the segmentr containing the Lab value +static +cmsGDBPoint* GetPoint(cmsGDB* gbd, const cmsCIELab* Lab, cmsSpherical* sp) +{ + cmsVEC3 v; + int alpha, theta; + + // Housekeeping + _cmsAssert(gbd != NULL); + _cmsAssert(Lab != NULL); + _cmsAssert(sp != NULL); + + // Center L* by substracting half of its domain, that's 50 + _cmsVEC3init(&v, Lab ->L - 50.0, Lab ->a, Lab ->b); + + // Convert to spherical coordinates + ToSpherical(sp, &v); + + if (sp ->r < 0 || sp ->alpha < 0 || sp->theta < 0) { + cmsSignalError(gbd ->ContextID, cmsERROR_RANGE, "spherical value out of range"); + return NULL; + } + + // On which sector it falls? + QuantizeToSector(sp, &alpha, &theta); + + if (alpha < 0 || theta < 0 || alpha >= SECTORS || theta >= SECTORS) { + cmsSignalError(gbd ->ContextID, cmsERROR_RANGE, " quadrant out of range"); + return NULL; + } + + // Get pointer to the sector + return &gbd ->Gamut[theta][alpha]; +} + +// Add a point to gamut descriptor. Point to add is in Lab color space. +// GBD is centered on a=b=0 and L*=50 +cmsBool CMSEXPORT cmsGDBAddPoint(cmsHANDLE hGBD, const cmsCIELab* Lab) +{ + cmsGDB* gbd = (cmsGDB*) hGBD; + cmsGDBPoint* ptr; + cmsSpherical sp; + + + // Get pointer to the sector + ptr = GetPoint(gbd, Lab, &sp); + if (ptr == NULL) return FALSE; + + // If no samples at this sector, add it + if (ptr ->Type == GP_EMPTY) { + + ptr -> Type = GP_SPECIFIED; + ptr -> p = sp; + } + else { + + + // Substitute only if radius is greater + if (sp.r > ptr -> p.r) { + + ptr -> Type = GP_SPECIFIED; + ptr -> p = sp; + } + } + + return TRUE; +} + +// Check if a given point falls inside gamut +cmsBool CMSEXPORT cmsGDBCheckPoint(cmsHANDLE hGBD, const cmsCIELab* Lab) +{ + cmsGDB* gbd = (cmsGDB*) hGBD; + cmsGDBPoint* ptr; + cmsSpherical sp; + + // Get pointer to the sector + ptr = GetPoint(gbd, Lab, &sp); + if (ptr == NULL) return FALSE; + + // If no samples at this sector, return no data + if (ptr ->Type == GP_EMPTY) return FALSE; + + // In gamut only if radius is greater + + return (sp.r <= ptr -> p.r); +} + +// ----------------------------------------------------------------------------------------------------------------------- + +// Find near sectors. The list of sectors found is returned on Close[]. +// The function returns the number of sectors as well. + +// 24 9 10 11 12 +// 23 8 1 2 13 +// 22 7 * 3 14 +// 21 6 5 4 15 +// 20 19 18 17 16 +// +// Those are the relative movements +// {-2,-2}, {-1, -2}, {0, -2}, {+1, -2}, {+2, -2}, +// {-2,-1}, {-1, -1}, {0, -1}, {+1, -1}, {+2, -1}, +// {-2, 0}, {-1, 0}, {0, 0}, {+1, 0}, {+2, 0}, +// {-2,+1}, {-1, +1}, {0, +1}, {+1, +1}, {+2, +1}, +// {-2,+2}, {-1, +2}, {0, +2}, {+1, +2}, {+2, +2}}; + + +static +const struct _spiral { + + int AdvX, AdvY; + + } Spiral[] = { {0, -1}, {+1, -1}, {+1, 0}, {+1, +1}, {0, +1}, {-1, +1}, + {-1, 0}, {-1, -1}, {-1, -2}, {0, -2}, {+1, -2}, {+2, -2}, + {+2, -1}, {+2, 0}, {+2, +1}, {+2, +2}, {+1, +2}, {0, +2}, + {-1, +2}, {-2, +2}, {-2, +1}, {-2, 0}, {-2, -1}, {-2, -2} }; + +#define NSTEPS (sizeof(Spiral) / sizeof(struct _spiral)) + +static +int FindNearSectors(cmsGDB* gbd, int alpha, int theta, cmsGDBPoint* Close[]) +{ + int nSectors = 0; + int a, t; + cmsUInt32Number i; + cmsGDBPoint* pt; + + for (i=0; i < NSTEPS; i++) { + + a = alpha + Spiral[i].AdvX; + t = theta + Spiral[i].AdvY; + + // Cycle at the end + a %= SECTORS; + t %= SECTORS; + + // Cycle at the begin + if (a < 0) a = SECTORS + a; + if (t < 0) t = SECTORS + t; + + pt = &gbd ->Gamut[t][a]; + + if (pt -> Type != GP_EMPTY) { + + Close[nSectors++] = pt; + } + } + + return nSectors; +} + + +// Interpolate a missing sector. Method identifies whatever this is top, bottom or mid +static +cmsBool InterpolateMissingSector(cmsGDB* gbd, int alpha, int theta) +{ + cmsSpherical sp; + cmsVEC3 Lab; + cmsVEC3 Centre; + cmsLine ray; + int nCloseSectors; + cmsGDBPoint* Close[NSTEPS + 1]; + cmsSpherical closel, templ; + cmsLine edge; + int k, m; + + // Is that point already specified? + if (gbd ->Gamut[theta][alpha].Type != GP_EMPTY) return TRUE; + + // Fill close points + nCloseSectors = FindNearSectors(gbd, alpha, theta, Close); + + + // Find a central point on the sector + sp.alpha = (cmsFloat64Number) ((alpha + 0.5) * 360.0) / (SECTORS); + sp.theta = (cmsFloat64Number) ((theta + 0.5) * 180.0) / (SECTORS); + sp.r = 50.0; + + // Convert to Cartesian + ToCartesian(&Lab, &sp); + + // Create a ray line from centre to this point + _cmsVEC3init(&Centre, 50.0, 0, 0); + LineOf2Points(&ray, &Lab, &Centre); + + // For all close sectors + closel.r = 0.0; + closel.alpha = 0; + closel.theta = 0; + + for (k=0; k < nCloseSectors; k++) { + + for(m = k+1; m < nCloseSectors; m++) { + + cmsVEC3 temp, a1, a2; + + // A line from sector to sector + ToCartesian(&a1, &Close[k]->p); + ToCartesian(&a2, &Close[m]->p); + + LineOf2Points(&edge, &a1, &a2); + + // Find a line + ClosestLineToLine(&temp, &ray, &edge); + + // Convert to spherical + ToSpherical(&templ, &temp); + + + if ( templ.r > closel.r && + templ.theta >= (theta*180.0/SECTORS) && + templ.theta <= ((theta+1)*180.0/SECTORS) && + templ.alpha >= (alpha*360.0/SECTORS) && + templ.alpha <= ((alpha+1)*360.0/SECTORS)) { + + closel = templ; + } + } + } + + gbd ->Gamut[theta][alpha].p = closel; + gbd ->Gamut[theta][alpha].Type = GP_MODELED; + + return TRUE; + +} + + +// Interpolate missing parts. The algorithm fist computes slices at +// theta=0 and theta=Max. +cmsBool CMSEXPORT cmsGDBCompute(cmsHANDLE hGBD, cmsUInt32Number dwFlags) +{ + int alpha, theta; + cmsGDB* gbd = (cmsGDB*) hGBD; + + _cmsAssert(hGBD != NULL); + + // Interpolate black + for (alpha = 0; alpha < SECTORS; alpha++) { + + if (!InterpolateMissingSector(gbd, alpha, 0)) return FALSE; + } + + // Interpolate white + for (alpha = 0; alpha < SECTORS; alpha++) { + + if (!InterpolateMissingSector(gbd, alpha, SECTORS-1)) return FALSE; + } + + + // Interpolate Mid + for (theta = 1; theta < SECTORS; theta++) { + for (alpha = 0; alpha < SECTORS; alpha++) { + + if (!InterpolateMissingSector(gbd, alpha, theta)) return FALSE; + } + } + + // Done + return TRUE; + + cmsUNUSED_PARAMETER(dwFlags); +} + + + + +// -------------------------------------------------------------------------------------------------------- + +// Great for debug, but not suitable for real use + +#if 0 +cmsBool cmsGBDdumpVRML(cmsHANDLE hGBD, const char* fname) +{ + FILE* fp; + int i, j; + cmsGDB* gbd = (cmsGDB*) hGBD; + cmsGDBPoint* pt; + + fp = fopen (fname, "wt"); + if (fp == NULL) + return FALSE; + + fprintf (fp, "#VRML V2.0 utf8\n"); + + // set the viewing orientation and distance + fprintf (fp, "DEF CamTest Group {\n"); + fprintf (fp, "\tchildren [\n"); + fprintf (fp, "\t\tDEF Cameras Group {\n"); + fprintf (fp, "\t\t\tchildren [\n"); + fprintf (fp, "\t\t\t\tDEF DefaultView Viewpoint {\n"); + fprintf (fp, "\t\t\t\t\tposition 0 0 340\n"); + fprintf (fp, "\t\t\t\t\torientation 0 0 1 0\n"); + fprintf (fp, "\t\t\t\t\tdescription \"default view\"\n"); + fprintf (fp, "\t\t\t\t}\n"); + fprintf (fp, "\t\t\t]\n"); + fprintf (fp, "\t\t},\n"); + fprintf (fp, "\t]\n"); + fprintf (fp, "}\n"); + + // Output the background stuff + fprintf (fp, "Background {\n"); + fprintf (fp, "\tskyColor [\n"); + fprintf (fp, "\t\t.5 .5 .5\n"); + fprintf (fp, "\t]\n"); + fprintf (fp, "}\n"); + + // Output the shape stuff + fprintf (fp, "Transform {\n"); + fprintf (fp, "\tscale .3 .3 .3\n"); + fprintf (fp, "\tchildren [\n"); + + // Draw the axes as a shape: + fprintf (fp, "\t\tShape {\n"); + fprintf (fp, "\t\t\tappearance Appearance {\n"); + fprintf (fp, "\t\t\t\tmaterial Material {\n"); + fprintf (fp, "\t\t\t\t\tdiffuseColor 0 0.8 0\n"); + fprintf (fp, "\t\t\t\t\temissiveColor 1.0 1.0 1.0\n"); + fprintf (fp, "\t\t\t\t\tshininess 0.8\n"); + fprintf (fp, "\t\t\t\t}\n"); + fprintf (fp, "\t\t\t}\n"); + fprintf (fp, "\t\t\tgeometry IndexedLineSet {\n"); + fprintf (fp, "\t\t\t\tcoord Coordinate {\n"); + fprintf (fp, "\t\t\t\t\tpoint [\n"); + fprintf (fp, "\t\t\t\t\t0.0 0.0 0.0,\n"); + fprintf (fp, "\t\t\t\t\t%f 0.0 0.0,\n", 255.0); + fprintf (fp, "\t\t\t\t\t0.0 %f 0.0,\n", 255.0); + fprintf (fp, "\t\t\t\t\t0.0 0.0 %f]\n", 255.0); + fprintf (fp, "\t\t\t\t}\n"); + fprintf (fp, "\t\t\t\tcoordIndex [\n"); + fprintf (fp, "\t\t\t\t\t0, 1, -1\n"); + fprintf (fp, "\t\t\t\t\t0, 2, -1\n"); + fprintf (fp, "\t\t\t\t\t0, 3, -1]\n"); + fprintf (fp, "\t\t\t}\n"); + fprintf (fp, "\t\t}\n"); + + + fprintf (fp, "\t\tShape {\n"); + fprintf (fp, "\t\t\tappearance Appearance {\n"); + fprintf (fp, "\t\t\t\tmaterial Material {\n"); + fprintf (fp, "\t\t\t\t\tdiffuseColor 0 0.8 0\n"); + fprintf (fp, "\t\t\t\t\temissiveColor 1 1 1\n"); + fprintf (fp, "\t\t\t\t\tshininess 0.8\n"); + fprintf (fp, "\t\t\t\t}\n"); + fprintf (fp, "\t\t\t}\n"); + fprintf (fp, "\t\t\tgeometry PointSet {\n"); + + // fill in the points here + fprintf (fp, "\t\t\t\tcoord Coordinate {\n"); + fprintf (fp, "\t\t\t\t\tpoint [\n"); + + // We need to transverse all gamut hull. + for (i=0; i < SECTORS; i++) + for (j=0; j < SECTORS; j++) { + + cmsVEC3 v; + + pt = &gbd ->Gamut[i][j]; + ToCartesian(&v, &pt ->p); + + fprintf (fp, "\t\t\t\t\t%g %g %g", v.n[0]+50, v.n[1], v.n[2]); + + if ((j == SECTORS - 1) && (i == SECTORS - 1)) + fprintf (fp, "]\n"); + else + fprintf (fp, ",\n"); + + } + + fprintf (fp, "\t\t\t\t}\n"); + + + + // fill in the face colors + fprintf (fp, "\t\t\t\tcolor Color {\n"); + fprintf (fp, "\t\t\t\t\tcolor [\n"); + + for (i=0; i < SECTORS; i++) + for (j=0; j < SECTORS; j++) { + + cmsVEC3 v; + + pt = &gbd ->Gamut[i][j]; + + + ToCartesian(&v, &pt ->p); + + + if (pt ->Type == GP_EMPTY) + fprintf (fp, "\t\t\t\t\t%g %g %g", 0.0, 0.0, 0.0); + else + if (pt ->Type == GP_MODELED) + fprintf (fp, "\t\t\t\t\t%g %g %g", 1.0, .5, .5); + else { + fprintf (fp, "\t\t\t\t\t%g %g %g", 1.0, 1.0, 1.0); + + } + + if ((j == SECTORS - 1) && (i == SECTORS - 1)) + fprintf (fp, "]\n"); + else + fprintf (fp, ",\n"); + } + fprintf (fp, "\t\t\t}\n"); + + + fprintf (fp, "\t\t\t}\n"); + fprintf (fp, "\t\t}\n"); + fprintf (fp, "\t]\n"); + fprintf (fp, "}\n"); + + fclose (fp); + + return TRUE; +} +#endif + diff --git a/jni/lcms2-2.5/src/cmstypes.c b/jni/lcms2-2.5/src/cmstypes.c new file mode 100644 index 00000000..019ad785 --- /dev/null +++ b/jni/lcms2-2.5/src/cmstypes.c @@ -0,0 +1,5440 @@ +//--------------------------------------------------------------------------------- +// +// Little Color Management System +// Copyright (c) 1998-2011 Marti Maria Saguer +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//--------------------------------------------------------------------------------- +// + +#include "lcms2_internal.h" + +// Tag Serialization ----------------------------------------------------------------------------- +// This file implements every single tag and tag type as described in the ICC spec. Some types +// have been deprecated, like ncl and Data. There is no implementation for those types as there +// are no profiles holding them. The programmer can also extend this list by defining his own types +// by using the appropiate plug-in. There are three types of plug ins regarding that. First type +// allows to define new tags using any existing type. Next plug-in type allows to define new types +// and the third one is very specific: allows to extend the number of elements in the multiprofile +// elements special type. +//-------------------------------------------------------------------------------------------------- + +// Some broken types +#define cmsCorbisBrokenXYZtype ((cmsTagTypeSignature) 0x17A505B8) +#define cmsMonacoBrokenCurveType ((cmsTagTypeSignature) 0x9478ee00) + +// This is the linked list that keeps track of the defined types +typedef struct _cmsTagTypeLinkedList_st { + + cmsTagTypeHandler Handler; + struct _cmsTagTypeLinkedList_st* Next; + +} _cmsTagTypeLinkedList; + +// Some macros to define callbacks. +#define READ_FN(x) Type_##x##_Read +#define WRITE_FN(x) Type_##x##_Write +#define FREE_FN(x) Type_##x##_Free +#define DUP_FN(x) Type_##x##_Dup + +// Helper macro to define a handler. Callbacks do have a fixed naming convention. +#define TYPE_HANDLER(t, x) { (t), READ_FN(x), WRITE_FN(x), DUP_FN(x), FREE_FN(x), NULL, 0 } + +// Helper macro to define a MPE handler. Callbacks do have a fixed naming convention +#define TYPE_MPE_HANDLER(t, x) { (t), READ_FN(x), WRITE_FN(x), GenericMPEdup, GenericMPEfree, NULL, 0 } + +// Register a new type handler. This routine is shared between normal types and MPE +static +cmsBool RegisterTypesPlugin(cmsContext id, cmsPluginBase* Data, _cmsTagTypeLinkedList* LinkedList, cmsUInt32Number DefaultListCount) +{ + cmsPluginTagType* Plugin = (cmsPluginTagType*) Data; + _cmsTagTypeLinkedList *pt, *Anterior = NULL; + + // Calling the function with NULL as plug-in would unregister the plug in. + if (Data == NULL) { + + LinkedList[DefaultListCount-1].Next = NULL; + return TRUE; + } + + pt = Anterior = LinkedList; + while (pt != NULL) { + + if (Plugin->Handler.Signature == pt -> Handler.Signature) { + pt ->Handler = Plugin ->Handler; // Replace old behaviour. + // Note that since no memory is allocated, unregister does not + // reset this action. + return TRUE; + } + + Anterior = pt; + pt = pt ->Next; + } + + // Registering happens in plug-in memory pool + pt = (_cmsTagTypeLinkedList*) _cmsPluginMalloc(id, sizeof(_cmsTagTypeLinkedList)); + if (pt == NULL) return FALSE; + + pt ->Handler = Plugin ->Handler; + pt ->Next = NULL; + + if (Anterior) + Anterior -> Next = pt; + + return TRUE; +} + +// Return handler for a given type or NULL if not found. Shared between normal types and MPE +static +cmsTagTypeHandler* GetHandler(cmsTagTypeSignature sig, _cmsTagTypeLinkedList* LinkedList) +{ + _cmsTagTypeLinkedList* pt; + + for (pt = LinkedList; + pt != NULL; + pt = pt ->Next) { + + if (sig == pt -> Handler.Signature) return &pt ->Handler; + } + + return NULL; +} + + +// Auxiliar to convert UTF-32 to UTF-16 in some cases +static +cmsBool _cmsWriteWCharArray(cmsIOHANDLER* io, cmsUInt32Number n, const wchar_t* Array) +{ + cmsUInt32Number i; + + _cmsAssert(io != NULL); + _cmsAssert(!(Array == NULL && n > 0)); + + for (i=0; i < n; i++) { + if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) Array[i])) return FALSE; + } + + return TRUE; +} + +static +cmsBool _cmsReadWCharArray(cmsIOHANDLER* io, cmsUInt32Number n, wchar_t* Array) +{ + cmsUInt32Number i; + cmsUInt16Number tmp; + + _cmsAssert(io != NULL); + + for (i=0; i < n; i++) { + + if (Array != NULL) { + + if (!_cmsReadUInt16Number(io, &tmp)) return FALSE; + Array[i] = (wchar_t) tmp; + } + else { + if (!_cmsReadUInt16Number(io, NULL)) return FALSE; + } + + } + return TRUE; +} + +// To deal with position tables +typedef cmsBool (* PositionTableEntryFn)(struct _cms_typehandler_struct* self, + cmsIOHANDLER* io, + void* Cargo, + cmsUInt32Number n, + cmsUInt32Number SizeOfTag); + +// Helper function to deal with position tables as decribed in ICC spec 4.3 +// A table of n elements is readed, where first comes n records containing offsets and sizes and +// then a block containing the data itself. This allows to reuse same data in more than one entry +static +cmsBool ReadPositionTable(struct _cms_typehandler_struct* self, + cmsIOHANDLER* io, + cmsUInt32Number Count, + cmsUInt32Number BaseOffset, + void *Cargo, + PositionTableEntryFn ElementFn) +{ + cmsUInt32Number i; + cmsUInt32Number *ElementOffsets = NULL, *ElementSizes = NULL; + + // Let's take the offsets to each element + ElementOffsets = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number)); + if (ElementOffsets == NULL) goto Error; + + ElementSizes = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number)); + if (ElementSizes == NULL) goto Error; + + for (i=0; i < Count; i++) { + + if (!_cmsReadUInt32Number(io, &ElementOffsets[i])) goto Error; + if (!_cmsReadUInt32Number(io, &ElementSizes[i])) goto Error; + + ElementOffsets[i] += BaseOffset; + } + + // Seek to each element and read it + for (i=0; i < Count; i++) { + + if (!io -> Seek(io, ElementOffsets[i])) goto Error; + + // This is the reader callback + if (!ElementFn(self, io, Cargo, i, ElementSizes[i])) goto Error; + } + + // Success + if (ElementOffsets != NULL) _cmsFree(io ->ContextID, ElementOffsets); + if (ElementSizes != NULL) _cmsFree(io ->ContextID, ElementSizes); + return TRUE; + +Error: + if (ElementOffsets != NULL) _cmsFree(io ->ContextID, ElementOffsets); + if (ElementSizes != NULL) _cmsFree(io ->ContextID, ElementSizes); + return FALSE; +} + +// Same as anterior, but for write position tables +static +cmsBool WritePositionTable(struct _cms_typehandler_struct* self, + cmsIOHANDLER* io, + cmsUInt32Number SizeOfTag, + cmsUInt32Number Count, + cmsUInt32Number BaseOffset, + void *Cargo, + PositionTableEntryFn ElementFn) +{ + cmsUInt32Number i; + cmsUInt32Number DirectoryPos, CurrentPos, Before; + cmsUInt32Number *ElementOffsets = NULL, *ElementSizes = NULL; + + // Create table + ElementOffsets = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number)); + if (ElementOffsets == NULL) goto Error; + + ElementSizes = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number)); + if (ElementSizes == NULL) goto Error; + + // Keep starting position of curve offsets + DirectoryPos = io ->Tell(io); + + // Write a fake directory to be filled latter on + for (i=0; i < Count; i++) { + + if (!_cmsWriteUInt32Number(io, 0)) goto Error; // Offset + if (!_cmsWriteUInt32Number(io, 0)) goto Error; // size + } + + // Write each element. Keep track of the size as well. + for (i=0; i < Count; i++) { + + Before = io ->Tell(io); + ElementOffsets[i] = Before - BaseOffset; + + // Callback to write... + if (!ElementFn(self, io, Cargo, i, SizeOfTag)) goto Error; + + // Now the size + ElementSizes[i] = io ->Tell(io) - Before; + } + + // Write the directory + CurrentPos = io ->Tell(io); + if (!io ->Seek(io, DirectoryPos)) goto Error; + + for (i=0; i < Count; i++) { + if (!_cmsWriteUInt32Number(io, ElementOffsets[i])) goto Error; + if (!_cmsWriteUInt32Number(io, ElementSizes[i])) goto Error; + } + + if (!io ->Seek(io, CurrentPos)) goto Error; + + if (ElementOffsets != NULL) _cmsFree(io ->ContextID, ElementOffsets); + if (ElementSizes != NULL) _cmsFree(io ->ContextID, ElementSizes); + return TRUE; + +Error: + if (ElementOffsets != NULL) _cmsFree(io ->ContextID, ElementOffsets); + if (ElementSizes != NULL) _cmsFree(io ->ContextID, ElementSizes); + return FALSE; +} + + +// ******************************************************************************** +// Type XYZ. Only one value is allowed +// ******************************************************************************** + +//The XYZType contains an array of three encoded values for the XYZ tristimulus +//values. Tristimulus values must be non-negative. The signed encoding allows for +//implementation optimizations by minimizing the number of fixed formats. + + +static +void *Type_XYZ_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) +{ + cmsCIEXYZ* xyz; + + *nItems = 0; + xyz = (cmsCIEXYZ*) _cmsMallocZero(self ->ContextID, sizeof(cmsCIEXYZ)); + if (xyz == NULL) return NULL; + + if (!_cmsReadXYZNumber(io, xyz)) { + _cmsFree(self ->ContextID, xyz); + return NULL; + } + + *nItems = 1; + return (void*) xyz; + + cmsUNUSED_PARAMETER(SizeOfTag); +} + +static +cmsBool Type_XYZ_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) +{ + return _cmsWriteXYZNumber(io, (cmsCIEXYZ*) Ptr); + + cmsUNUSED_PARAMETER(nItems); + cmsUNUSED_PARAMETER(self); +} + +static +void* Type_XYZ_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) +{ + return _cmsDupMem(self ->ContextID, Ptr, sizeof(cmsCIEXYZ)); + + cmsUNUSED_PARAMETER(n); +} + +static +void Type_XYZ_Free(struct _cms_typehandler_struct* self, void *Ptr) +{ + _cmsFree(self ->ContextID, Ptr); +} + + +static +cmsTagTypeSignature DecideXYZtype(cmsFloat64Number ICCVersion, const void *Data) +{ + return cmsSigXYZType; + + cmsUNUSED_PARAMETER(ICCVersion); + cmsUNUSED_PARAMETER(Data); +} + + +// ******************************************************************************** +// Type chromaticity. Only one value is allowed +// ******************************************************************************** +// The chromaticity tag type provides basic chromaticity data and type of +// phosphors or colorants of a monitor to applications and utilities. + +static +void *Type_Chromaticity_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) +{ + cmsCIExyYTRIPLE* chrm; + cmsUInt16Number nChans, Table; + + *nItems = 0; + chrm = (cmsCIExyYTRIPLE*) _cmsMallocZero(self ->ContextID, sizeof(cmsCIExyYTRIPLE)); + if (chrm == NULL) return NULL; + + if (!_cmsReadUInt16Number(io, &nChans)) goto Error; + + // Let's recover from a bug introduced in early versions of lcms1 + if (nChans == 0 && SizeOfTag == 32) { + + if (!_cmsReadUInt16Number(io, NULL)) goto Error; + if (!_cmsReadUInt16Number(io, &nChans)) goto Error; + } + + if (nChans != 3) goto Error; + + if (!_cmsReadUInt16Number(io, &Table)) goto Error; + + if (!_cmsRead15Fixed16Number(io, &chrm ->Red.x)) goto Error; + if (!_cmsRead15Fixed16Number(io, &chrm ->Red.y)) goto Error; + + chrm ->Red.Y = 1.0; + + if (!_cmsRead15Fixed16Number(io, &chrm ->Green.x)) goto Error; + if (!_cmsRead15Fixed16Number(io, &chrm ->Green.y)) goto Error; + + chrm ->Green.Y = 1.0; + + if (!_cmsRead15Fixed16Number(io, &chrm ->Blue.x)) goto Error; + if (!_cmsRead15Fixed16Number(io, &chrm ->Blue.y)) goto Error; + + chrm ->Blue.Y = 1.0; + + *nItems = 1; + return (void*) chrm; + +Error: + _cmsFree(self ->ContextID, (void*) chrm); + return NULL; + + cmsUNUSED_PARAMETER(SizeOfTag); +} + +static +cmsBool SaveOneChromaticity(cmsFloat64Number x, cmsFloat64Number y, cmsIOHANDLER* io) +{ + if (!_cmsWriteUInt32Number(io, _cmsDoubleTo15Fixed16(x))) return FALSE; + if (!_cmsWriteUInt32Number(io, _cmsDoubleTo15Fixed16(y))) return FALSE; + + return TRUE; +} + +static +cmsBool Type_Chromaticity_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) +{ + cmsCIExyYTRIPLE* chrm = (cmsCIExyYTRIPLE*) Ptr; + + if (!_cmsWriteUInt16Number(io, 3)) return FALSE; // nChannels + if (!_cmsWriteUInt16Number(io, 0)) return FALSE; // Table + + if (!SaveOneChromaticity(chrm -> Red.x, chrm -> Red.y, io)) return FALSE; + if (!SaveOneChromaticity(chrm -> Green.x, chrm -> Green.y, io)) return FALSE; + if (!SaveOneChromaticity(chrm -> Blue.x, chrm -> Blue.y, io)) return FALSE; + + return TRUE; + + cmsUNUSED_PARAMETER(nItems); + cmsUNUSED_PARAMETER(self); +} + +static +void* Type_Chromaticity_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) +{ + return _cmsDupMem(self ->ContextID, Ptr, sizeof(cmsCIExyYTRIPLE)); + + cmsUNUSED_PARAMETER(n); +} + +static +void Type_Chromaticity_Free(struct _cms_typehandler_struct* self, void* Ptr) +{ + _cmsFree(self ->ContextID, Ptr); +} + + +// ******************************************************************************** +// Type cmsSigColorantOrderType +// ******************************************************************************** + +// This is an optional tag which specifies the laydown order in which colorants will +// be printed on an n-colorant device. The laydown order may be the same as the +// channel generation order listed in the colorantTableTag or the channel order of a +// colour space such as CMYK, in which case this tag is not needed. When this is not +// the case (for example, ink-towers sometimes use the order KCMY), this tag may be +// used to specify the laydown order of the colorants. + + +static +void *Type_ColorantOrderType_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) +{ + cmsUInt8Number* ColorantOrder; + cmsUInt32Number Count; + + *nItems = 0; + if (!_cmsReadUInt32Number(io, &Count)) return NULL; + if (Count > cmsMAXCHANNELS) return NULL; + + ColorantOrder = (cmsUInt8Number*) _cmsCalloc(self ->ContextID, cmsMAXCHANNELS, sizeof(cmsUInt8Number)); + if (ColorantOrder == NULL) return NULL; + + // We use FF as end marker + memset(ColorantOrder, 0xFF, cmsMAXCHANNELS * sizeof(cmsUInt8Number)); + + if (io ->Read(io, ColorantOrder, sizeof(cmsUInt8Number), Count) != Count) { + + _cmsFree(self ->ContextID, (void*) ColorantOrder); + return NULL; + } + + *nItems = 1; + return (void*) ColorantOrder; + + cmsUNUSED_PARAMETER(SizeOfTag); +} + +static +cmsBool Type_ColorantOrderType_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) +{ + cmsUInt8Number* ColorantOrder = (cmsUInt8Number*) Ptr; + cmsUInt32Number i, sz, Count; + + // Get the length + for (Count=i=0; i < cmsMAXCHANNELS; i++) { + if (ColorantOrder[i] != 0xFF) Count++; + } + + if (!_cmsWriteUInt32Number(io, Count)) return FALSE; + + sz = Count * sizeof(cmsUInt8Number); + if (!io -> Write(io, sz, ColorantOrder)) return FALSE; + + return TRUE; + + cmsUNUSED_PARAMETER(nItems); + cmsUNUSED_PARAMETER(self); +} + +static +void* Type_ColorantOrderType_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) +{ + return _cmsDupMem(self ->ContextID, Ptr, cmsMAXCHANNELS * sizeof(cmsUInt8Number)); + + cmsUNUSED_PARAMETER(n); +} + + +static +void Type_ColorantOrderType_Free(struct _cms_typehandler_struct* self, void* Ptr) +{ + _cmsFree(self ->ContextID, Ptr); +} + +// ******************************************************************************** +// Type cmsSigS15Fixed16ArrayType +// ******************************************************************************** +// This type represents an array of generic 4-byte/32-bit fixed point quantity. +// The number of values is determined from the size of the tag. + +static +void *Type_S15Fixed16_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) +{ + cmsFloat64Number* array_double; + cmsUInt32Number i, n; + + *nItems = 0; + n = SizeOfTag / sizeof(cmsUInt32Number); + array_double = (cmsFloat64Number*) _cmsCalloc(self ->ContextID, n, sizeof(cmsFloat64Number)); + if (array_double == NULL) return NULL; + + for (i=0; i < n; i++) { + + if (!_cmsRead15Fixed16Number(io, &array_double[i])) { + + _cmsFree(self ->ContextID, array_double); + return NULL; + } + } + + *nItems = n; + return (void*) array_double; +} + +static +cmsBool Type_S15Fixed16_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) +{ + cmsFloat64Number* Value = (cmsFloat64Number*) Ptr; + cmsUInt32Number i; + + for (i=0; i < nItems; i++) { + + if (!_cmsWrite15Fixed16Number(io, Value[i])) return FALSE; + } + + return TRUE; + + cmsUNUSED_PARAMETER(self); +} + +static +void* Type_S15Fixed16_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) +{ + return _cmsDupMem(self ->ContextID, Ptr, n * sizeof(cmsFloat64Number)); +} + + +static +void Type_S15Fixed16_Free(struct _cms_typehandler_struct* self, void* Ptr) +{ + _cmsFree(self ->ContextID, Ptr); +} + +// ******************************************************************************** +// Type cmsSigU16Fixed16ArrayType +// ******************************************************************************** +// This type represents an array of generic 4-byte/32-bit quantity. +// The number of values is determined from the size of the tag. + + +static +void *Type_U16Fixed16_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) +{ + cmsFloat64Number* array_double; + cmsUInt32Number v; + cmsUInt32Number i, n; + + *nItems = 0; + n = SizeOfTag / sizeof(cmsUInt32Number); + array_double = (cmsFloat64Number*) _cmsCalloc(self ->ContextID, n, sizeof(cmsFloat64Number)); + if (array_double == NULL) return NULL; + + for (i=0; i < n; i++) { + + if (!_cmsReadUInt32Number(io, &v)) { + _cmsFree(self ->ContextID, (void*) array_double); + return NULL; + } + + // Convert to cmsFloat64Number + array_double[i] = (cmsFloat64Number) (v / 65536.0); + } + + *nItems = n; + return (void*) array_double; +} + +static +cmsBool Type_U16Fixed16_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) +{ + cmsFloat64Number* Value = (cmsFloat64Number*) Ptr; + cmsUInt32Number i; + + for (i=0; i < nItems; i++) { + + cmsUInt32Number v = (cmsUInt32Number) floor(Value[i]*65536.0 + 0.5); + + if (!_cmsWriteUInt32Number(io, v)) return FALSE; + } + + return TRUE; + + cmsUNUSED_PARAMETER(self); +} + + +static +void* Type_U16Fixed16_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) +{ + return _cmsDupMem(self ->ContextID, Ptr, n * sizeof(cmsFloat64Number)); +} + +static +void Type_U16Fixed16_Free(struct _cms_typehandler_struct* self, void* Ptr) +{ + _cmsFree(self ->ContextID, Ptr); +} + +// ******************************************************************************** +// Type cmsSigSignatureType +// ******************************************************************************** +// +// The signatureType contains a four-byte sequence, Sequences of less than four +// characters are padded at the end with spaces, 20h. +// Typically this type is used for registered tags that can be displayed on many +// development systems as a sequence of four characters. + +static +void *Type_Signature_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) +{ + cmsSignature* SigPtr = (cmsSignature*) _cmsMalloc(self ->ContextID, sizeof(cmsSignature)); + if (SigPtr == NULL) return NULL; + + if (!_cmsReadUInt32Number(io, SigPtr)) return NULL; + *nItems = 1; + + return SigPtr; + + cmsUNUSED_PARAMETER(SizeOfTag); +} + +static +cmsBool Type_Signature_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) +{ + cmsSignature* SigPtr = (cmsSignature*) Ptr; + + return _cmsWriteUInt32Number(io, *SigPtr); + + cmsUNUSED_PARAMETER(nItems); + cmsUNUSED_PARAMETER(self); +} + +static +void* Type_Signature_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) +{ + return _cmsDupMem(self ->ContextID, Ptr, n * sizeof(cmsSignature)); +} + +static +void Type_Signature_Free(struct _cms_typehandler_struct* self, void* Ptr) +{ + _cmsFree(self ->ContextID, Ptr); +} + + +// ******************************************************************************** +// Type cmsSigTextType +// ******************************************************************************** +// +// The textType is a simple text structure that contains a 7-bit ASCII text string. +// The length of the string is obtained by subtracting 8 from the element size portion +// of the tag itself. This string must be terminated with a 00h byte. + +static +void *Type_Text_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) +{ + char* Text = NULL; + cmsMLU* mlu = NULL; + + // Create a container + mlu = cmsMLUalloc(self ->ContextID, 1); + if (mlu == NULL) return NULL; + + *nItems = 0; + + // We need to store the "\0" at the end, so +1 + if (SizeOfTag == UINT_MAX) goto Error; + + Text = (char*) _cmsMalloc(self ->ContextID, SizeOfTag + 1); + if (Text == NULL) goto Error; + + if (io -> Read(io, Text, sizeof(char), SizeOfTag) != SizeOfTag) goto Error; + + // Make sure text is properly ended + Text[SizeOfTag] = 0; + *nItems = 1; + + // Keep the result + if (!cmsMLUsetASCII(mlu, cmsNoLanguage, cmsNoCountry, Text)) goto Error; + + _cmsFree(self ->ContextID, Text); + return (void*) mlu; + +Error: + if (mlu != NULL) + cmsMLUfree(mlu); + if (Text != NULL) + _cmsFree(self ->ContextID, Text); + + return NULL; +} + +// The conversion implies to choose a language. So, we choose the actual language. +static +cmsBool Type_Text_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) +{ + cmsMLU* mlu = (cmsMLU*) Ptr; + cmsUInt32Number size; + cmsBool rc; + char* Text; + + // Get the size of the string. Note there is an extra "\0" at the end + size = cmsMLUgetASCII(mlu, cmsNoLanguage, cmsNoCountry, NULL, 0); + if (size == 0) return FALSE; // Cannot be zero! + + // Create memory + Text = (char*) _cmsMalloc(self ->ContextID, size); + cmsMLUgetASCII(mlu, cmsNoLanguage, cmsNoCountry, Text, size); + + // Write it, including separator + rc = io ->Write(io, size, Text); + + _cmsFree(self ->ContextID, Text); + return rc; + + cmsUNUSED_PARAMETER(nItems); +} + +static +void* Type_Text_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) +{ + return (void*) cmsMLUdup((cmsMLU*) Ptr); + + cmsUNUSED_PARAMETER(n); + cmsUNUSED_PARAMETER(self); +} + + +static +void Type_Text_Free(struct _cms_typehandler_struct* self, void* Ptr) +{ + cmsMLU* mlu = (cmsMLU*) Ptr; + cmsMLUfree(mlu); + return; + + cmsUNUSED_PARAMETER(self); +} + +static +cmsTagTypeSignature DecideTextType(cmsFloat64Number ICCVersion, const void *Data) +{ + if (ICCVersion >= 4.0) + return cmsSigMultiLocalizedUnicodeType; + + return cmsSigTextType; + + cmsUNUSED_PARAMETER(Data); +} + + +// ******************************************************************************** +// Type cmsSigDataType +// ******************************************************************************** + +// General purpose data type +static +void *Type_Data_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) +{ + cmsICCData* BinData; + cmsUInt32Number LenOfData; + + *nItems = 0; + + if (SizeOfTag < sizeof(cmsUInt32Number)) return NULL; + + LenOfData = SizeOfTag - sizeof(cmsUInt32Number); + if (LenOfData > INT_MAX) return NULL; + + BinData = (cmsICCData*) _cmsMalloc(self ->ContextID, sizeof(cmsICCData) + LenOfData - 1); + if (BinData == NULL) return NULL; + + BinData ->len = LenOfData; + if (!_cmsReadUInt32Number(io, &BinData->flag)) { + _cmsFree(self ->ContextID, BinData); + return NULL; + } + + if (io -> Read(io, BinData ->data, sizeof(cmsUInt8Number), LenOfData) != LenOfData) { + + _cmsFree(self ->ContextID, BinData); + return NULL; + } + + *nItems = 1; + + return (void*) BinData; +} + + +static +cmsBool Type_Data_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) +{ + cmsICCData* BinData = (cmsICCData*) Ptr; + + if (!_cmsWriteUInt32Number(io, BinData ->flag)) return FALSE; + + return io ->Write(io, BinData ->len, BinData ->data); + + cmsUNUSED_PARAMETER(nItems); + cmsUNUSED_PARAMETER(self); +} + + +static +void* Type_Data_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) +{ + cmsICCData* BinData = (cmsICCData*) Ptr; + + return _cmsDupMem(self ->ContextID, Ptr, sizeof(cmsICCData) + BinData ->len - 1); + + cmsUNUSED_PARAMETER(n); +} + +static +void Type_Data_Free(struct _cms_typehandler_struct* self, void* Ptr) +{ + _cmsFree(self ->ContextID, Ptr); +} + +// ******************************************************************************** +// Type cmsSigTextDescriptionType +// ******************************************************************************** + +static +void *Type_Text_Description_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) +{ + char* Text = NULL; + cmsMLU* mlu = NULL; + cmsUInt32Number AsciiCount; + cmsUInt32Number i, UnicodeCode, UnicodeCount; + cmsUInt16Number ScriptCodeCode, Dummy; + cmsUInt8Number ScriptCodeCount; + + *nItems = 0; + + // One dword should be there + if (SizeOfTag < sizeof(cmsUInt32Number)) return NULL; + + // Read len of ASCII + if (!_cmsReadUInt32Number(io, &AsciiCount)) return NULL; + SizeOfTag -= sizeof(cmsUInt32Number); + + // Check for size + if (SizeOfTag < AsciiCount) return NULL; + + // All seems Ok, allocate the container + mlu = cmsMLUalloc(self ->ContextID, 1); + if (mlu == NULL) return NULL; + + // As many memory as size of tag + Text = (char*) _cmsMalloc(self ->ContextID, AsciiCount + 1); + if (Text == NULL) goto Error; + + // Read it + if (io ->Read(io, Text, sizeof(char), AsciiCount) != AsciiCount) goto Error; + SizeOfTag -= AsciiCount; + + // Make sure there is a terminator + Text[AsciiCount] = 0; + + // Set the MLU entry. From here we can be tolerant to wrong types + if (!cmsMLUsetASCII(mlu, cmsNoLanguage, cmsNoCountry, Text)) goto Error; + _cmsFree(self ->ContextID, (void*) Text); + Text = NULL; + + // Skip Unicode code + if (SizeOfTag < 2* sizeof(cmsUInt32Number)) goto Done; + if (!_cmsReadUInt32Number(io, &UnicodeCode)) goto Done; + if (!_cmsReadUInt32Number(io, &UnicodeCount)) goto Done; + SizeOfTag -= 2* sizeof(cmsUInt32Number); + + if (SizeOfTag < UnicodeCount*sizeof(cmsUInt16Number)) goto Done; + + for (i=0; i < UnicodeCount; i++) { + if (!io ->Read(io, &Dummy, sizeof(cmsUInt16Number), 1)) goto Done; + } + SizeOfTag -= UnicodeCount*sizeof(cmsUInt16Number); + + // Skip ScriptCode code if present. Some buggy profiles does have less + // data that stricttly required. We need to skip it as this type may come + // embedded in other types. + + if (SizeOfTag >= sizeof(cmsUInt16Number) + sizeof(cmsUInt8Number) + 67) { + + if (!_cmsReadUInt16Number(io, &ScriptCodeCode)) goto Done; + if (!_cmsReadUInt8Number(io, &ScriptCodeCount)) goto Done; + + // Skip rest of tag + for (i=0; i < 67; i++) { + if (!io ->Read(io, &Dummy, sizeof(cmsUInt8Number), 1)) goto Error; + } + } + +Done: + + *nItems = 1; + return mlu; + +Error: + if (Text) _cmsFree(self ->ContextID, (void*) Text); + if (mlu) cmsMLUfree(mlu); + return NULL; +} + + +// This tag can come IN UNALIGNED SIZE. In order to prevent issues, we force zeros on description to align it +static +cmsBool Type_Text_Description_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) +{ + cmsMLU* mlu = (cmsMLU*) Ptr; + char *Text = NULL; + wchar_t *Wide = NULL; + cmsUInt32Number len, len_aligned, len_filler_alignment; + cmsBool rc = FALSE; + char Filler[68]; + + // Used below for writting zeroes + memset(Filler, 0, sizeof(Filler)); + + // Get the len of string + len = cmsMLUgetASCII(mlu, cmsNoLanguage, cmsNoCountry, NULL, 0); + + // From ICC3.4: It has been found that textDescriptionType can contain misaligned data + //(see clause 4.1 for the definition of “aligned”). Because the Unicode language + // code and Unicode count immediately follow the ASCII description, their + // alignment is not correct if the ASCII count is not a multiple of four. The + // ScriptCode code is misaligned when the ASCII count is odd. Profile reading and + // writing software must be written carefully in order to handle these alignment + // problems. + + // Compute an aligned size + len_aligned = _cmsALIGNLONG(len); + len_filler_alignment = len_aligned - len; + + // Null strings + if (len <= 0) { + + Text = (char*) _cmsDupMem(self ->ContextID, "", sizeof(char)); + Wide = (wchar_t*) _cmsDupMem(self ->ContextID, L"", sizeof(wchar_t)); + } + else { + // Create independent buffers + Text = (char*) _cmsCalloc(self ->ContextID, len, sizeof(char)); + if (Text == NULL) goto Error; + + Wide = (wchar_t*) _cmsCalloc(self ->ContextID, len, sizeof(wchar_t)); + if (Wide == NULL) goto Error; + + // Get both representations. + cmsMLUgetASCII(mlu, cmsNoLanguage, cmsNoCountry, Text, len * sizeof(char)); + cmsMLUgetWide(mlu, cmsNoLanguage, cmsNoCountry, Wide, len * sizeof(wchar_t)); + } + + // * cmsUInt32Number count; * Description length + // * cmsInt8Number desc[count] * NULL terminated ascii string + // * cmsUInt32Number ucLangCode; * UniCode language code + // * cmsUInt32Number ucCount; * UniCode description length + // * cmsInt16Number ucDesc[ucCount];* The UniCode description + // * cmsUInt16Number scCode; * ScriptCode code + // * cmsUInt8Number scCount; * ScriptCode count + // * cmsInt8Number scDesc[67]; * ScriptCode Description + + if (!_cmsWriteUInt32Number(io, len_aligned)) goto Error; + if (!io ->Write(io, len, Text)) goto Error; + if (!io ->Write(io, len_filler_alignment, Filler)) goto Error; + + if (!_cmsWriteUInt32Number(io, 0)) goto Error; // ucLanguageCode + + // This part is tricky: we need an aligned tag size, and the ScriptCode part + // takes 70 bytes, so we need 2 extra bytes to do the alignment + + if (!_cmsWriteUInt32Number(io, len_aligned+1)) goto Error; + + // Note that in some compilers sizeof(cmsUInt16Number) != sizeof(wchar_t) + if (!_cmsWriteWCharArray(io, len, Wide)) goto Error; + if (!_cmsWriteUInt16Array(io, len_filler_alignment+1, (cmsUInt16Number*) Filler)) goto Error; + + // ScriptCode Code & count (unused) + if (!_cmsWriteUInt16Number(io, 0)) goto Error; + if (!_cmsWriteUInt8Number(io, 0)) goto Error; + + if (!io ->Write(io, 67, Filler)) goto Error; + + rc = TRUE; + +Error: + if (Text) _cmsFree(self ->ContextID, Text); + if (Wide) _cmsFree(self ->ContextID, Wide); + + return rc; + + cmsUNUSED_PARAMETER(nItems); +} + + +static +void* Type_Text_Description_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) +{ + return (void*) cmsMLUdup((cmsMLU*) Ptr); + + cmsUNUSED_PARAMETER(n); + cmsUNUSED_PARAMETER(self); +} + +static +void Type_Text_Description_Free(struct _cms_typehandler_struct* self, void* Ptr) +{ + cmsMLU* mlu = (cmsMLU*) Ptr; + + cmsMLUfree(mlu); + return; + + cmsUNUSED_PARAMETER(self); +} + + +static +cmsTagTypeSignature DecideTextDescType(cmsFloat64Number ICCVersion, const void *Data) +{ + if (ICCVersion >= 4.0) + return cmsSigMultiLocalizedUnicodeType; + + return cmsSigTextDescriptionType; + + cmsUNUSED_PARAMETER(Data); +} + + +// ******************************************************************************** +// Type cmsSigCurveType +// ******************************************************************************** + +static +void *Type_Curve_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) +{ + cmsUInt32Number Count; + cmsToneCurve* NewGamma; + + *nItems = 0; + if (!_cmsReadUInt32Number(io, &Count)) return NULL; + + switch (Count) { + + case 0: // Linear. + { + cmsFloat64Number SingleGamma = 1.0; + + NewGamma = cmsBuildParametricToneCurve(self ->ContextID, 1, &SingleGamma); + if (!NewGamma) return NULL; + *nItems = 1; + return NewGamma; + } + + case 1: // Specified as the exponent of gamma function + { + cmsUInt16Number SingleGammaFixed; + cmsFloat64Number SingleGamma; + + if (!_cmsReadUInt16Number(io, &SingleGammaFixed)) return NULL; + SingleGamma = _cms8Fixed8toDouble(SingleGammaFixed); + + *nItems = 1; + return cmsBuildParametricToneCurve(self ->ContextID, 1, &SingleGamma); + } + + default: // Curve + + if (Count > 0x7FFF) + return NULL; // This is to prevent bad guys for doing bad things + + NewGamma = cmsBuildTabulatedToneCurve16(self ->ContextID, Count, NULL); + if (!NewGamma) return NULL; + + if (!_cmsReadUInt16Array(io, Count, NewGamma -> Table16)) return NULL; + + *nItems = 1; + return NewGamma; + } + + cmsUNUSED_PARAMETER(SizeOfTag); +} + + +static +cmsBool Type_Curve_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) +{ + cmsToneCurve* Curve = (cmsToneCurve*) Ptr; + + if (Curve ->nSegments == 1 && Curve ->Segments[0].Type == 1) { + + // Single gamma, preserve number + cmsUInt16Number SingleGammaFixed = _cmsDoubleTo8Fixed8(Curve ->Segments[0].Params[0]); + + if (!_cmsWriteUInt32Number(io, 1)) return FALSE; + if (!_cmsWriteUInt16Number(io, SingleGammaFixed)) return FALSE; + return TRUE; + + } + + if (!_cmsWriteUInt32Number(io, Curve ->nEntries)) return FALSE; + return _cmsWriteUInt16Array(io, Curve ->nEntries, Curve ->Table16); + + cmsUNUSED_PARAMETER(nItems); + cmsUNUSED_PARAMETER(self); +} + + +static +void* Type_Curve_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) +{ + return (void*) cmsDupToneCurve((cmsToneCurve*) Ptr); + + cmsUNUSED_PARAMETER(n); + cmsUNUSED_PARAMETER(self); +} + +static +void Type_Curve_Free(struct _cms_typehandler_struct* self, void* Ptr) +{ + cmsToneCurve* gamma = (cmsToneCurve*) Ptr; + + cmsFreeToneCurve(gamma); + return; + + cmsUNUSED_PARAMETER(self); +} + + +// ******************************************************************************** +// Type cmsSigParametricCurveType +// ******************************************************************************** + + +// Decide which curve type to use on writting +static +cmsTagTypeSignature DecideCurveType(cmsFloat64Number ICCVersion, const void *Data) +{ + cmsToneCurve* Curve = (cmsToneCurve*) Data; + + if (ICCVersion < 4.0) return cmsSigCurveType; + if (Curve ->nSegments != 1) return cmsSigCurveType; // Only 1-segment curves can be saved as parametric + if (Curve ->Segments[0].Type < 0) return cmsSigCurveType; // Only non-inverted curves + if (Curve ->Segments[0].Type > 5) return cmsSigCurveType; // Only ICC parametric curves + + return cmsSigParametricCurveType; +} + +static +void *Type_ParametricCurve_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) +{ + static const int ParamsByType[] = { 1, 3, 4, 5, 7 }; + cmsFloat64Number Params[10]; + cmsUInt16Number Type; + int i, n; + cmsToneCurve* NewGamma; + + if (!_cmsReadUInt16Number(io, &Type)) return NULL; + if (!_cmsReadUInt16Number(io, NULL)) return NULL; // Reserved + + if (Type > 4) { + + cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown parametric curve type '%d'", Type); + return NULL; + } + + memset(Params, 0, sizeof(Params)); + n = ParamsByType[Type]; + + for (i=0; i < n; i++) { + + if (!_cmsRead15Fixed16Number(io, &Params[i])) return NULL; + } + + NewGamma = cmsBuildParametricToneCurve(self ->ContextID, Type+1, Params); + + *nItems = 1; + return NewGamma; + + cmsUNUSED_PARAMETER(SizeOfTag); +} + + +static +cmsBool Type_ParametricCurve_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) +{ + cmsToneCurve* Curve = (cmsToneCurve*) Ptr; + int i, nParams, typen; + static const int ParamsByType[] = { 0, 1, 3, 4, 5, 7 }; + + typen = Curve -> Segments[0].Type; + + if (Curve ->nSegments > 1 || typen < 1) { + + cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Multisegment or Inverted parametric curves cannot be written"); + return FALSE; + } + + if (typen > 5) { + cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported parametric curve"); + return FALSE; + } + + nParams = ParamsByType[typen]; + + if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) (Curve ->Segments[0].Type - 1))) return FALSE; + if (!_cmsWriteUInt16Number(io, 0)) return FALSE; // Reserved + + for (i=0; i < nParams; i++) { + + if (!_cmsWrite15Fixed16Number(io, Curve -> Segments[0].Params[i])) return FALSE; + } + + return TRUE; + + cmsUNUSED_PARAMETER(nItems); +} + +static +void* Type_ParametricCurve_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) +{ + return (void*) cmsDupToneCurve((cmsToneCurve*) Ptr); + + cmsUNUSED_PARAMETER(n); + cmsUNUSED_PARAMETER(self); +} + +static +void Type_ParametricCurve_Free(struct _cms_typehandler_struct* self, void* Ptr) +{ + cmsToneCurve* gamma = (cmsToneCurve*) Ptr; + + cmsFreeToneCurve(gamma); + return; + + cmsUNUSED_PARAMETER(self); +} + + +// ******************************************************************************** +// Type cmsSigDateTimeType +// ******************************************************************************** + +// A 12-byte value representation of the time and date, where the byte usage is assigned +// as specified in table 1. The actual values are encoded as 16-bit unsigned integers +// (uInt16Number - see 5.1.6). +// +// All the dateTimeNumber values in a profile shall be in Coordinated Universal Time +// (UTC, also known as GMT or ZULU Time). Profile writers are required to convert local +// time to UTC when setting these values. Programmes that display these values may show +// the dateTimeNumber as UTC, show the equivalent local time (at current locale), or +// display both UTC and local versions of the dateTimeNumber. + +static +void *Type_DateTime_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) +{ + cmsDateTimeNumber timestamp; + struct tm * NewDateTime; + + *nItems = 0; + NewDateTime = (struct tm*) _cmsMalloc(self ->ContextID, sizeof(struct tm)); + if (NewDateTime == NULL) return NULL; + + if (io->Read(io, ×tamp, sizeof(cmsDateTimeNumber), 1) != 1) return NULL; + + _cmsDecodeDateTimeNumber(×tamp, NewDateTime); + + *nItems = 1; + return NewDateTime; + + cmsUNUSED_PARAMETER(SizeOfTag); +} + + +static +cmsBool Type_DateTime_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) +{ + struct tm * DateTime = (struct tm*) Ptr; + cmsDateTimeNumber timestamp; + + _cmsEncodeDateTimeNumber(×tamp, DateTime); + if (!io ->Write(io, sizeof(cmsDateTimeNumber), ×tamp)) return FALSE; + + return TRUE; + + cmsUNUSED_PARAMETER(nItems); + cmsUNUSED_PARAMETER(self); +} + +static +void* Type_DateTime_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) +{ + return _cmsDupMem(self ->ContextID, Ptr, sizeof(struct tm)); + + cmsUNUSED_PARAMETER(n); +} + +static +void Type_DateTime_Free(struct _cms_typehandler_struct* self, void* Ptr) +{ + _cmsFree(self ->ContextID, Ptr); +} + + + +// ******************************************************************************** +// Type icMeasurementType +// ******************************************************************************** + +/* +The measurementType information refers only to the internal profile data and is +meant to provide profile makers an alternative to the default measurement +specifications. +*/ + +static +void *Type_Measurement_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) +{ + cmsICCMeasurementConditions mc; + + + memset(&mc, 0, sizeof(mc)); + + if (!_cmsReadUInt32Number(io, &mc.Observer)) return NULL; + if (!_cmsReadXYZNumber(io, &mc.Backing)) return NULL; + if (!_cmsReadUInt32Number(io, &mc.Geometry)) return NULL; + if (!_cmsRead15Fixed16Number(io, &mc.Flare)) return NULL; + if (!_cmsReadUInt32Number(io, &mc.IlluminantType)) return NULL; + + *nItems = 1; + return _cmsDupMem(self ->ContextID, &mc, sizeof(cmsICCMeasurementConditions)); + + cmsUNUSED_PARAMETER(SizeOfTag); +} + + +static +cmsBool Type_Measurement_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) +{ + cmsICCMeasurementConditions* mc =(cmsICCMeasurementConditions*) Ptr; + + if (!_cmsWriteUInt32Number(io, mc->Observer)) return FALSE; + if (!_cmsWriteXYZNumber(io, &mc->Backing)) return FALSE; + if (!_cmsWriteUInt32Number(io, mc->Geometry)) return FALSE; + if (!_cmsWrite15Fixed16Number(io, mc->Flare)) return FALSE; + if (!_cmsWriteUInt32Number(io, mc->IlluminantType)) return FALSE; + + return TRUE; + + cmsUNUSED_PARAMETER(nItems); + cmsUNUSED_PARAMETER(self); +} + +static +void* Type_Measurement_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) +{ + return _cmsDupMem(self ->ContextID, Ptr, sizeof(cmsICCMeasurementConditions)); + + cmsUNUSED_PARAMETER(n); +} + +static +void Type_Measurement_Free(struct _cms_typehandler_struct* self, void* Ptr) +{ + _cmsFree(self ->ContextID, Ptr); +} + + +// ******************************************************************************** +// Type cmsSigMultiLocalizedUnicodeType +// ******************************************************************************** +// +// Do NOT trust SizeOfTag as there is an issue on the definition of profileSequenceDescTag. See the TechNote from +// Max Derhak and Rohit Patil about this: basically the size of the string table should be guessed and cannot be +// taken from the size of tag if this tag is embedded as part of bigger structures (profileSequenceDescTag, for instance) +// + +static +void *Type_MLU_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) +{ + cmsMLU* mlu; + cmsUInt32Number Count, RecLen, NumOfWchar; + cmsUInt32Number SizeOfHeader; + cmsUInt32Number Len, Offset; + cmsUInt32Number i; + wchar_t* Block; + cmsUInt32Number BeginOfThisString, EndOfThisString, LargestPosition; + + *nItems = 0; + if (!_cmsReadUInt32Number(io, &Count)) return NULL; + if (!_cmsReadUInt32Number(io, &RecLen)) return NULL; + + if (RecLen != 12) { + + cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "multiLocalizedUnicodeType of len != 12 is not supported."); + return NULL; + } + + mlu = cmsMLUalloc(self ->ContextID, Count); + if (mlu == NULL) return NULL; + + mlu ->UsedEntries = Count; + + SizeOfHeader = 12 * Count + sizeof(_cmsTagBase); + LargestPosition = 0; + + for (i=0; i < Count; i++) { + + if (!_cmsReadUInt16Number(io, &mlu ->Entries[i].Language)) goto Error; + if (!_cmsReadUInt16Number(io, &mlu ->Entries[i].Country)) goto Error; + + // Now deal with Len and offset. + if (!_cmsReadUInt32Number(io, &Len)) goto Error; + if (!_cmsReadUInt32Number(io, &Offset)) goto Error; + + // Check for overflow + if (Offset < (SizeOfHeader + 8)) goto Error; + + // True begin of the string + BeginOfThisString = Offset - SizeOfHeader - 8; + + // Ajust to wchar_t elements + mlu ->Entries[i].Len = (Len * sizeof(wchar_t)) / sizeof(cmsUInt16Number); + mlu ->Entries[i].StrW = (BeginOfThisString * sizeof(wchar_t)) / sizeof(cmsUInt16Number); + + // To guess maximum size, add offset + len + EndOfThisString = BeginOfThisString + Len; + if (EndOfThisString > LargestPosition) + LargestPosition = EndOfThisString; + } + + // Now read the remaining of tag and fill all strings. Substract the directory + SizeOfTag = (LargestPosition * sizeof(wchar_t)) / sizeof(cmsUInt16Number); + if (SizeOfTag == 0) + { + Block = NULL; + NumOfWchar = 0; + + } + else + { + Block = (wchar_t*) _cmsMalloc(self ->ContextID, SizeOfTag); + if (Block == NULL) goto Error; + NumOfWchar = SizeOfTag / sizeof(wchar_t); + if (!_cmsReadWCharArray(io, NumOfWchar, Block)) goto Error; + } + + mlu ->MemPool = Block; + mlu ->PoolSize = SizeOfTag; + mlu ->PoolUsed = SizeOfTag; + + *nItems = 1; + return (void*) mlu; + +Error: + if (mlu) cmsMLUfree(mlu); + return NULL; +} + +static +cmsBool Type_MLU_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) +{ + cmsMLU* mlu =(cmsMLU*) Ptr; + cmsUInt32Number HeaderSize; + cmsUInt32Number Len, Offset; + int i; + + if (Ptr == NULL) { + + // Empty placeholder + if (!_cmsWriteUInt32Number(io, 0)) return FALSE; + if (!_cmsWriteUInt32Number(io, 12)) return FALSE; + return TRUE; + } + + if (!_cmsWriteUInt32Number(io, mlu ->UsedEntries)) return FALSE; + if (!_cmsWriteUInt32Number(io, 12)) return FALSE; + + HeaderSize = 12 * mlu ->UsedEntries + sizeof(_cmsTagBase); + + for (i=0; i < mlu ->UsedEntries; i++) { + + Len = mlu ->Entries[i].Len; + Offset = mlu ->Entries[i].StrW; + + Len = (Len * sizeof(cmsUInt16Number)) / sizeof(wchar_t); + Offset = (Offset * sizeof(cmsUInt16Number)) / sizeof(wchar_t) + HeaderSize + 8; + + if (!_cmsWriteUInt16Number(io, mlu ->Entries[i].Language)) return FALSE; + if (!_cmsWriteUInt16Number(io, mlu ->Entries[i].Country)) return FALSE; + if (!_cmsWriteUInt32Number(io, Len)) return FALSE; + if (!_cmsWriteUInt32Number(io, Offset)) return FALSE; + } + + if (!_cmsWriteWCharArray(io, mlu ->PoolUsed / sizeof(wchar_t), (wchar_t*) mlu ->MemPool)) return FALSE; + + return TRUE; + + cmsUNUSED_PARAMETER(nItems); + cmsUNUSED_PARAMETER(self); +} + + +static +void* Type_MLU_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) +{ + return (void*) cmsMLUdup((cmsMLU*) Ptr); + + cmsUNUSED_PARAMETER(n); + cmsUNUSED_PARAMETER(self); +} + +static +void Type_MLU_Free(struct _cms_typehandler_struct* self, void* Ptr) +{ + cmsMLUfree((cmsMLU*) Ptr); + return; + + cmsUNUSED_PARAMETER(self); +} + + +// ******************************************************************************** +// Type cmsSigLut8Type +// ******************************************************************************** + +// Decide which LUT type to use on writting +static +cmsTagTypeSignature DecideLUTtypeA2B(cmsFloat64Number ICCVersion, const void *Data) +{ + cmsPipeline* Lut = (cmsPipeline*) Data; + + if (ICCVersion < 4.0) { + if (Lut ->SaveAs8Bits) return cmsSigLut8Type; + return cmsSigLut16Type; + } + else { + return cmsSigLutAtoBType; + } +} + +static +cmsTagTypeSignature DecideLUTtypeB2A(cmsFloat64Number ICCVersion, const void *Data) +{ + cmsPipeline* Lut = (cmsPipeline*) Data; + + if (ICCVersion < 4.0) { + if (Lut ->SaveAs8Bits) return cmsSigLut8Type; + return cmsSigLut16Type; + } + else { + return cmsSigLutBtoAType; + } +} + +/* +This structure represents a colour transform using tables of 8-bit precision. +This type contains four processing elements: a 3 by 3 matrix (which shall be +the identity matrix unless the input colour space is XYZ), a set of one dimensional +input tables, a multidimensional lookup table, and a set of one dimensional output +tables. Data is processed using these elements via the following sequence: +(matrix) -> (1d input tables) -> (multidimensional lookup table - CLUT) -> (1d output tables) + +Byte Position Field Length (bytes) Content Encoded as... +8 1 Number of Input Channels (i) uInt8Number +9 1 Number of Output Channels (o) uInt8Number +10 1 Number of CLUT grid points (identical for each side) (g) uInt8Number +11 1 Reserved for padding (fill with 00h) + +12..15 4 Encoded e00 parameter s15Fixed16Number +*/ + + +// Read 8 bit tables as gamma functions +static +cmsBool Read8bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsPipeline* lut, int nChannels) +{ + cmsUInt8Number* Temp = NULL; + int i, j; + cmsToneCurve* Tables[cmsMAXCHANNELS]; + + if (nChannels > cmsMAXCHANNELS) return FALSE; + if (nChannels <= 0) return FALSE; + + memset(Tables, 0, sizeof(Tables)); + + Temp = (cmsUInt8Number*) _cmsMalloc(ContextID, 256); + if (Temp == NULL) return FALSE; + + for (i=0; i < nChannels; i++) { + Tables[i] = cmsBuildTabulatedToneCurve16(ContextID, 256, NULL); + if (Tables[i] == NULL) goto Error; + } + + for (i=0; i < nChannels; i++) { + + if (io ->Read(io, Temp, 256, 1) != 1) goto Error; + + for (j=0; j < 256; j++) + Tables[i]->Table16[j] = (cmsUInt16Number) FROM_8_TO_16(Temp[j]); + } + + _cmsFree(ContextID, Temp); + Temp = NULL; + + if (!cmsPipelineInsertStage(lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, nChannels, Tables))) + goto Error; + + for (i=0; i < nChannels; i++) + cmsFreeToneCurve(Tables[i]); + + return TRUE; + +Error: + for (i=0; i < nChannels; i++) { + if (Tables[i]) cmsFreeToneCurve(Tables[i]); + } + + if (Temp) _cmsFree(ContextID, Temp); + return FALSE; +} + + +static +cmsBool Write8bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsUInt32Number n, _cmsStageToneCurvesData* Tables) +{ + int j; + cmsUInt32Number i; + cmsUInt8Number val; + + for (i=0; i < n; i++) { + + if (Tables) { + + // Usual case of identity curves + if ((Tables ->TheCurves[i]->nEntries == 2) && + (Tables->TheCurves[i]->Table16[0] == 0) && + (Tables->TheCurves[i]->Table16[1] == 65535)) { + + for (j=0; j < 256; j++) { + if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) j)) return FALSE; + } + } + else + if (Tables ->TheCurves[i]->nEntries != 256) { + cmsSignalError(ContextID, cmsERROR_RANGE, "LUT8 needs 256 entries on prelinearization"); + return FALSE; + } + else + for (j=0; j < 256; j++) { + + if (Tables != NULL) + val = (cmsUInt8Number) FROM_16_TO_8(Tables->TheCurves[i]->Table16[j]); + else + val = (cmsUInt8Number) j; + + if (!_cmsWriteUInt8Number(io, val)) return FALSE; + } + } + } + return TRUE; +} + + +// Check overflow +static +cmsUInt32Number uipow(cmsUInt32Number n, cmsUInt32Number a, cmsUInt32Number b) +{ + cmsUInt32Number rv = 1, rc; + + if (a == 0) return 0; + if (n == 0) return 0; + + for (; b > 0; b--) { + + rv *= a; + + // Check for overflow + if (rv > UINT_MAX / a) return (cmsUInt32Number) -1; + + } + + rc = rv * n; + + if (rv != rc / n) return (cmsUInt32Number) -1; + return rc; +} + + +// That will create a MPE LUT with Matrix, pre tables, CLUT and post tables. +// 8 bit lut may be scaled easely to v4 PCS, but we need also to properly adjust +// PCS on BToAxx tags and AtoB if abstract. We need to fix input direction. + +static +void *Type_LUT8_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) +{ + cmsUInt8Number InputChannels, OutputChannels, CLUTpoints; + cmsUInt8Number* Temp = NULL; + cmsPipeline* NewLUT = NULL; + cmsUInt32Number nTabSize, i; + cmsFloat64Number Matrix[3*3]; + + *nItems = 0; + + if (!_cmsReadUInt8Number(io, &InputChannels)) goto Error; + if (!_cmsReadUInt8Number(io, &OutputChannels)) goto Error; + if (!_cmsReadUInt8Number(io, &CLUTpoints)) goto Error; + + if (CLUTpoints == 1) goto Error; // Impossible value, 0 for no CLUT and then 2 at least + + // Padding + if (!_cmsReadUInt8Number(io, NULL)) goto Error; + + // Do some checking + + if (InputChannels > cmsMAXCHANNELS) goto Error; + if (OutputChannels > cmsMAXCHANNELS) goto Error; + + // Allocates an empty Pipeline + NewLUT = cmsPipelineAlloc(self ->ContextID, InputChannels, OutputChannels); + if (NewLUT == NULL) goto Error; + + // Read the Matrix + if (!_cmsRead15Fixed16Number(io, &Matrix[0])) goto Error; + if (!_cmsRead15Fixed16Number(io, &Matrix[1])) goto Error; + if (!_cmsRead15Fixed16Number(io, &Matrix[2])) goto Error; + if (!_cmsRead15Fixed16Number(io, &Matrix[3])) goto Error; + if (!_cmsRead15Fixed16Number(io, &Matrix[4])) goto Error; + if (!_cmsRead15Fixed16Number(io, &Matrix[5])) goto Error; + if (!_cmsRead15Fixed16Number(io, &Matrix[6])) goto Error; + if (!_cmsRead15Fixed16Number(io, &Matrix[7])) goto Error; + if (!_cmsRead15Fixed16Number(io, &Matrix[8])) goto Error; + + + // Only operates if not identity... + if ((InputChannels == 3) && !_cmsMAT3isIdentity((cmsMAT3*) Matrix)) { + + if (!cmsPipelineInsertStage(NewLUT, cmsAT_BEGIN, cmsStageAllocMatrix(self ->ContextID, 3, 3, Matrix, NULL))) + goto Error; + } + + // Get input tables + if (!Read8bitTables(self ->ContextID, io, NewLUT, InputChannels)) goto Error; + + // Get 3D CLUT. Check the overflow.... + nTabSize = uipow(OutputChannels, CLUTpoints, InputChannels); + if (nTabSize == (cmsUInt32Number) -1) goto Error; + if (nTabSize > 0) { + + cmsUInt16Number *PtrW, *T; + + PtrW = T = (cmsUInt16Number*) _cmsCalloc(self ->ContextID, nTabSize, sizeof(cmsUInt16Number)); + if (T == NULL) goto Error; + + Temp = (cmsUInt8Number*) _cmsMalloc(self ->ContextID, nTabSize); + if (Temp == NULL) goto Error; + + if (io ->Read(io, Temp, nTabSize, 1) != 1) goto Error; + + for (i = 0; i < nTabSize; i++) { + + *PtrW++ = FROM_8_TO_16(Temp[i]); + } + _cmsFree(self ->ContextID, Temp); + Temp = NULL; + + if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, cmsStageAllocCLut16bit(self ->ContextID, CLUTpoints, InputChannels, OutputChannels, T))) + goto Error; + _cmsFree(self ->ContextID, T); + } + + + // Get output tables + if (!Read8bitTables(self ->ContextID, io, NewLUT, OutputChannels)) goto Error; + + *nItems = 1; + return NewLUT; + +Error: + if (NewLUT != NULL) cmsPipelineFree(NewLUT); + return NULL; + + cmsUNUSED_PARAMETER(SizeOfTag); +} + +// We only allow a specific MPE structure: Matrix plus prelin, plus clut, plus post-lin. +static +cmsBool Type_LUT8_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) +{ + cmsUInt32Number j, nTabSize; + cmsUInt8Number val; + cmsPipeline* NewLUT = (cmsPipeline*) Ptr; + cmsStage* mpe; + _cmsStageToneCurvesData* PreMPE = NULL, *PostMPE = NULL; + _cmsStageMatrixData* MatMPE = NULL; + _cmsStageCLutData* clut = NULL; + int clutPoints; + + // Disassemble the LUT into components. + mpe = NewLUT -> Elements; + if (mpe ->Type == cmsSigMatrixElemType) { + + MatMPE = (_cmsStageMatrixData*) mpe ->Data; + mpe = mpe -> Next; + } + + if (mpe != NULL && mpe ->Type == cmsSigCurveSetElemType) { + PreMPE = (_cmsStageToneCurvesData*) mpe ->Data; + mpe = mpe -> Next; + } + + if (mpe != NULL && mpe ->Type == cmsSigCLutElemType) { + clut = (_cmsStageCLutData*) mpe -> Data; + mpe = mpe ->Next; + } + + if (mpe != NULL && mpe ->Type == cmsSigCurveSetElemType) { + PostMPE = (_cmsStageToneCurvesData*) mpe ->Data; + mpe = mpe -> Next; + } + + // That should be all + if (mpe != NULL) { + cmsSignalError(mpe->ContextID, cmsERROR_UNKNOWN_EXTENSION, "LUT is not suitable to be saved as LUT8"); + return FALSE; + } + + + if (clut == NULL) + clutPoints = 0; + else + clutPoints = clut->Params->nSamples[0]; + + if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) NewLUT ->InputChannels)) return FALSE; + if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) NewLUT ->OutputChannels)) return FALSE; + if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) clutPoints)) return FALSE; + if (!_cmsWriteUInt8Number(io, 0)) return FALSE; // Padding + + + if (MatMPE != NULL) { + + if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[0])) return FALSE; + if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[1])) return FALSE; + if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[2])) return FALSE; + if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[3])) return FALSE; + if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[4])) return FALSE; + if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[5])) return FALSE; + if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[6])) return FALSE; + if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[7])) return FALSE; + if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[8])) return FALSE; + + } + else { + + if (!_cmsWrite15Fixed16Number(io, 1)) return FALSE; + if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE; + if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE; + if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE; + if (!_cmsWrite15Fixed16Number(io, 1)) return FALSE; + if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE; + if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE; + if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE; + if (!_cmsWrite15Fixed16Number(io, 1)) return FALSE; + } + + // The prelinearization table + if (!Write8bitTables(self ->ContextID, io, NewLUT ->InputChannels, PreMPE)) return FALSE; + + nTabSize = uipow(NewLUT->OutputChannels, clutPoints, NewLUT ->InputChannels); + if (nTabSize == (cmsUInt32Number) -1) return FALSE; + if (nTabSize > 0) { + + // The 3D CLUT. + if (clut != NULL) { + + for (j=0; j < nTabSize; j++) { + + val = (cmsUInt8Number) FROM_16_TO_8(clut ->Tab.T[j]); + if (!_cmsWriteUInt8Number(io, val)) return FALSE; + } + } + } + + // The postlinearization table + if (!Write8bitTables(self ->ContextID, io, NewLUT ->OutputChannels, PostMPE)) return FALSE; + + return TRUE; + + cmsUNUSED_PARAMETER(nItems); +} + + +static +void* Type_LUT8_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) +{ + return (void*) cmsPipelineDup((cmsPipeline*) Ptr); + + cmsUNUSED_PARAMETER(n); + cmsUNUSED_PARAMETER(self); +} + +static +void Type_LUT8_Free(struct _cms_typehandler_struct* self, void* Ptr) +{ + cmsPipelineFree((cmsPipeline*) Ptr); + return; + + cmsUNUSED_PARAMETER(self); +} + +// ******************************************************************************** +// Type cmsSigLut16Type +// ******************************************************************************** + +// Read 16 bit tables as gamma functions +static +cmsBool Read16bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsPipeline* lut, int nChannels, int nEntries) +{ + int i; + cmsToneCurve* Tables[cmsMAXCHANNELS]; + + // Maybe an empty table? (this is a lcms extension) + if (nEntries <= 0) return TRUE; + + // Check for malicious profiles + if (nEntries < 2) return FALSE; + if (nChannels > cmsMAXCHANNELS) return FALSE; + + // Init table to zero + memset(Tables, 0, sizeof(Tables)); + + for (i=0; i < nChannels; i++) { + + Tables[i] = cmsBuildTabulatedToneCurve16(ContextID, nEntries, NULL); + if (Tables[i] == NULL) goto Error; + + if (!_cmsReadUInt16Array(io, nEntries, Tables[i]->Table16)) goto Error; + } + + + // Add the table (which may certainly be an identity, but this is up to the optimizer, not the reading code) + if (!cmsPipelineInsertStage(lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, nChannels, Tables))) + goto Error; + + for (i=0; i < nChannels; i++) + cmsFreeToneCurve(Tables[i]); + + return TRUE; + +Error: + for (i=0; i < nChannels; i++) { + if (Tables[i]) cmsFreeToneCurve(Tables[i]); + } + + return FALSE; +} + +static +cmsBool Write16bitTables(cmsContext ContextID, cmsIOHANDLER* io, _cmsStageToneCurvesData* Tables) +{ + int j; + cmsUInt32Number i; + cmsUInt16Number val; + int nEntries; + + _cmsAssert(Tables != NULL); + + nEntries = Tables->TheCurves[0]->nEntries; + + for (i=0; i < Tables ->nCurves; i++) { + + for (j=0; j < nEntries; j++) { + + val = Tables->TheCurves[i]->Table16[j]; + if (!_cmsWriteUInt16Number(io, val)) return FALSE; + } + } + return TRUE; + + cmsUNUSED_PARAMETER(ContextID); +} + +static +void *Type_LUT16_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) +{ + cmsUInt8Number InputChannels, OutputChannels, CLUTpoints; + cmsPipeline* NewLUT = NULL; + cmsUInt32Number nTabSize; + cmsFloat64Number Matrix[3*3]; + cmsUInt16Number InputEntries, OutputEntries; + + *nItems = 0; + + if (!_cmsReadUInt8Number(io, &InputChannels)) return NULL; + if (!_cmsReadUInt8Number(io, &OutputChannels)) return NULL; + if (!_cmsReadUInt8Number(io, &CLUTpoints)) return NULL; // 255 maximum + + // Padding + if (!_cmsReadUInt8Number(io, NULL)) return NULL; + + // Do some checking + if (InputChannels > cmsMAXCHANNELS) goto Error; + if (OutputChannels > cmsMAXCHANNELS) goto Error; + + // Allocates an empty LUT + NewLUT = cmsPipelineAlloc(self ->ContextID, InputChannels, OutputChannels); + if (NewLUT == NULL) goto Error; + + // Read the Matrix + if (!_cmsRead15Fixed16Number(io, &Matrix[0])) goto Error; + if (!_cmsRead15Fixed16Number(io, &Matrix[1])) goto Error; + if (!_cmsRead15Fixed16Number(io, &Matrix[2])) goto Error; + if (!_cmsRead15Fixed16Number(io, &Matrix[3])) goto Error; + if (!_cmsRead15Fixed16Number(io, &Matrix[4])) goto Error; + if (!_cmsRead15Fixed16Number(io, &Matrix[5])) goto Error; + if (!_cmsRead15Fixed16Number(io, &Matrix[6])) goto Error; + if (!_cmsRead15Fixed16Number(io, &Matrix[7])) goto Error; + if (!_cmsRead15Fixed16Number(io, &Matrix[8])) goto Error; + + + // Only operates on 3 channels + if ((InputChannels == 3) && !_cmsMAT3isIdentity((cmsMAT3*) Matrix)) { + + if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, cmsStageAllocMatrix(self ->ContextID, 3, 3, Matrix, NULL))) + goto Error; + } + + if (!_cmsReadUInt16Number(io, &InputEntries)) goto Error; + if (!_cmsReadUInt16Number(io, &OutputEntries)) goto Error; + + if (InputEntries > 0x7FFF || OutputEntries > 0x7FFF) goto Error; + if (CLUTpoints == 1) goto Error; // Impossible value, 0 for no CLUT and then 2 at least + + // Get input tables + if (!Read16bitTables(self ->ContextID, io, NewLUT, InputChannels, InputEntries)) goto Error; + + // Get 3D CLUT + nTabSize = uipow(OutputChannels, CLUTpoints, InputChannels); + if (nTabSize == (cmsUInt32Number) -1) goto Error; + if (nTabSize > 0) { + + cmsUInt16Number *T; + + T = (cmsUInt16Number*) _cmsCalloc(self ->ContextID, nTabSize, sizeof(cmsUInt16Number)); + if (T == NULL) goto Error; + + if (!_cmsReadUInt16Array(io, nTabSize, T)) { + _cmsFree(self ->ContextID, T); + goto Error; + } + + if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, cmsStageAllocCLut16bit(self ->ContextID, CLUTpoints, InputChannels, OutputChannels, T))) { + _cmsFree(self ->ContextID, T); + goto Error; + } + _cmsFree(self ->ContextID, T); + } + + + // Get output tables + if (!Read16bitTables(self ->ContextID, io, NewLUT, OutputChannels, OutputEntries)) goto Error; + + *nItems = 1; + return NewLUT; + +Error: + if (NewLUT != NULL) cmsPipelineFree(NewLUT); + return NULL; + + cmsUNUSED_PARAMETER(SizeOfTag); +} + +// We only allow some specific MPE structures: Matrix plus prelin, plus clut, plus post-lin. +// Some empty defaults are created for missing parts + +static +cmsBool Type_LUT16_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) +{ + cmsUInt32Number nTabSize; + cmsPipeline* NewLUT = (cmsPipeline*) Ptr; + cmsStage* mpe; + _cmsStageToneCurvesData* PreMPE = NULL, *PostMPE = NULL; + _cmsStageMatrixData* MatMPE = NULL; + _cmsStageCLutData* clut = NULL; + int i, InputChannels, OutputChannels, clutPoints; + + // Disassemble the LUT into components. + mpe = NewLUT -> Elements; + if (mpe != NULL && mpe ->Type == cmsSigMatrixElemType) { + + MatMPE = (_cmsStageMatrixData*) mpe ->Data; + mpe = mpe -> Next; + } + + + if (mpe != NULL && mpe ->Type == cmsSigCurveSetElemType) { + PreMPE = (_cmsStageToneCurvesData*) mpe ->Data; + mpe = mpe -> Next; + } + + if (mpe != NULL && mpe ->Type == cmsSigCLutElemType) { + clut = (_cmsStageCLutData*) mpe -> Data; + mpe = mpe ->Next; + } + + if (mpe != NULL && mpe ->Type == cmsSigCurveSetElemType) { + PostMPE = (_cmsStageToneCurvesData*) mpe ->Data; + mpe = mpe -> Next; + } + + // That should be all + if (mpe != NULL) { + cmsSignalError(mpe->ContextID, cmsERROR_UNKNOWN_EXTENSION, "LUT is not suitable to be saved as LUT16"); + return FALSE; + } + + InputChannels = cmsPipelineInputChannels(NewLUT); + OutputChannels = cmsPipelineOutputChannels(NewLUT); + + if (clut == NULL) + clutPoints = 0; + else + clutPoints = clut->Params->nSamples[0]; + + if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) InputChannels)) return FALSE; + if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) OutputChannels)) return FALSE; + if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) clutPoints)) return FALSE; + if (!_cmsWriteUInt8Number(io, 0)) return FALSE; // Padding + + + if (MatMPE != NULL) { + + if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[0])) return FALSE; + if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[1])) return FALSE; + if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[2])) return FALSE; + if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[3])) return FALSE; + if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[4])) return FALSE; + if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[5])) return FALSE; + if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[6])) return FALSE; + if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[7])) return FALSE; + if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[8])) return FALSE; + } + else { + + if (!_cmsWrite15Fixed16Number(io, 1)) return FALSE; + if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE; + if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE; + if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE; + if (!_cmsWrite15Fixed16Number(io, 1)) return FALSE; + if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE; + if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE; + if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE; + if (!_cmsWrite15Fixed16Number(io, 1)) return FALSE; + } + + + if (PreMPE != NULL) { + if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) PreMPE ->TheCurves[0]->nEntries)) return FALSE; + } else { + if (!_cmsWriteUInt16Number(io, 2)) return FALSE; + } + + if (PostMPE != NULL) { + if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) PostMPE ->TheCurves[0]->nEntries)) return FALSE; + } else { + if (!_cmsWriteUInt16Number(io, 2)) return FALSE; + + } + + // The prelinearization table + + if (PreMPE != NULL) { + if (!Write16bitTables(self ->ContextID, io, PreMPE)) return FALSE; + } + else { + for (i=0; i < InputChannels; i++) { + + if (!_cmsWriteUInt16Number(io, 0)) return FALSE; + if (!_cmsWriteUInt16Number(io, 0xffff)) return FALSE; + } + } + + nTabSize = uipow(OutputChannels, clutPoints, InputChannels); + if (nTabSize == (cmsUInt32Number) -1) return FALSE; + if (nTabSize > 0) { + // The 3D CLUT. + if (clut != NULL) { + if (!_cmsWriteUInt16Array(io, nTabSize, clut->Tab.T)) return FALSE; + } + } + + // The postlinearization table + if (PostMPE != NULL) { + if (!Write16bitTables(self ->ContextID, io, PostMPE)) return FALSE; + } + else { + for (i=0; i < OutputChannels; i++) { + + if (!_cmsWriteUInt16Number(io, 0)) return FALSE; + if (!_cmsWriteUInt16Number(io, 0xffff)) return FALSE; + } + } + + return TRUE; + + cmsUNUSED_PARAMETER(nItems); +} + +static +void* Type_LUT16_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) +{ + return (void*) cmsPipelineDup((cmsPipeline*) Ptr); + + cmsUNUSED_PARAMETER(n); + cmsUNUSED_PARAMETER(self); +} + +static +void Type_LUT16_Free(struct _cms_typehandler_struct* self, void* Ptr) +{ + cmsPipelineFree((cmsPipeline*) Ptr); + return; + + cmsUNUSED_PARAMETER(self); +} + + +// ******************************************************************************** +// Type cmsSigLutAToBType +// ******************************************************************************** + + +// V4 stuff. Read matrix for LutAtoB and LutBtoA + +static +cmsStage* ReadMatrix(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number Offset) +{ + cmsFloat64Number dMat[3*3]; + cmsFloat64Number dOff[3]; + cmsStage* Mat; + + // Go to address + if (!io -> Seek(io, Offset)) return NULL; + + // Read the Matrix + if (!_cmsRead15Fixed16Number(io, &dMat[0])) return NULL; + if (!_cmsRead15Fixed16Number(io, &dMat[1])) return NULL; + if (!_cmsRead15Fixed16Number(io, &dMat[2])) return NULL; + if (!_cmsRead15Fixed16Number(io, &dMat[3])) return NULL; + if (!_cmsRead15Fixed16Number(io, &dMat[4])) return NULL; + if (!_cmsRead15Fixed16Number(io, &dMat[5])) return NULL; + if (!_cmsRead15Fixed16Number(io, &dMat[6])) return NULL; + if (!_cmsRead15Fixed16Number(io, &dMat[7])) return NULL; + if (!_cmsRead15Fixed16Number(io, &dMat[8])) return NULL; + + if (!_cmsRead15Fixed16Number(io, &dOff[0])) return NULL; + if (!_cmsRead15Fixed16Number(io, &dOff[1])) return NULL; + if (!_cmsRead15Fixed16Number(io, &dOff[2])) return NULL; + + Mat = cmsStageAllocMatrix(self ->ContextID, 3, 3, dMat, dOff); + + return Mat; +} + + + + +// V4 stuff. Read CLUT part for LutAtoB and LutBtoA + +static +cmsStage* ReadCLUT(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number Offset, int InputChannels, int OutputChannels) +{ + cmsUInt8Number gridPoints8[cmsMAXCHANNELS]; // Number of grid points in each dimension. + cmsUInt32Number GridPoints[cmsMAXCHANNELS], i; + cmsUInt8Number Precision; + cmsStage* CLUT; + _cmsStageCLutData* Data; + + if (!io -> Seek(io, Offset)) return NULL; + if (io -> Read(io, gridPoints8, cmsMAXCHANNELS, 1) != 1) return NULL; + + + for (i=0; i < cmsMAXCHANNELS; i++) { + + if (gridPoints8[i] == 1) return NULL; // Impossible value, 0 for no CLUT and then 2 at least + GridPoints[i] = gridPoints8[i]; + } + + if (!_cmsReadUInt8Number(io, &Precision)) return NULL; + + if (!_cmsReadUInt8Number(io, NULL)) return NULL; + if (!_cmsReadUInt8Number(io, NULL)) return NULL; + if (!_cmsReadUInt8Number(io, NULL)) return NULL; + + CLUT = cmsStageAllocCLut16bitGranular(self ->ContextID, GridPoints, InputChannels, OutputChannels, NULL); + if (CLUT == NULL) return NULL; + + Data = (_cmsStageCLutData*) CLUT ->Data; + + // Precision can be 1 or 2 bytes + if (Precision == 1) { + + cmsUInt8Number v; + + for (i=0; i < Data ->nEntries; i++) { + + if (io ->Read(io, &v, sizeof(cmsUInt8Number), 1) != 1) return NULL; + Data ->Tab.T[i] = FROM_8_TO_16(v); + } + + } + else + if (Precision == 2) { + + if (!_cmsReadUInt16Array(io, Data->nEntries, Data ->Tab.T)) return NULL; + } + else { + cmsSignalError(self ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown precision of '%d'", Precision); + return NULL; + } + + + return CLUT; +} + +static +cmsToneCurve* ReadEmbeddedCurve(struct _cms_typehandler_struct* self, cmsIOHANDLER* io) +{ + cmsTagTypeSignature BaseType; + cmsUInt32Number nItems; + + BaseType = _cmsReadTypeBase(io); + switch (BaseType) { + + case cmsSigCurveType: + return (cmsToneCurve*) Type_Curve_Read(self, io, &nItems, 0); + + case cmsSigParametricCurveType: + return (cmsToneCurve*) Type_ParametricCurve_Read(self, io, &nItems, 0); + + default: + { + char String[5]; + + _cmsTagSignature2String(String, (cmsTagSignature) BaseType); + cmsSignalError(self ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown curve type '%s'", String); + } + return NULL; + } +} + + +// Read a set of curves from specific offset +static +cmsStage* ReadSetOfCurves(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number Offset, cmsUInt32Number nCurves) +{ + cmsToneCurve* Curves[cmsMAXCHANNELS]; + cmsUInt32Number i; + cmsStage* Lin = NULL; + + if (nCurves > cmsMAXCHANNELS) return FALSE; + + if (!io -> Seek(io, Offset)) return FALSE; + + for (i=0; i < nCurves; i++) + Curves[i] = NULL; + + for (i=0; i < nCurves; i++) { + + Curves[i] = ReadEmbeddedCurve(self, io); + if (Curves[i] == NULL) goto Error; + if (!_cmsReadAlignment(io)) goto Error; + + } + + Lin = cmsStageAllocToneCurves(self ->ContextID, nCurves, Curves); + +Error: + for (i=0; i < nCurves; i++) + cmsFreeToneCurve(Curves[i]); + + return Lin; +} + + +// LutAtoB type + +// This structure represents a colour transform. The type contains up to five processing +// elements which are stored in the AtoBTag tag in the following order: a set of one +// dimensional curves, a 3 by 3 matrix with offset terms, a set of one dimensional curves, +// a multidimensional lookup table, and a set of one dimensional output curves. +// Data are processed using these elements via the following sequence: +// +//("A" curves) -> (multidimensional lookup table - CLUT) -> ("M" curves) -> (matrix) -> ("B" curves). +// +/* +It is possible to use any or all of these processing elements. At least one processing element +must be included.Only the following combinations are allowed: + +B +M - Matrix - B +A - CLUT - B +A - CLUT - M - Matrix - B + +*/ + +static +void* Type_LUTA2B_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) +{ + cmsUInt32Number BaseOffset; + cmsUInt8Number inputChan; // Number of input channels + cmsUInt8Number outputChan; // Number of output channels + cmsUInt32Number offsetB; // Offset to first "B" curve + cmsUInt32Number offsetMat; // Offset to matrix + cmsUInt32Number offsetM; // Offset to first "M" curve + cmsUInt32Number offsetC; // Offset to CLUT + cmsUInt32Number offsetA; // Offset to first "A" curve + cmsPipeline* NewLUT = NULL; + + + BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase); + + if (!_cmsReadUInt8Number(io, &inputChan)) return NULL; + if (!_cmsReadUInt8Number(io, &outputChan)) return NULL; + + if (!_cmsReadUInt16Number(io, NULL)) return NULL; + + if (!_cmsReadUInt32Number(io, &offsetB)) return NULL; + if (!_cmsReadUInt32Number(io, &offsetMat)) return NULL; + if (!_cmsReadUInt32Number(io, &offsetM)) return NULL; + if (!_cmsReadUInt32Number(io, &offsetC)) return NULL; + if (!_cmsReadUInt32Number(io, &offsetA)) return NULL; + + // Allocates an empty LUT + NewLUT = cmsPipelineAlloc(self ->ContextID, inputChan, outputChan); + if (NewLUT == NULL) return NULL; + + if (offsetA!= 0) { + if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetA, inputChan))) + goto Error; + } + + if (offsetC != 0) { + if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadCLUT(self, io, BaseOffset + offsetC, inputChan, outputChan))) + goto Error; + } + + if (offsetM != 0) { + if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetM, outputChan))) + goto Error; + } + + if (offsetMat != 0) { + if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadMatrix(self, io, BaseOffset + offsetMat))) + goto Error; + } + + if (offsetB != 0) { + if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetB, outputChan))) + goto Error; + } + + *nItems = 1; + return NewLUT; +Error: + cmsPipelineFree(NewLUT); + return NULL; + + cmsUNUSED_PARAMETER(SizeOfTag); +} + +// Write a set of curves +static +cmsBool WriteMatrix(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsStage* mpe) +{ + _cmsStageMatrixData* m = (_cmsStageMatrixData*) mpe -> Data; + + // Write the Matrix + if (!_cmsWrite15Fixed16Number(io, m -> Double[0])) return FALSE; + if (!_cmsWrite15Fixed16Number(io, m -> Double[1])) return FALSE; + if (!_cmsWrite15Fixed16Number(io, m -> Double[2])) return FALSE; + if (!_cmsWrite15Fixed16Number(io, m -> Double[3])) return FALSE; + if (!_cmsWrite15Fixed16Number(io, m -> Double[4])) return FALSE; + if (!_cmsWrite15Fixed16Number(io, m -> Double[5])) return FALSE; + if (!_cmsWrite15Fixed16Number(io, m -> Double[6])) return FALSE; + if (!_cmsWrite15Fixed16Number(io, m -> Double[7])) return FALSE; + if (!_cmsWrite15Fixed16Number(io, m -> Double[8])) return FALSE; + + if (m ->Offset != NULL) { + + if (!_cmsWrite15Fixed16Number(io, m -> Offset[0])) return FALSE; + if (!_cmsWrite15Fixed16Number(io, m -> Offset[1])) return FALSE; + if (!_cmsWrite15Fixed16Number(io, m -> Offset[2])) return FALSE; + } + else { + if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE; + if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE; + if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE; + + } + + + return TRUE; + + cmsUNUSED_PARAMETER(self); +} + + +// Write a set of curves +static +cmsBool WriteSetOfCurves(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsTagTypeSignature Type, cmsStage* mpe) +{ + cmsUInt32Number i, n; + cmsTagTypeSignature CurrentType; + cmsToneCurve** Curves; + + + n = cmsStageOutputChannels(mpe); + Curves = _cmsStageGetPtrToCurveSet(mpe); + + for (i=0; i < n; i++) { + + // If this is a table-based curve, use curve type even on V4 + CurrentType = Type; + + if ((Curves[i] ->nSegments == 0)|| + ((Curves[i]->nSegments == 2) && (Curves[i] ->Segments[1].Type == 0)) ) + CurrentType = cmsSigCurveType; + else + if (Curves[i] ->Segments[0].Type < 0) + CurrentType = cmsSigCurveType; + + if (!_cmsWriteTypeBase(io, CurrentType)) return FALSE; + + switch (CurrentType) { + + case cmsSigCurveType: + if (!Type_Curve_Write(self, io, Curves[i], 1)) return FALSE; + break; + + case cmsSigParametricCurveType: + if (!Type_ParametricCurve_Write(self, io, Curves[i], 1)) return FALSE; + break; + + default: + { + char String[5]; + + _cmsTagSignature2String(String, (cmsTagSignature) Type); + cmsSignalError(self ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown curve type '%s'", String); + } + return FALSE; + } + + if (!_cmsWriteAlignment(io)) return FALSE; + } + + + return TRUE; +} + + +static +cmsBool WriteCLUT(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt8Number Precision, cmsStage* mpe) +{ + cmsUInt8Number gridPoints[cmsMAXCHANNELS]; // Number of grid points in each dimension. + cmsUInt32Number i; + _cmsStageCLutData* CLUT = ( _cmsStageCLutData*) mpe -> Data; + + if (CLUT ->HasFloatValues) { + cmsSignalError(self ->ContextID, cmsERROR_NOT_SUITABLE, "Cannot save floating point data, CLUT are 8 or 16 bit only"); + return FALSE; + } + + memset(gridPoints, 0, sizeof(gridPoints)); + for (i=0; i < (cmsUInt32Number) CLUT ->Params ->nInputs; i++) + gridPoints[i] = (cmsUInt8Number) CLUT ->Params ->nSamples[i]; + + if (!io -> Write(io, cmsMAXCHANNELS*sizeof(cmsUInt8Number), gridPoints)) return FALSE; + + if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) Precision)) return FALSE; + if (!_cmsWriteUInt8Number(io, 0)) return FALSE; + if (!_cmsWriteUInt8Number(io, 0)) return FALSE; + if (!_cmsWriteUInt8Number(io, 0)) return FALSE; + + // Precision can be 1 or 2 bytes + if (Precision == 1) { + + for (i=0; i < CLUT->nEntries; i++) { + + if (!_cmsWriteUInt8Number(io, FROM_16_TO_8(CLUT->Tab.T[i]))) return FALSE; + } + } + else + if (Precision == 2) { + + if (!_cmsWriteUInt16Array(io, CLUT->nEntries, CLUT ->Tab.T)) return FALSE; + } + else { + cmsSignalError(self ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown precision of '%d'", Precision); + return FALSE; + } + + if (!_cmsWriteAlignment(io)) return FALSE; + + return TRUE; +} + + + + +static +cmsBool Type_LUTA2B_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) +{ + cmsPipeline* Lut = (cmsPipeline*) Ptr; + int inputChan, outputChan; + cmsStage *A = NULL, *B = NULL, *M = NULL; + cmsStage * Matrix = NULL; + cmsStage * CLUT = NULL; + cmsUInt32Number offsetB = 0, offsetMat = 0, offsetM = 0, offsetC = 0, offsetA = 0; + cmsUInt32Number BaseOffset, DirectoryPos, CurrentPos; + + // Get the base for all offsets + BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase); + + if (Lut ->Elements != NULL) + if (!cmsPipelineCheckAndRetreiveStages(Lut, 1, cmsSigCurveSetElemType, &B)) + if (!cmsPipelineCheckAndRetreiveStages(Lut, 3, cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType, &M, &Matrix, &B)) + if (!cmsPipelineCheckAndRetreiveStages(Lut, 3, cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType, &A, &CLUT, &B)) + if (!cmsPipelineCheckAndRetreiveStages(Lut, 5, cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType, + cmsSigMatrixElemType, cmsSigCurveSetElemType, &A, &CLUT, &M, &Matrix, &B)) { + + cmsSignalError(self->ContextID, cmsERROR_NOT_SUITABLE, "LUT is not suitable to be saved as LutAToB"); + return FALSE; + } + + // Get input, output channels + inputChan = cmsPipelineInputChannels(Lut); + outputChan = cmsPipelineOutputChannels(Lut); + + // Write channel count + if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) inputChan)) return FALSE; + if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) outputChan)) return FALSE; + if (!_cmsWriteUInt16Number(io, 0)) return FALSE; + + // Keep directory to be filled latter + DirectoryPos = io ->Tell(io); + + // Write the directory + if (!_cmsWriteUInt32Number(io, 0)) return FALSE; + if (!_cmsWriteUInt32Number(io, 0)) return FALSE; + if (!_cmsWriteUInt32Number(io, 0)) return FALSE; + if (!_cmsWriteUInt32Number(io, 0)) return FALSE; + if (!_cmsWriteUInt32Number(io, 0)) return FALSE; + + if (A != NULL) { + + offsetA = io ->Tell(io) - BaseOffset; + if (!WriteSetOfCurves(self, io, cmsSigParametricCurveType, A)) return FALSE; + } + + if (CLUT != NULL) { + offsetC = io ->Tell(io) - BaseOffset; + if (!WriteCLUT(self, io, Lut ->SaveAs8Bits ? 1 : 2, CLUT)) return FALSE; + + } + if (M != NULL) { + + offsetM = io ->Tell(io) - BaseOffset; + if (!WriteSetOfCurves(self, io, cmsSigParametricCurveType, M)) return FALSE; + } + + if (Matrix != NULL) { + offsetMat = io ->Tell(io) - BaseOffset; + if (!WriteMatrix(self, io, Matrix)) return FALSE; + } + + if (B != NULL) { + + offsetB = io ->Tell(io) - BaseOffset; + if (!WriteSetOfCurves(self, io, cmsSigParametricCurveType, B)) return FALSE; + } + + CurrentPos = io ->Tell(io); + + if (!io ->Seek(io, DirectoryPos)) return FALSE; + + if (!_cmsWriteUInt32Number(io, offsetB)) return FALSE; + if (!_cmsWriteUInt32Number(io, offsetMat)) return FALSE; + if (!_cmsWriteUInt32Number(io, offsetM)) return FALSE; + if (!_cmsWriteUInt32Number(io, offsetC)) return FALSE; + if (!_cmsWriteUInt32Number(io, offsetA)) return FALSE; + + if (!io ->Seek(io, CurrentPos)) return FALSE; + + return TRUE; + + cmsUNUSED_PARAMETER(nItems); +} + + +static +void* Type_LUTA2B_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) +{ + return (void*) cmsPipelineDup((cmsPipeline*) Ptr); + + cmsUNUSED_PARAMETER(n); + cmsUNUSED_PARAMETER(self); +} + +static +void Type_LUTA2B_Free(struct _cms_typehandler_struct* self, void* Ptr) +{ + cmsPipelineFree((cmsPipeline*) Ptr); + return; + + cmsUNUSED_PARAMETER(self); +} + + +// LutBToA type + +static +void* Type_LUTB2A_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) +{ + cmsUInt8Number inputChan; // Number of input channels + cmsUInt8Number outputChan; // Number of output channels + cmsUInt32Number BaseOffset; // Actual position in file + cmsUInt32Number offsetB; // Offset to first "B" curve + cmsUInt32Number offsetMat; // Offset to matrix + cmsUInt32Number offsetM; // Offset to first "M" curve + cmsUInt32Number offsetC; // Offset to CLUT + cmsUInt32Number offsetA; // Offset to first "A" curve + cmsPipeline* NewLUT = NULL; + + + BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase); + + if (!_cmsReadUInt8Number(io, &inputChan)) return NULL; + if (!_cmsReadUInt8Number(io, &outputChan)) return NULL; + + // Padding + if (!_cmsReadUInt16Number(io, NULL)) return NULL; + + if (!_cmsReadUInt32Number(io, &offsetB)) return NULL; + if (!_cmsReadUInt32Number(io, &offsetMat)) return NULL; + if (!_cmsReadUInt32Number(io, &offsetM)) return NULL; + if (!_cmsReadUInt32Number(io, &offsetC)) return NULL; + if (!_cmsReadUInt32Number(io, &offsetA)) return NULL; + + // Allocates an empty LUT + NewLUT = cmsPipelineAlloc(self ->ContextID, inputChan, outputChan); + if (NewLUT == NULL) return NULL; + + if (offsetB != 0) { + if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetB, inputChan))) + goto Error; + } + + if (offsetMat != 0) { + if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadMatrix(self, io, BaseOffset + offsetMat))) + goto Error; + } + + if (offsetM != 0) { + if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetM, inputChan))) + goto Error; + } + + if (offsetC != 0) { + if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadCLUT(self, io, BaseOffset + offsetC, inputChan, outputChan))) + goto Error; + } + + if (offsetA!= 0) { + if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetA, outputChan))) + goto Error; + } + + *nItems = 1; + return NewLUT; +Error: + cmsPipelineFree(NewLUT); + return NULL; + + cmsUNUSED_PARAMETER(SizeOfTag); +} + + +/* +B +B - Matrix - M +B - CLUT - A +B - Matrix - M - CLUT - A +*/ + +static +cmsBool Type_LUTB2A_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) +{ + cmsPipeline* Lut = (cmsPipeline*) Ptr; + int inputChan, outputChan; + cmsStage *A = NULL, *B = NULL, *M = NULL; + cmsStage *Matrix = NULL; + cmsStage *CLUT = NULL; + cmsUInt32Number offsetB = 0, offsetMat = 0, offsetM = 0, offsetC = 0, offsetA = 0; + cmsUInt32Number BaseOffset, DirectoryPos, CurrentPos; + + + BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase); + + if (!cmsPipelineCheckAndRetreiveStages(Lut, 1, cmsSigCurveSetElemType, &B)) + if (!cmsPipelineCheckAndRetreiveStages(Lut, 3, cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType, &B, &Matrix, &M)) + if (!cmsPipelineCheckAndRetreiveStages(Lut, 3, cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType, &B, &CLUT, &A)) + if (!cmsPipelineCheckAndRetreiveStages(Lut, 5, cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType, + cmsSigCLutElemType, cmsSigCurveSetElemType, &B, &Matrix, &M, &CLUT, &A)) { + cmsSignalError(self->ContextID, cmsERROR_NOT_SUITABLE, "LUT is not suitable to be saved as LutBToA"); + return FALSE; + } + + inputChan = cmsPipelineInputChannels(Lut); + outputChan = cmsPipelineOutputChannels(Lut); + + if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) inputChan)) return FALSE; + if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) outputChan)) return FALSE; + if (!_cmsWriteUInt16Number(io, 0)) return FALSE; + + DirectoryPos = io ->Tell(io); + + if (!_cmsWriteUInt32Number(io, 0)) return FALSE; + if (!_cmsWriteUInt32Number(io, 0)) return FALSE; + if (!_cmsWriteUInt32Number(io, 0)) return FALSE; + if (!_cmsWriteUInt32Number(io, 0)) return FALSE; + if (!_cmsWriteUInt32Number(io, 0)) return FALSE; + + if (A != NULL) { + + offsetA = io ->Tell(io) - BaseOffset; + if (!WriteSetOfCurves(self, io, cmsSigParametricCurveType, A)) return FALSE; + } + + if (CLUT != NULL) { + offsetC = io ->Tell(io) - BaseOffset; + if (!WriteCLUT(self, io, Lut ->SaveAs8Bits ? 1 : 2, CLUT)) return FALSE; + + } + if (M != NULL) { + + offsetM = io ->Tell(io) - BaseOffset; + if (!WriteSetOfCurves(self, io, cmsSigParametricCurveType, M)) return FALSE; + } + + if (Matrix != NULL) { + offsetMat = io ->Tell(io) - BaseOffset; + if (!WriteMatrix(self, io, Matrix)) return FALSE; + } + + if (B != NULL) { + + offsetB = io ->Tell(io) - BaseOffset; + if (!WriteSetOfCurves(self, io, cmsSigParametricCurveType, B)) return FALSE; + } + + CurrentPos = io ->Tell(io); + + if (!io ->Seek(io, DirectoryPos)) return FALSE; + + if (!_cmsWriteUInt32Number(io, offsetB)) return FALSE; + if (!_cmsWriteUInt32Number(io, offsetMat)) return FALSE; + if (!_cmsWriteUInt32Number(io, offsetM)) return FALSE; + if (!_cmsWriteUInt32Number(io, offsetC)) return FALSE; + if (!_cmsWriteUInt32Number(io, offsetA)) return FALSE; + + if (!io ->Seek(io, CurrentPos)) return FALSE; + + return TRUE; + + cmsUNUSED_PARAMETER(nItems); +} + + + +static +void* Type_LUTB2A_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) +{ + return (void*) cmsPipelineDup((cmsPipeline*) Ptr); + + cmsUNUSED_PARAMETER(n); + cmsUNUSED_PARAMETER(self); +} + +static +void Type_LUTB2A_Free(struct _cms_typehandler_struct* self, void* Ptr) +{ + cmsPipelineFree((cmsPipeline*) Ptr); + return; + + cmsUNUSED_PARAMETER(self); +} + + + +// ******************************************************************************** +// Type cmsSigColorantTableType +// ******************************************************************************** +/* +The purpose of this tag is to identify the colorants used in the profile by a +unique name and set of XYZ or L*a*b* values to give the colorant an unambiguous +value. The first colorant listed is the colorant of the first device channel of +a lut tag. The second colorant listed is the colorant of the second device channel +of a lut tag, and so on. +*/ + +static +void *Type_ColorantTable_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) +{ + cmsUInt32Number i, Count; + cmsNAMEDCOLORLIST* List; + char Name[34]; + cmsUInt16Number PCS[3]; + + + if (!_cmsReadUInt32Number(io, &Count)) return NULL; + + if (Count > cmsMAXCHANNELS) { + cmsSignalError(self->ContextID, cmsERROR_RANGE, "Too many colorants '%d'", Count); + return NULL; + } + + List = cmsAllocNamedColorList(self ->ContextID, Count, 0, "", ""); + for (i=0; i < Count; i++) { + + if (io ->Read(io, Name, 32, 1) != 1) goto Error; + Name[33] = 0; + + if (!_cmsReadUInt16Array(io, 3, PCS)) goto Error; + + if (!cmsAppendNamedColor(List, Name, PCS, NULL)) goto Error; + + } + + *nItems = 1; + return List; + +Error: + *nItems = 0; + cmsFreeNamedColorList(List); + return NULL; + + cmsUNUSED_PARAMETER(SizeOfTag); +} + + + +// Saves a colorant table. It is using the named color structure for simplicity sake +static +cmsBool Type_ColorantTable_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) +{ + cmsNAMEDCOLORLIST* NamedColorList = (cmsNAMEDCOLORLIST*) Ptr; + int i, nColors; + + nColors = cmsNamedColorCount(NamedColorList); + + if (!_cmsWriteUInt32Number(io, nColors)) return FALSE; + + for (i=0; i < nColors; i++) { + + char root[33]; + cmsUInt16Number PCS[3]; + + if (!cmsNamedColorInfo(NamedColorList, i, root, NULL, NULL, PCS, NULL)) return 0; + root[32] = 0; + + if (!io ->Write(io, 32, root)) return FALSE; + if (!_cmsWriteUInt16Array(io, 3, PCS)) return FALSE; + } + + return TRUE; + + cmsUNUSED_PARAMETER(nItems); + cmsUNUSED_PARAMETER(self); +} + + +static +void* Type_ColorantTable_Dup(struct _cms_typehandler_struct* self, const void* Ptr, cmsUInt32Number n) +{ + cmsNAMEDCOLORLIST* nc = (cmsNAMEDCOLORLIST*) Ptr; + return (void*) cmsDupNamedColorList(nc); + + cmsUNUSED_PARAMETER(n); + cmsUNUSED_PARAMETER(self); +} + + +static +void Type_ColorantTable_Free(struct _cms_typehandler_struct* self, void* Ptr) +{ + cmsFreeNamedColorList((cmsNAMEDCOLORLIST*) Ptr); + return; + + cmsUNUSED_PARAMETER(self); +} + + +// ******************************************************************************** +// Type cmsSigNamedColor2Type +// ******************************************************************************** +// +//The namedColor2Type is a count value and array of structures that provide color +//coordinates for 7-bit ASCII color names. For each named color, a PCS and optional +//device representation of the color are given. Both representations are 16-bit values. +//The device representation corresponds to the header’s “color space of data” field. +//This representation should be consistent with the “number of device components” +//field in the namedColor2Type. If this field is 0, device coordinates are not provided. +//The PCS representation corresponds to the header’s PCS field. The PCS representation +//is always provided. Color names are fixed-length, 32-byte fields including null +//termination. In order to maintain maximum portability, it is strongly recommended +//that special characters of the 7-bit ASCII set not be used. + +static +void *Type_NamedColor_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) +{ + + cmsUInt32Number vendorFlag; // Bottom 16 bits for ICC use + cmsUInt32Number count; // Count of named colors + cmsUInt32Number nDeviceCoords; // Num of device coordinates + char prefix[32]; // Prefix for each color name + char suffix[32]; // Suffix for each color name + cmsNAMEDCOLORLIST* v; + cmsUInt32Number i; + + + *nItems = 0; + if (!_cmsReadUInt32Number(io, &vendorFlag)) return NULL; + if (!_cmsReadUInt32Number(io, &count)) return NULL; + if (!_cmsReadUInt32Number(io, &nDeviceCoords)) return NULL; + + if (io -> Read(io, prefix, 32, 1) != 1) return NULL; + if (io -> Read(io, suffix, 32, 1) != 1) return NULL; + + prefix[31] = suffix[31] = 0; + + v = cmsAllocNamedColorList(self ->ContextID, count, nDeviceCoords, prefix, suffix); + if (v == NULL) { + cmsSignalError(self->ContextID, cmsERROR_RANGE, "Too many named colors '%d'", count); + return NULL; + } + + if (nDeviceCoords > cmsMAXCHANNELS) { + cmsSignalError(self->ContextID, cmsERROR_RANGE, "Too many device coordinates '%d'", nDeviceCoords); + return 0; + } + for (i=0; i < count; i++) { + + cmsUInt16Number PCS[3]; + cmsUInt16Number Colorant[cmsMAXCHANNELS]; + char Root[33]; + + memset(Colorant, 0, sizeof(Colorant)); + if (io -> Read(io, Root, 32, 1) != 1) return NULL; + if (!_cmsReadUInt16Array(io, 3, PCS)) goto Error; + if (!_cmsReadUInt16Array(io, nDeviceCoords, Colorant)) goto Error; + + if (!cmsAppendNamedColor(v, Root, PCS, Colorant)) goto Error; + } + + *nItems = 1; + return (void*) v ; + +Error: + cmsFreeNamedColorList(v); + return NULL; + + cmsUNUSED_PARAMETER(SizeOfTag); +} + + +// Saves a named color list into a named color profile +static +cmsBool Type_NamedColor_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) +{ + cmsNAMEDCOLORLIST* NamedColorList = (cmsNAMEDCOLORLIST*) Ptr; + char prefix[32]; // Prefix for each color name + char suffix[32]; // Suffix for each color name + int i, nColors; + + nColors = cmsNamedColorCount(NamedColorList); + + if (!_cmsWriteUInt32Number(io, 0)) return FALSE; + if (!_cmsWriteUInt32Number(io, nColors)) return FALSE; + if (!_cmsWriteUInt32Number(io, NamedColorList ->ColorantCount)) return FALSE; + + strncpy(prefix, (const char*) NamedColorList->Prefix, 32); + strncpy(suffix, (const char*) NamedColorList->Suffix, 32); + + suffix[31] = prefix[31] = 0; + + if (!io ->Write(io, 32, prefix)) return FALSE; + if (!io ->Write(io, 32, suffix)) return FALSE; + + for (i=0; i < nColors; i++) { + + cmsUInt16Number PCS[3]; + cmsUInt16Number Colorant[cmsMAXCHANNELS]; + char Root[33]; + + if (!cmsNamedColorInfo(NamedColorList, i, Root, NULL, NULL, PCS, Colorant)) return 0; + if (!io ->Write(io, 32 , Root)) return FALSE; + if (!_cmsWriteUInt16Array(io, 3, PCS)) return FALSE; + if (!_cmsWriteUInt16Array(io, NamedColorList ->ColorantCount, Colorant)) return FALSE; + } + + return TRUE; + + cmsUNUSED_PARAMETER(nItems); + cmsUNUSED_PARAMETER(self); +} + +static +void* Type_NamedColor_Dup(struct _cms_typehandler_struct* self, const void* Ptr, cmsUInt32Number n) +{ + cmsNAMEDCOLORLIST* nc = (cmsNAMEDCOLORLIST*) Ptr; + + return (void*) cmsDupNamedColorList(nc); + + cmsUNUSED_PARAMETER(n); + cmsUNUSED_PARAMETER(self); +} + + +static +void Type_NamedColor_Free(struct _cms_typehandler_struct* self, void* Ptr) +{ + cmsFreeNamedColorList((cmsNAMEDCOLORLIST*) Ptr); + return; + + cmsUNUSED_PARAMETER(self); +} + + +// ******************************************************************************** +// Type cmsSigProfileSequenceDescType +// ******************************************************************************** + +// This type is an array of structures, each of which contains information from the +// header fields and tags from the original profiles which were combined to create +// the final profile. The order of the structures is the order in which the profiles +// were combined and includes a structure for the final profile. This provides a +// description of the profile sequence from source to destination, +// typically used with the DeviceLink profile. + +static +cmsBool ReadEmbeddedText(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsMLU** mlu, cmsUInt32Number SizeOfTag) +{ + cmsTagTypeSignature BaseType; + cmsUInt32Number nItems; + + BaseType = _cmsReadTypeBase(io); + + switch (BaseType) { + + case cmsSigTextType: + if (*mlu) cmsMLUfree(*mlu); + *mlu = (cmsMLU*)Type_Text_Read(self, io, &nItems, SizeOfTag); + return (*mlu != NULL); + + case cmsSigTextDescriptionType: + if (*mlu) cmsMLUfree(*mlu); + *mlu = (cmsMLU*) Type_Text_Description_Read(self, io, &nItems, SizeOfTag); + return (*mlu != NULL); + + /* + TBD: Size is needed for MLU, and we have no idea on which is the available size + */ + + case cmsSigMultiLocalizedUnicodeType: + if (*mlu) cmsMLUfree(*mlu); + *mlu = (cmsMLU*) Type_MLU_Read(self, io, &nItems, SizeOfTag); + return (*mlu != NULL); + + default: return FALSE; + } +} + + +static +void *Type_ProfileSequenceDesc_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) +{ + cmsSEQ* OutSeq; + cmsUInt32Number i, Count; + + *nItems = 0; + + if (!_cmsReadUInt32Number(io, &Count)) return NULL; + + if (SizeOfTag < sizeof(cmsUInt32Number)) return NULL; + SizeOfTag -= sizeof(cmsUInt32Number); + + + OutSeq = cmsAllocProfileSequenceDescription(self ->ContextID, Count); + if (OutSeq == NULL) return NULL; + + OutSeq ->n = Count; + + // Get structures as well + + for (i=0; i < Count; i++) { + + cmsPSEQDESC* sec = &OutSeq -> seq[i]; + + if (!_cmsReadUInt32Number(io, &sec ->deviceMfg)) goto Error; + if (SizeOfTag < sizeof(cmsUInt32Number)) goto Error; + SizeOfTag -= sizeof(cmsUInt32Number); + + if (!_cmsReadUInt32Number(io, &sec ->deviceModel)) goto Error; + if (SizeOfTag < sizeof(cmsUInt32Number)) goto Error; + SizeOfTag -= sizeof(cmsUInt32Number); + + if (!_cmsReadUInt64Number(io, &sec ->attributes)) goto Error; + if (SizeOfTag < sizeof(cmsUInt64Number)) goto Error; + SizeOfTag -= sizeof(cmsUInt64Number); + + if (!_cmsReadUInt32Number(io, (cmsUInt32Number *)&sec ->technology)) goto Error; + if (SizeOfTag < sizeof(cmsUInt32Number)) goto Error; + SizeOfTag -= sizeof(cmsUInt32Number); + + if (!ReadEmbeddedText(self, io, &sec ->Manufacturer, SizeOfTag)) goto Error; + if (!ReadEmbeddedText(self, io, &sec ->Model, SizeOfTag)) goto Error; + } + + *nItems = 1; + return OutSeq; + +Error: + cmsFreeProfileSequenceDescription(OutSeq); + return NULL; +} + + +// Aux--Embed a text description type. It can be of type text description or multilocalized unicode +// and it depends of the version number passed on cmsTagDescriptor structure instead of stack +static +cmsBool SaveDescription(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsMLU* Text) +{ + if (self ->ICCVersion < 0x4000000) { + + if (!_cmsWriteTypeBase(io, cmsSigTextDescriptionType)) return FALSE; + return Type_Text_Description_Write(self, io, Text, 1); + } + else { + if (!_cmsWriteTypeBase(io, cmsSigMultiLocalizedUnicodeType)) return FALSE; + return Type_MLU_Write(self, io, Text, 1); + } +} + + +static +cmsBool Type_ProfileSequenceDesc_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) +{ + cmsSEQ* Seq = (cmsSEQ*) Ptr; + cmsUInt32Number i; + + if (!_cmsWriteUInt32Number(io, Seq->n)) return FALSE; + + for (i=0; i < Seq ->n; i++) { + + cmsPSEQDESC* sec = &Seq -> seq[i]; + + if (!_cmsWriteUInt32Number(io, sec ->deviceMfg)) return FALSE; + if (!_cmsWriteUInt32Number(io, sec ->deviceModel)) return FALSE; + if (!_cmsWriteUInt64Number(io, &sec ->attributes)) return FALSE; + if (!_cmsWriteUInt32Number(io, sec ->technology)) return FALSE; + + if (!SaveDescription(self, io, sec ->Manufacturer)) return FALSE; + if (!SaveDescription(self, io, sec ->Model)) return FALSE; + } + + return TRUE; + + cmsUNUSED_PARAMETER(nItems); +} + + +static +void* Type_ProfileSequenceDesc_Dup(struct _cms_typehandler_struct* self, const void* Ptr, cmsUInt32Number n) +{ + return (void*) cmsDupProfileSequenceDescription((cmsSEQ*) Ptr); + + cmsUNUSED_PARAMETER(n); + cmsUNUSED_PARAMETER(self); +} + +static +void Type_ProfileSequenceDesc_Free(struct _cms_typehandler_struct* self, void* Ptr) +{ + cmsFreeProfileSequenceDescription((cmsSEQ*) Ptr); + return; + + cmsUNUSED_PARAMETER(self); +} + + +// ******************************************************************************** +// Type cmsSigProfileSequenceIdType +// ******************************************************************************** +/* +In certain workflows using ICC Device Link Profiles, it is necessary to identify the +original profiles that were combined to create the Device Link Profile. +This type is an array of structures, each of which contains information for +identification of a profile used in a sequence +*/ + + +static +cmsBool ReadSeqID(struct _cms_typehandler_struct* self, + cmsIOHANDLER* io, + void* Cargo, + cmsUInt32Number n, + cmsUInt32Number SizeOfTag) +{ + cmsSEQ* OutSeq = (cmsSEQ*) Cargo; + cmsPSEQDESC* seq = &OutSeq ->seq[n]; + + if (io -> Read(io, seq ->ProfileID.ID8, 16, 1) != 1) return FALSE; + if (!ReadEmbeddedText(self, io, &seq ->Description, SizeOfTag)) return FALSE; + + return TRUE; +} + + + +static +void *Type_ProfileSequenceId_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) +{ + cmsSEQ* OutSeq; + cmsUInt32Number Count; + cmsUInt32Number BaseOffset; + + *nItems = 0; + + // Get actual position as a basis for element offsets + BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase); + + // Get table count + if (!_cmsReadUInt32Number(io, &Count)) return NULL; + SizeOfTag -= sizeof(cmsUInt32Number); + + // Allocate an empty structure + OutSeq = cmsAllocProfileSequenceDescription(self ->ContextID, Count); + if (OutSeq == NULL) return NULL; + + + // Read the position table + if (!ReadPositionTable(self, io, Count, BaseOffset, OutSeq, ReadSeqID)) { + + cmsFreeProfileSequenceDescription(OutSeq); + return NULL; + } + + // Success + *nItems = 1; + return OutSeq; + +} + + +static +cmsBool WriteSeqID(struct _cms_typehandler_struct* self, + cmsIOHANDLER* io, + void* Cargo, + cmsUInt32Number n, + cmsUInt32Number SizeOfTag) +{ + cmsSEQ* Seq = (cmsSEQ*) Cargo; + + if (!io ->Write(io, 16, Seq ->seq[n].ProfileID.ID8)) return FALSE; + + // Store here the MLU + if (!SaveDescription(self, io, Seq ->seq[n].Description)) return FALSE; + + return TRUE; + + cmsUNUSED_PARAMETER(SizeOfTag); +} + +static +cmsBool Type_ProfileSequenceId_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) +{ + cmsSEQ* Seq = (cmsSEQ*) Ptr; + cmsUInt32Number BaseOffset; + + // Keep the base offset + BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase); + + // This is the table count + if (!_cmsWriteUInt32Number(io, Seq ->n)) return FALSE; + + // This is the position table and content + if (!WritePositionTable(self, io, 0, Seq ->n, BaseOffset, Seq, WriteSeqID)) return FALSE; + + return TRUE; + + cmsUNUSED_PARAMETER(nItems); +} + +static +void* Type_ProfileSequenceId_Dup(struct _cms_typehandler_struct* self, const void* Ptr, cmsUInt32Number n) +{ + return (void*) cmsDupProfileSequenceDescription((cmsSEQ*) Ptr); + + cmsUNUSED_PARAMETER(n); + cmsUNUSED_PARAMETER(self); +} + +static +void Type_ProfileSequenceId_Free(struct _cms_typehandler_struct* self, void* Ptr) +{ + cmsFreeProfileSequenceDescription((cmsSEQ*) Ptr); + return; + + cmsUNUSED_PARAMETER(self); +} + + +// ******************************************************************************** +// Type cmsSigUcrBgType +// ******************************************************************************** +/* +This type contains curves representing the under color removal and black +generation and a text string which is a general description of the method used +for the ucr/bg. +*/ + +static +void *Type_UcrBg_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) +{ + cmsUcrBg* n = (cmsUcrBg*) _cmsMallocZero(self ->ContextID, sizeof(cmsUcrBg)); + cmsUInt32Number CountUcr, CountBg; + char* ASCIIString; + + *nItems = 0; + if (n == NULL) return NULL; + + // First curve is Under color removal + if (!_cmsReadUInt32Number(io, &CountUcr)) return NULL; + if (SizeOfTag < sizeof(cmsUInt32Number)) return NULL; + SizeOfTag -= sizeof(cmsUInt32Number); + + n ->Ucr = cmsBuildTabulatedToneCurve16(self ->ContextID, CountUcr, NULL); + if (n ->Ucr == NULL) return NULL; + + if (!_cmsReadUInt16Array(io, CountUcr, n ->Ucr->Table16)) return NULL; + if (SizeOfTag < sizeof(cmsUInt32Number)) return NULL; + SizeOfTag -= CountUcr * sizeof(cmsUInt16Number); + + // Second curve is Black generation + if (!_cmsReadUInt32Number(io, &CountBg)) return NULL; + if (SizeOfTag < sizeof(cmsUInt32Number)) return NULL; + SizeOfTag -= sizeof(cmsUInt32Number); + + n ->Bg = cmsBuildTabulatedToneCurve16(self ->ContextID, CountBg, NULL); + if (n ->Bg == NULL) return NULL; + if (!_cmsReadUInt16Array(io, CountBg, n ->Bg->Table16)) return NULL; + if (SizeOfTag < CountBg * sizeof(cmsUInt16Number)) return NULL; + SizeOfTag -= CountBg * sizeof(cmsUInt16Number); + if (SizeOfTag == UINT_MAX) return NULL; + + // Now comes the text. The length is specified by the tag size + n ->Desc = cmsMLUalloc(self ->ContextID, 1); + if (n ->Desc == NULL) return NULL; + + ASCIIString = (char*) _cmsMalloc(self ->ContextID, SizeOfTag + 1); + if (io ->Read(io, ASCIIString, sizeof(char), SizeOfTag) != SizeOfTag) return NULL; + ASCIIString[SizeOfTag] = 0; + cmsMLUsetASCII(n ->Desc, cmsNoLanguage, cmsNoCountry, ASCIIString); + _cmsFree(self ->ContextID, ASCIIString); + + *nItems = 1; + return (void*) n; +} + +static +cmsBool Type_UcrBg_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) +{ + cmsUcrBg* Value = (cmsUcrBg*) Ptr; + cmsUInt32Number TextSize; + char* Text; + + // First curve is Under color removal + if (!_cmsWriteUInt32Number(io, Value ->Ucr ->nEntries)) return FALSE; + if (!_cmsWriteUInt16Array(io, Value ->Ucr ->nEntries, Value ->Ucr ->Table16)) return FALSE; + + // Then black generation + if (!_cmsWriteUInt32Number(io, Value ->Bg ->nEntries)) return FALSE; + if (!_cmsWriteUInt16Array(io, Value ->Bg ->nEntries, Value ->Bg ->Table16)) return FALSE; + + // Now comes the text. The length is specified by the tag size + TextSize = cmsMLUgetASCII(Value ->Desc, cmsNoLanguage, cmsNoCountry, NULL, 0); + Text = (char*) _cmsMalloc(self ->ContextID, TextSize); + if (cmsMLUgetASCII(Value ->Desc, cmsNoLanguage, cmsNoCountry, Text, TextSize) != TextSize) return FALSE; + + if (!io ->Write(io, TextSize, Text)) return FALSE; + _cmsFree(self ->ContextID, Text); + + return TRUE; + + cmsUNUSED_PARAMETER(nItems); +} + +static +void* Type_UcrBg_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) +{ + cmsUcrBg* Src = (cmsUcrBg*) Ptr; + cmsUcrBg* NewUcrBg = (cmsUcrBg*) _cmsMallocZero(self ->ContextID, sizeof(cmsUcrBg)); + + if (NewUcrBg == NULL) return NULL; + + NewUcrBg ->Bg = cmsDupToneCurve(Src ->Bg); + NewUcrBg ->Ucr = cmsDupToneCurve(Src ->Ucr); + NewUcrBg ->Desc = cmsMLUdup(Src ->Desc); + + return (void*) NewUcrBg; + + cmsUNUSED_PARAMETER(n); +} + +static +void Type_UcrBg_Free(struct _cms_typehandler_struct* self, void *Ptr) +{ + cmsUcrBg* Src = (cmsUcrBg*) Ptr; + + if (Src ->Ucr) cmsFreeToneCurve(Src ->Ucr); + if (Src ->Bg) cmsFreeToneCurve(Src ->Bg); + if (Src ->Desc) cmsMLUfree(Src ->Desc); + + _cmsFree(self ->ContextID, Ptr); +} + +// ******************************************************************************** +// Type cmsSigCrdInfoType +// ******************************************************************************** + +/* +This type contains the PostScript product name to which this profile corresponds +and the names of the companion CRDs. Recall that a single profile can generate +multiple CRDs. It is implemented as a MLU being the language code "PS" and then +country varies for each element: + + nm: PostScript product name + #0: Rendering intent 0 CRD name + #1: Rendering intent 1 CRD name + #2: Rendering intent 2 CRD name + #3: Rendering intent 3 CRD name +*/ + + + +// Auxiliar, read an string specified as count + string +static +cmsBool ReadCountAndSting(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsMLU* mlu, cmsUInt32Number* SizeOfTag, const char* Section) +{ + cmsUInt32Number Count; + char* Text; + + if (*SizeOfTag < sizeof(cmsUInt32Number)) return FALSE; + + if (!_cmsReadUInt32Number(io, &Count)) return FALSE; + + if (Count > UINT_MAX - sizeof(cmsUInt32Number)) return FALSE; + if (*SizeOfTag < Count + sizeof(cmsUInt32Number)) return FALSE; + + Text = (char*) _cmsMalloc(self ->ContextID, Count+1); + if (Text == NULL) return FALSE; + + if (io ->Read(io, Text, sizeof(cmsUInt8Number), Count) != Count) { + _cmsFree(self ->ContextID, Text); + return FALSE; + } + + Text[Count] = 0; + + cmsMLUsetASCII(mlu, "PS", Section, Text); + _cmsFree(self ->ContextID, Text); + + *SizeOfTag -= (Count + sizeof(cmsUInt32Number)); + return TRUE; +} + +static +cmsBool WriteCountAndSting(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsMLU* mlu, const char* Section) +{ + cmsUInt32Number TextSize; + char* Text; + + TextSize = cmsMLUgetASCII(mlu, "PS", Section, NULL, 0); + Text = (char*) _cmsMalloc(self ->ContextID, TextSize); + + if (!_cmsWriteUInt32Number(io, TextSize)) return FALSE; + + if (cmsMLUgetASCII(mlu, "PS", Section, Text, TextSize) == 0) return FALSE; + + if (!io ->Write(io, TextSize, Text)) return FALSE; + _cmsFree(self ->ContextID, Text); + + return TRUE; +} + +static +void *Type_CrdInfo_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) +{ + cmsMLU* mlu = cmsMLUalloc(self ->ContextID, 5); + + *nItems = 0; + if (!ReadCountAndSting(self, io, mlu, &SizeOfTag, "nm")) goto Error; + if (!ReadCountAndSting(self, io, mlu, &SizeOfTag, "#0")) goto Error; + if (!ReadCountAndSting(self, io, mlu, &SizeOfTag, "#1")) goto Error; + if (!ReadCountAndSting(self, io, mlu, &SizeOfTag, "#2")) goto Error; + if (!ReadCountAndSting(self, io, mlu, &SizeOfTag, "#3")) goto Error; + + *nItems = 1; + return (void*) mlu; + +Error: + cmsMLUfree(mlu); + return NULL; + +} + +static +cmsBool Type_CrdInfo_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) +{ + + cmsMLU* mlu = (cmsMLU*) Ptr; + + if (!WriteCountAndSting(self, io, mlu, "nm")) goto Error; + if (!WriteCountAndSting(self, io, mlu, "#0")) goto Error; + if (!WriteCountAndSting(self, io, mlu, "#1")) goto Error; + if (!WriteCountAndSting(self, io, mlu, "#2")) goto Error; + if (!WriteCountAndSting(self, io, mlu, "#3")) goto Error; + + return TRUE; + +Error: + return FALSE; + + cmsUNUSED_PARAMETER(nItems); +} + + +static +void* Type_CrdInfo_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) +{ + return (void*) cmsMLUdup((cmsMLU*) Ptr); + + cmsUNUSED_PARAMETER(n); + cmsUNUSED_PARAMETER(self); +} + +static +void Type_CrdInfo_Free(struct _cms_typehandler_struct* self, void *Ptr) +{ + cmsMLUfree((cmsMLU*) Ptr); + return; + + cmsUNUSED_PARAMETER(self); +} + +// ******************************************************************************** +// Type cmsSigScreeningType +// ******************************************************************************** +// +//The screeningType describes various screening parameters including screen +//frequency, screening angle, and spot shape. + +static +void *Type_Screening_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) +{ + cmsScreening* sc = NULL; + cmsUInt32Number i; + + sc = (cmsScreening*) _cmsMallocZero(self ->ContextID, sizeof(cmsScreening)); + if (sc == NULL) return NULL; + + *nItems = 0; + + if (!_cmsReadUInt32Number(io, &sc ->Flag)) goto Error; + if (!_cmsReadUInt32Number(io, &sc ->nChannels)) goto Error; + + if (sc ->nChannels > cmsMAXCHANNELS - 1) + sc ->nChannels = cmsMAXCHANNELS - 1; + + for (i=0; i < sc ->nChannels; i++) { + + if (!_cmsRead15Fixed16Number(io, &sc ->Channels[i].Frequency)) goto Error; + if (!_cmsRead15Fixed16Number(io, &sc ->Channels[i].ScreenAngle)) goto Error; + if (!_cmsReadUInt32Number(io, &sc ->Channels[i].SpotShape)) goto Error; + } + + + *nItems = 1; + + return (void*) sc; + +Error: + if (sc != NULL) + _cmsFree(self ->ContextID, sc); + + return NULL; + + cmsUNUSED_PARAMETER(SizeOfTag); +} + + +static +cmsBool Type_Screening_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) +{ + cmsScreening* sc = (cmsScreening* ) Ptr; + cmsUInt32Number i; + + if (!_cmsWriteUInt32Number(io, sc ->Flag)) return FALSE; + if (!_cmsWriteUInt32Number(io, sc ->nChannels)) return FALSE; + + for (i=0; i < sc ->nChannels; i++) { + + if (!_cmsWrite15Fixed16Number(io, sc ->Channels[i].Frequency)) return FALSE; + if (!_cmsWrite15Fixed16Number(io, sc ->Channels[i].ScreenAngle)) return FALSE; + if (!_cmsWriteUInt32Number(io, sc ->Channels[i].SpotShape)) return FALSE; + } + + return TRUE; + + cmsUNUSED_PARAMETER(nItems); + cmsUNUSED_PARAMETER(self); +} + + +static +void* Type_Screening_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) +{ + return _cmsDupMem(self ->ContextID, Ptr, sizeof(cmsScreening)); + + cmsUNUSED_PARAMETER(n); +} + + +static +void Type_Screening_Free(struct _cms_typehandler_struct* self, void* Ptr) +{ + _cmsFree(self ->ContextID, Ptr); +} + +// ******************************************************************************** +// Type cmsSigViewingConditionsType +// ******************************************************************************** +// +//This type represents a set of viewing condition parameters including: +//CIE ’absolute’ illuminant white point tristimulus values and CIE ’absolute’ +//surround tristimulus values. + +static +void *Type_ViewingConditions_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) +{ + cmsICCViewingConditions* vc = NULL; + + vc = (cmsICCViewingConditions*) _cmsMallocZero(self ->ContextID, sizeof(cmsICCViewingConditions)); + if (vc == NULL) return NULL; + + *nItems = 0; + + if (!_cmsReadXYZNumber(io, &vc ->IlluminantXYZ)) goto Error; + if (!_cmsReadXYZNumber(io, &vc ->SurroundXYZ)) goto Error; + if (!_cmsReadUInt32Number(io, &vc ->IlluminantType)) goto Error; + + *nItems = 1; + + return (void*) vc; + +Error: + if (vc != NULL) + _cmsFree(self ->ContextID, vc); + + return NULL; + + cmsUNUSED_PARAMETER(SizeOfTag); +} + + +static +cmsBool Type_ViewingConditions_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) +{ + cmsICCViewingConditions* sc = (cmsICCViewingConditions* ) Ptr; + + if (!_cmsWriteXYZNumber(io, &sc ->IlluminantXYZ)) return FALSE; + if (!_cmsWriteXYZNumber(io, &sc ->SurroundXYZ)) return FALSE; + if (!_cmsWriteUInt32Number(io, sc ->IlluminantType)) return FALSE; + + return TRUE; + + cmsUNUSED_PARAMETER(nItems); + cmsUNUSED_PARAMETER(self); +} + + +static +void* Type_ViewingConditions_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) +{ + return _cmsDupMem(self ->ContextID, Ptr, sizeof(cmsScreening)); + + cmsUNUSED_PARAMETER(n); +} + + +static +void Type_ViewingConditions_Free(struct _cms_typehandler_struct* self, void* Ptr) +{ + _cmsFree(self ->ContextID, Ptr); +} + + +// ******************************************************************************** +// Type cmsSigMultiProcessElementType +// ******************************************************************************** + + +static +void* GenericMPEdup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) +{ + return (void*) cmsStageDup((cmsStage*) Ptr); + + cmsUNUSED_PARAMETER(n); + cmsUNUSED_PARAMETER(self); +} + +static +void GenericMPEfree(struct _cms_typehandler_struct* self, void *Ptr) +{ + cmsStageFree((cmsStage*) Ptr); + return; + + cmsUNUSED_PARAMETER(self); +} + +// Each curve is stored in one or more curve segments, with break-points specified between curve segments. +// The first curve segment always starts at –Infinity, and the last curve segment always ends at +Infinity. The +// first and last curve segments shall be specified in terms of a formula, whereas the other segments shall be +// specified either in terms of a formula, or by a sampled curve. + + +// Read an embedded segmented curve +static +cmsToneCurve* ReadSegmentedCurve(struct _cms_typehandler_struct* self, cmsIOHANDLER* io) +{ + cmsCurveSegSignature ElementSig; + cmsUInt32Number i, j; + cmsUInt16Number nSegments; + cmsCurveSegment* Segments; + cmsToneCurve* Curve; + cmsFloat32Number PrevBreak = -1E22F; // - infinite + + // Take signature and channels for each element. + if (!_cmsReadUInt32Number(io, (cmsUInt32Number*) &ElementSig)) return NULL; + + // That should be a segmented curve + if (ElementSig != cmsSigSegmentedCurve) return NULL; + + if (!_cmsReadUInt32Number(io, NULL)) return NULL; + if (!_cmsReadUInt16Number(io, &nSegments)) return NULL; + if (!_cmsReadUInt16Number(io, NULL)) return NULL; + + if (nSegments < 1) return NULL; + Segments = (cmsCurveSegment*) _cmsCalloc(self ->ContextID, nSegments, sizeof(cmsCurveSegment)); + if (Segments == NULL) return NULL; + + // Read breakpoints + for (i=0; i < (cmsUInt32Number) nSegments - 1; i++) { + + Segments[i].x0 = PrevBreak; + if (!_cmsReadFloat32Number(io, &Segments[i].x1)) goto Error; + PrevBreak = Segments[i].x1; + } + + Segments[nSegments-1].x0 = PrevBreak; + Segments[nSegments-1].x1 = 1E22F; // A big cmsFloat32Number number + + // Read segments + for (i=0; i < nSegments; i++) { + + if (!_cmsReadUInt32Number(io, (cmsUInt32Number*) &ElementSig)) goto Error; + if (!_cmsReadUInt32Number(io, NULL)) goto Error; + + switch (ElementSig) { + + case cmsSigFormulaCurveSeg: { + + cmsUInt16Number Type; + cmsUInt32Number ParamsByType[] = {4, 5, 5 }; + + if (!_cmsReadUInt16Number(io, &Type)) goto Error; + if (!_cmsReadUInt16Number(io, NULL)) goto Error; + + Segments[i].Type = Type + 6; + if (Type > 2) goto Error; + + for (j=0; j < ParamsByType[Type]; j++) { + + cmsFloat32Number f; + if (!_cmsReadFloat32Number(io, &f)) goto Error; + Segments[i].Params[j] = f; + } + } + break; + + + case cmsSigSampledCurveSeg: { + cmsUInt32Number Count; + + if (!_cmsReadUInt32Number(io, &Count)) return NULL; + + Segments[i].nGridPoints = Count; + Segments[i].SampledPoints = (cmsFloat32Number*) _cmsCalloc(self ->ContextID, Count, sizeof(cmsFloat32Number)); + if (Segments[i].SampledPoints == NULL) goto Error; + + for (j=0; j < Count; j++) { + if (!_cmsReadFloat32Number(io, &Segments[i].SampledPoints[j])) goto Error; + } + } + break; + + default: + { + char String[5]; + + _cmsTagSignature2String(String, (cmsTagSignature) ElementSig); + cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown curve element type '%s' found.", String); + } + return NULL; + + } + } + + Curve = cmsBuildSegmentedToneCurve(self ->ContextID, nSegments, Segments); + + for (i=0; i < nSegments; i++) { + if (Segments[i].SampledPoints) _cmsFree(self ->ContextID, Segments[i].SampledPoints); + } + _cmsFree(self ->ContextID, Segments); + return Curve; + +Error: + if (Segments) _cmsFree(self ->ContextID, Segments); + return NULL; +} + + +static +cmsBool ReadMPECurve(struct _cms_typehandler_struct* self, + cmsIOHANDLER* io, + void* Cargo, + cmsUInt32Number n, + cmsUInt32Number SizeOfTag) +{ + cmsToneCurve** GammaTables = ( cmsToneCurve**) Cargo; + + GammaTables[n] = ReadSegmentedCurve(self, io); + return (GammaTables[n] != NULL); + + cmsUNUSED_PARAMETER(SizeOfTag); +} + +static +void *Type_MPEcurve_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) +{ + cmsStage* mpe = NULL; + cmsUInt16Number InputChans, OutputChans; + cmsUInt32Number i, BaseOffset; + cmsToneCurve** GammaTables; + + *nItems = 0; + + // Get actual position as a basis for element offsets + BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase); + + if (!_cmsReadUInt16Number(io, &InputChans)) return NULL; + if (!_cmsReadUInt16Number(io, &OutputChans)) return NULL; + + if (InputChans != OutputChans) return NULL; + + GammaTables = (cmsToneCurve**) _cmsCalloc(self ->ContextID, InputChans, sizeof(cmsToneCurve*)); + if (GammaTables == NULL) return NULL; + + if (ReadPositionTable(self, io, InputChans, BaseOffset, GammaTables, ReadMPECurve)) { + + mpe = cmsStageAllocToneCurves(self ->ContextID, InputChans, GammaTables); + } + else { + mpe = NULL; + } + + for (i=0; i < InputChans; i++) { + if (GammaTables[i]) cmsFreeToneCurve(GammaTables[i]); + } + + _cmsFree(self ->ContextID, GammaTables); + *nItems = (mpe != NULL) ? 1 : 0; + return mpe; + + cmsUNUSED_PARAMETER(SizeOfTag); +} + + +// Write a single segmented curve. NO CHECK IS PERFORMED ON VALIDITY +static +cmsBool WriteSegmentedCurve(cmsIOHANDLER* io, cmsToneCurve* g) +{ + cmsUInt32Number i, j; + cmsCurveSegment* Segments = g ->Segments; + cmsUInt32Number nSegments = g ->nSegments; + + if (!_cmsWriteUInt32Number(io, cmsSigSegmentedCurve)) goto Error; + if (!_cmsWriteUInt32Number(io, 0)) goto Error; + if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) nSegments)) goto Error; + if (!_cmsWriteUInt16Number(io, 0)) goto Error; + + // Write the break-points + for (i=0; i < nSegments - 1; i++) { + if (!_cmsWriteFloat32Number(io, Segments[i].x1)) goto Error; + } + + // Write the segments + for (i=0; i < g ->nSegments; i++) { + + cmsCurveSegment* ActualSeg = Segments + i; + + if (ActualSeg -> Type == 0) { + + // This is a sampled curve + if (!_cmsWriteUInt32Number(io, (cmsUInt32Number) cmsSigSampledCurveSeg)) goto Error; + if (!_cmsWriteUInt32Number(io, 0)) goto Error; + if (!_cmsWriteUInt32Number(io, ActualSeg -> nGridPoints)) goto Error; + + for (j=0; j < g ->Segments[i].nGridPoints; j++) { + if (!_cmsWriteFloat32Number(io, ActualSeg -> SampledPoints[j])) goto Error; + } + + } + else { + int Type; + cmsUInt32Number ParamsByType[] = { 4, 5, 5 }; + + // This is a formula-based + if (!_cmsWriteUInt32Number(io, (cmsUInt32Number) cmsSigFormulaCurveSeg)) goto Error; + if (!_cmsWriteUInt32Number(io, 0)) goto Error; + + // We only allow 1, 2 and 3 as types + Type = ActualSeg ->Type - 6; + if (Type > 2 || Type < 0) goto Error; + + if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) Type)) goto Error; + if (!_cmsWriteUInt16Number(io, 0)) goto Error; + + for (j=0; j < ParamsByType[Type]; j++) { + if (!_cmsWriteFloat32Number(io, (cmsFloat32Number) ActualSeg ->Params[j])) goto Error; + } + } + + // It seems there is no need to align. Code is here, and for safety commented out + // if (!_cmsWriteAlignment(io)) goto Error; + } + + return TRUE; + +Error: + return FALSE; +} + + +static +cmsBool WriteMPECurve(struct _cms_typehandler_struct* self, + cmsIOHANDLER* io, + void* Cargo, + cmsUInt32Number n, + cmsUInt32Number SizeOfTag) +{ + _cmsStageToneCurvesData* Curves = (_cmsStageToneCurvesData*) Cargo; + + return WriteSegmentedCurve(io, Curves ->TheCurves[n]); + + cmsUNUSED_PARAMETER(SizeOfTag); + cmsUNUSED_PARAMETER(self); +} + +// Write a curve, checking first for validity +static +cmsBool Type_MPEcurve_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) +{ + cmsUInt32Number BaseOffset; + cmsStage* mpe = (cmsStage*) Ptr; + _cmsStageToneCurvesData* Curves = (_cmsStageToneCurvesData*) mpe ->Data; + + BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase); + + // Write the header. Since those are curves, input and output channels are same + if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) mpe ->InputChannels)) return FALSE; + if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) mpe ->InputChannels)) return FALSE; + + if (!WritePositionTable(self, io, 0, + mpe ->InputChannels, BaseOffset, Curves, WriteMPECurve)) return FALSE; + + + return TRUE; + + cmsUNUSED_PARAMETER(nItems); +} + + + +// The matrix is organized as an array of PxQ+Q elements, where P is the number of input channels to the +// matrix, and Q is the number of output channels. The matrix elements are each float32Numbers. The array +// is organized as follows: +// array = [e11, e12, …, e1P, e21, e22, …, e2P, …, eQ1, eQ2, …, eQP, e1, e2, …, eQ] + +static +void *Type_MPEmatrix_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) +{ + cmsStage* mpe; + cmsUInt16Number InputChans, OutputChans; + cmsUInt32Number nElems, i; + cmsFloat64Number* Matrix; + cmsFloat64Number* Offsets; + + if (!_cmsReadUInt16Number(io, &InputChans)) return NULL; + if (!_cmsReadUInt16Number(io, &OutputChans)) return NULL; + + + nElems = InputChans * OutputChans; + + // Input and output chans may be ANY (up to 0xffff) + Matrix = (cmsFloat64Number*) _cmsCalloc(self ->ContextID, nElems, sizeof(cmsFloat64Number)); + if (Matrix == NULL) return NULL; + + Offsets = (cmsFloat64Number*) _cmsCalloc(self ->ContextID, OutputChans, sizeof(cmsFloat64Number)); + if (Offsets == NULL) { + + _cmsFree(self ->ContextID, Matrix); + return NULL; + } + + for (i=0; i < nElems; i++) { + + cmsFloat32Number v; + + if (!_cmsReadFloat32Number(io, &v)) return NULL; + Matrix[i] = v; + } + + + for (i=0; i < OutputChans; i++) { + + cmsFloat32Number v; + + if (!_cmsReadFloat32Number(io, &v)) return NULL; + Offsets[i] = v; + } + + + mpe = cmsStageAllocMatrix(self ->ContextID, OutputChans, InputChans, Matrix, Offsets); + _cmsFree(self ->ContextID, Matrix); + _cmsFree(self ->ContextID, Offsets); + + *nItems = 1; + + return mpe; + + cmsUNUSED_PARAMETER(SizeOfTag); +} + +static +cmsBool Type_MPEmatrix_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) +{ + cmsUInt32Number i, nElems; + cmsStage* mpe = (cmsStage*) Ptr; + _cmsStageMatrixData* Matrix = (_cmsStageMatrixData*) mpe ->Data; + + if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) mpe ->InputChannels)) return FALSE; + if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) mpe ->OutputChannels)) return FALSE; + + nElems = mpe ->InputChannels * mpe ->OutputChannels; + + for (i=0; i < nElems; i++) { + if (!_cmsWriteFloat32Number(io, (cmsFloat32Number) Matrix->Double[i])) return FALSE; + } + + + for (i=0; i < mpe ->OutputChannels; i++) { + + if (Matrix ->Offset == NULL) { + + if (!_cmsWriteFloat32Number(io, 0)) return FALSE; + } + else { + if (!_cmsWriteFloat32Number(io, (cmsFloat32Number) Matrix->Offset[i])) return FALSE; + } + } + + return TRUE; + + cmsUNUSED_PARAMETER(nItems); + cmsUNUSED_PARAMETER(self); +} + + + +static +void *Type_MPEclut_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) +{ + cmsStage* mpe = NULL; + cmsUInt16Number InputChans, OutputChans; + cmsUInt8Number Dimensions8[16]; + cmsUInt32Number i, nMaxGrids, GridPoints[MAX_INPUT_DIMENSIONS]; + _cmsStageCLutData* clut; + + if (!_cmsReadUInt16Number(io, &InputChans)) return NULL; + if (!_cmsReadUInt16Number(io, &OutputChans)) return NULL; + + if (InputChans == 0) goto Error; + if (OutputChans == 0) goto Error; + + if (io ->Read(io, Dimensions8, sizeof(cmsUInt8Number), 16) != 16) + goto Error; + + // Copy MAX_INPUT_DIMENSIONS at most. Expand to cmsUInt32Number + nMaxGrids = InputChans > MAX_INPUT_DIMENSIONS ? MAX_INPUT_DIMENSIONS : InputChans; + for (i=0; i < nMaxGrids; i++) GridPoints[i] = (cmsUInt32Number) Dimensions8[i]; + + // Allocate the true CLUT + mpe = cmsStageAllocCLutFloatGranular(self ->ContextID, GridPoints, InputChans, OutputChans, NULL); + if (mpe == NULL) goto Error; + + // Read the data + clut = (_cmsStageCLutData*) mpe ->Data; + for (i=0; i < clut ->nEntries; i++) { + + if (!_cmsReadFloat32Number(io, &clut ->Tab.TFloat[i])) goto Error; + } + + *nItems = 1; + return mpe; + +Error: + *nItems = 0; + if (mpe != NULL) cmsStageFree(mpe); + return NULL; + + cmsUNUSED_PARAMETER(SizeOfTag); +} + +// Write a CLUT in floating point +static +cmsBool Type_MPEclut_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) +{ + cmsUInt8Number Dimensions8[16]; + cmsUInt32Number i; + cmsStage* mpe = (cmsStage*) Ptr; + _cmsStageCLutData* clut = (_cmsStageCLutData*) mpe ->Data; + + // Check for maximum number of channels + if (mpe -> InputChannels > 15) return FALSE; + + // Only floats are supported in MPE + if (clut ->HasFloatValues == FALSE) return FALSE; + + if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) mpe ->InputChannels)) return FALSE; + if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) mpe ->OutputChannels)) return FALSE; + + memset(Dimensions8, 0, sizeof(Dimensions8)); + + for (i=0; i < mpe ->InputChannels; i++) + Dimensions8[i] = (cmsUInt8Number) clut ->Params ->nSamples[i]; + + if (!io ->Write(io, 16, Dimensions8)) return FALSE; + + for (i=0; i < clut ->nEntries; i++) { + + if (!_cmsWriteFloat32Number(io, clut ->Tab.TFloat[i])) return FALSE; + } + + return TRUE; + + cmsUNUSED_PARAMETER(nItems); + cmsUNUSED_PARAMETER(self); +} + + + +// This is the list of built-in MPE types +static _cmsTagTypeLinkedList SupportedMPEtypes[] = { + +{{ (cmsTagTypeSignature) cmsSigBAcsElemType, NULL, NULL, NULL, NULL, NULL, 0 }, &SupportedMPEtypes[1] }, // Ignore those elements for now +{{ (cmsTagTypeSignature) cmsSigEAcsElemType, NULL, NULL, NULL, NULL, NULL, 0 }, &SupportedMPEtypes[2] }, // (That's what the spec says) + +{TYPE_MPE_HANDLER((cmsTagTypeSignature) cmsSigCurveSetElemType, MPEcurve), &SupportedMPEtypes[3] }, +{TYPE_MPE_HANDLER((cmsTagTypeSignature) cmsSigMatrixElemType, MPEmatrix), &SupportedMPEtypes[4] }, +{TYPE_MPE_HANDLER((cmsTagTypeSignature) cmsSigCLutElemType, MPEclut), NULL }, +}; + +#define DEFAULT_MPE_TYPE_COUNT (sizeof(SupportedMPEtypes) / sizeof(_cmsTagTypeLinkedList)) + +static +cmsBool ReadMPEElem(struct _cms_typehandler_struct* self, + cmsIOHANDLER* io, + void* Cargo, + cmsUInt32Number n, + cmsUInt32Number SizeOfTag) +{ + cmsStageSignature ElementSig; + cmsTagTypeHandler* TypeHandler; + cmsUInt32Number nItems; + cmsPipeline *NewLUT = (cmsPipeline *) Cargo; + + // Take signature and channels for each element. + if (!_cmsReadUInt32Number(io, (cmsUInt32Number*) &ElementSig)) return FALSE; + + // The reserved placeholder + if (!_cmsReadUInt32Number(io, NULL)) return FALSE; + + // Read diverse MPE types + TypeHandler = GetHandler((cmsTagTypeSignature) ElementSig, SupportedMPEtypes); + if (TypeHandler == NULL) { + + char String[5]; + + _cmsTagSignature2String(String, (cmsTagSignature) ElementSig); + + // An unknown element was found. + cmsSignalError(self ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown MPE type '%s' found.", String); + return FALSE; + } + + // If no read method, just ignore the element (valid for cmsSigBAcsElemType and cmsSigEAcsElemType) + // Read the MPE. No size is given + if (TypeHandler ->ReadPtr != NULL) { + + // This is a real element which should be read and processed + if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, (cmsStage*) TypeHandler ->ReadPtr(self, io, &nItems, SizeOfTag))) + return FALSE; + } + + return TRUE; + + cmsUNUSED_PARAMETER(SizeOfTag); + cmsUNUSED_PARAMETER(n); +} + + +// This is the main dispatcher for MPE +static +void *Type_MPE_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) +{ + cmsUInt16Number InputChans, OutputChans; + cmsUInt32Number ElementCount; + cmsPipeline *NewLUT = NULL; + cmsUInt32Number BaseOffset; + + // Get actual position as a basis for element offsets + BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase); + + // Read channels and element count + if (!_cmsReadUInt16Number(io, &InputChans)) return NULL; + if (!_cmsReadUInt16Number(io, &OutputChans)) return NULL; + + // Allocates an empty LUT + NewLUT = cmsPipelineAlloc(self ->ContextID, InputChans, OutputChans); + if (NewLUT == NULL) return NULL; + + if (!_cmsReadUInt32Number(io, &ElementCount)) return NULL; + + if (!ReadPositionTable(self, io, ElementCount, BaseOffset, NewLUT, ReadMPEElem)) { + if (NewLUT != NULL) cmsPipelineFree(NewLUT); + *nItems = 0; + return NULL; + } + + // Success + *nItems = 1; + return NewLUT; + + cmsUNUSED_PARAMETER(SizeOfTag); +} + + + +// This one is a liitle bit more complex, so we don't use position tables this time. +static +cmsBool Type_MPE_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) +{ + cmsUInt32Number i, BaseOffset, DirectoryPos, CurrentPos; + int inputChan, outputChan; + cmsUInt32Number ElemCount; + cmsUInt32Number *ElementOffsets = NULL, *ElementSizes = NULL, Before; + cmsStageSignature ElementSig; + cmsPipeline* Lut = (cmsPipeline*) Ptr; + cmsStage* Elem = Lut ->Elements; + cmsTagTypeHandler* TypeHandler; + + BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase); + + inputChan = cmsPipelineInputChannels(Lut); + outputChan = cmsPipelineOutputChannels(Lut); + ElemCount = cmsPipelineStageCount(Lut); + + ElementOffsets = (cmsUInt32Number *) _cmsCalloc(self ->ContextID, ElemCount, sizeof(cmsUInt32Number)); + if (ElementOffsets == NULL) goto Error; + + ElementSizes = (cmsUInt32Number *) _cmsCalloc(self ->ContextID, ElemCount, sizeof(cmsUInt32Number)); + if (ElementSizes == NULL) goto Error; + + // Write the head + if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) inputChan)) goto Error; + if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) outputChan)) goto Error; + if (!_cmsWriteUInt32Number(io, (cmsUInt16Number) ElemCount)) goto Error; + + DirectoryPos = io ->Tell(io); + + // Write a fake directory to be filled latter on + for (i=0; i < ElemCount; i++) { + if (!_cmsWriteUInt32Number(io, 0)) goto Error; // Offset + if (!_cmsWriteUInt32Number(io, 0)) goto Error; // size + } + + // Write each single tag. Keep track of the size as well. + for (i=0; i < ElemCount; i++) { + + ElementOffsets[i] = io ->Tell(io) - BaseOffset; + + ElementSig = Elem ->Type; + + TypeHandler = GetHandler((cmsTagTypeSignature) ElementSig, SupportedMPEtypes); + if (TypeHandler == NULL) { + + char String[5]; + + _cmsTagSignature2String(String, (cmsTagSignature) ElementSig); + + // An unknow element was found. + cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Found unknown MPE type '%s'", String); + goto Error; + } + + if (!_cmsWriteUInt32Number(io, ElementSig)) goto Error; + if (!_cmsWriteUInt32Number(io, 0)) goto Error; + Before = io ->Tell(io); + if (!TypeHandler ->WritePtr(self, io, Elem, 1)) goto Error; + if (!_cmsWriteAlignment(io)) goto Error; + + ElementSizes[i] = io ->Tell(io) - Before; + + Elem = Elem ->Next; + } + + // Write the directory + CurrentPos = io ->Tell(io); + + if (!io ->Seek(io, DirectoryPos)) goto Error; + + for (i=0; i < ElemCount; i++) { + if (!_cmsWriteUInt32Number(io, ElementOffsets[i])) goto Error; + if (!_cmsWriteUInt32Number(io, ElementSizes[i])) goto Error; + } + + if (!io ->Seek(io, CurrentPos)) goto Error; + + if (ElementOffsets != NULL) _cmsFree(self ->ContextID, ElementOffsets); + if (ElementSizes != NULL) _cmsFree(self ->ContextID, ElementSizes); + return TRUE; + +Error: + if (ElementOffsets != NULL) _cmsFree(self ->ContextID, ElementOffsets); + if (ElementSizes != NULL) _cmsFree(self ->ContextID, ElementSizes); + return FALSE; + + cmsUNUSED_PARAMETER(nItems); +} + + +static +void* Type_MPE_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) +{ + return (void*) cmsPipelineDup((cmsPipeline*) Ptr); + + cmsUNUSED_PARAMETER(n); + cmsUNUSED_PARAMETER(self); +} + +static +void Type_MPE_Free(struct _cms_typehandler_struct* self, void *Ptr) +{ + cmsPipelineFree((cmsPipeline*) Ptr); + return; + + cmsUNUSED_PARAMETER(self); +} + + +// ******************************************************************************** +// Type cmsSigVcgtType +// ******************************************************************************** + + +#define cmsVideoCardGammaTableType 0 +#define cmsVideoCardGammaFormulaType 1 + +// Used internally +typedef struct { + double Gamma; + double Min; + double Max; +} _cmsVCGTGAMMA; + + +static +void *Type_vcgt_Read(struct _cms_typehandler_struct* self, + cmsIOHANDLER* io, + cmsUInt32Number* nItems, + cmsUInt32Number SizeOfTag) +{ + cmsUInt32Number TagType, n, i; + cmsToneCurve** Curves; + + *nItems = 0; + + // Read tag type + if (!_cmsReadUInt32Number(io, &TagType)) return NULL; + + // Allocate space for the array + Curves = ( cmsToneCurve**) _cmsCalloc(self ->ContextID, 3, sizeof(cmsToneCurve*)); + if (Curves == NULL) return NULL; + + // There are two possible flavors + switch (TagType) { + + // Gamma is stored as a table + case cmsVideoCardGammaTableType: + { + cmsUInt16Number nChannels, nElems, nBytes; + + // Check channel count, which should be 3 (we don't support monochrome this time) + if (!_cmsReadUInt16Number(io, &nChannels)) goto Error; + + if (nChannels != 3) { + cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported number of channels for VCGT '%d'", nChannels); + goto Error; + } + + // Get Table element count and bytes per element + if (!_cmsReadUInt16Number(io, &nElems)) goto Error; + if (!_cmsReadUInt16Number(io, &nBytes)) goto Error; + + // Adobe's quirk fixup. Fixing broken profiles... + if (nElems == 256 && nBytes == 1 && SizeOfTag == 1576) + nBytes = 2; + + + // Populate tone curves + for (n=0; n < 3; n++) { + + Curves[n] = cmsBuildTabulatedToneCurve16(self ->ContextID, nElems, NULL); + if (Curves[n] == NULL) goto Error; + + // On depending on byte depth + switch (nBytes) { + + // One byte, 0..255 + case 1: + for (i=0; i < nElems; i++) { + + cmsUInt8Number v; + + if (!_cmsReadUInt8Number(io, &v)) goto Error; + Curves[n] ->Table16[i] = FROM_8_TO_16(v); + } + break; + + // One word 0..65535 + case 2: + if (!_cmsReadUInt16Array(io, nElems, Curves[n]->Table16)) goto Error; + break; + + // Unsupported + default: + cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported bit depth for VCGT '%d'", nBytes * 8); + goto Error; + } + } // For all 3 channels + } + break; + + // In this case, gamma is stored as a formula + case cmsVideoCardGammaFormulaType: + { + _cmsVCGTGAMMA Colorant[3]; + + // Populate tone curves + for (n=0; n < 3; n++) { + + double Params[10]; + + if (!_cmsRead15Fixed16Number(io, &Colorant[n].Gamma)) goto Error; + if (!_cmsRead15Fixed16Number(io, &Colorant[n].Min)) goto Error; + if (!_cmsRead15Fixed16Number(io, &Colorant[n].Max)) goto Error; + + // Parametric curve type 5 is: + // Y = (aX + b)^Gamma + e | X >= d + // Y = cX + f | X < d + + // vcgt formula is: + // Y = (Max – Min) * (X ^ Gamma) + Min + + // So, the translation is + // a = (Max – Min) ^ ( 1 / Gamma) + // e = Min + // b=c=d=f=0 + + Params[0] = Colorant[n].Gamma; + Params[1] = pow((Colorant[n].Max - Colorant[n].Min), (1.0 / Colorant[n].Gamma)); + Params[2] = 0; + Params[3] = 0; + Params[4] = 0; + Params[5] = Colorant[n].Min; + Params[6] = 0; + + Curves[n] = cmsBuildParametricToneCurve(self ->ContextID, 5, Params); + if (Curves[n] == NULL) goto Error; + } + } + break; + + // Unsupported + default: + cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported tag type for VCGT '%d'", TagType); + goto Error; + } + + *nItems = 1; + return (void*) Curves; + +// Regret, free all resources +Error: + + cmsFreeToneCurveTriple(Curves); + _cmsFree(self ->ContextID, Curves); + return NULL; + + cmsUNUSED_PARAMETER(SizeOfTag); +} + + +// We don't support all flavors, only 16bits tables and formula +static +cmsBool Type_vcgt_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) +{ + cmsToneCurve** Curves = (cmsToneCurve**) Ptr; + cmsUInt32Number i, j; + + if (cmsGetToneCurveParametricType(Curves[0]) == 5 && + cmsGetToneCurveParametricType(Curves[1]) == 5 && + cmsGetToneCurveParametricType(Curves[2]) == 5) { + + if (!_cmsWriteUInt32Number(io, cmsVideoCardGammaFormulaType)) return FALSE; + + // Save parameters + for (i=0; i < 3; i++) { + + _cmsVCGTGAMMA v; + + v.Gamma = Curves[i] ->Segments[0].Params[0]; + v.Min = Curves[i] ->Segments[0].Params[5]; + v.Max = pow(Curves[i] ->Segments[0].Params[1], v.Gamma) + v.Min; + + if (!_cmsWrite15Fixed16Number(io, v.Gamma)) return FALSE; + if (!_cmsWrite15Fixed16Number(io, v.Min)) return FALSE; + if (!_cmsWrite15Fixed16Number(io, v.Max)) return FALSE; + } + } + + else { + + // Always store as a table of 256 words + if (!_cmsWriteUInt32Number(io, cmsVideoCardGammaTableType)) return FALSE; + if (!_cmsWriteUInt16Number(io, 3)) return FALSE; + if (!_cmsWriteUInt16Number(io, 256)) return FALSE; + if (!_cmsWriteUInt16Number(io, 2)) return FALSE; + + for (i=0; i < 3; i++) { + for (j=0; j < 256; j++) { + + cmsFloat32Number v = cmsEvalToneCurveFloat(Curves[i], (cmsFloat32Number) (j / 255.0)); + cmsUInt16Number n = _cmsQuickSaturateWord(v * 65535.0); + + if (!_cmsWriteUInt16Number(io, n)) return FALSE; + } + } + } + + return TRUE; + + cmsUNUSED_PARAMETER(self); + cmsUNUSED_PARAMETER(nItems); +} + +static +void* Type_vcgt_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) +{ + cmsToneCurve** OldCurves = (cmsToneCurve**) Ptr; + cmsToneCurve** NewCurves; + + NewCurves = ( cmsToneCurve**) _cmsCalloc(self ->ContextID, 3, sizeof(cmsToneCurve*)); + if (NewCurves == NULL) return NULL; + + NewCurves[0] = cmsDupToneCurve(OldCurves[0]); + NewCurves[1] = cmsDupToneCurve(OldCurves[1]); + NewCurves[2] = cmsDupToneCurve(OldCurves[2]); + + return (void*) NewCurves; + + cmsUNUSED_PARAMETER(n); +} + + +static +void Type_vcgt_Free(struct _cms_typehandler_struct* self, void* Ptr) +{ + cmsFreeToneCurveTriple((cmsToneCurve**) Ptr); + _cmsFree(self ->ContextID, Ptr); +} + + +// ******************************************************************************** +// Type cmsSigDictType +// ******************************************************************************** + +// Single column of the table can point to wchar or MLUC elements. Holds arrays of data +typedef struct { + cmsContext ContextID; + cmsUInt32Number *Offsets; + cmsUInt32Number *Sizes; +} _cmsDICelem; + +typedef struct { + _cmsDICelem Name, Value, DisplayName, DisplayValue; + +} _cmsDICarray; + +// Allocate an empty array element +static +cmsBool AllocElem(cmsContext ContextID, _cmsDICelem* e, cmsUInt32Number Count) +{ + e->Offsets = (cmsUInt32Number *) _cmsCalloc(ContextID, Count, sizeof(cmsUInt32Number)); + if (e->Offsets == NULL) return FALSE; + + e->Sizes = (cmsUInt32Number *) _cmsCalloc(ContextID, Count, sizeof(cmsUInt32Number)); + if (e->Sizes == NULL) { + + _cmsFree(ContextID, e -> Offsets); + return FALSE; + } + + e ->ContextID = ContextID; + return TRUE; +} + +// Free an array element +static +void FreeElem(_cmsDICelem* e) +{ + if (e ->Offsets != NULL) _cmsFree(e -> ContextID, e -> Offsets); + if (e ->Sizes != NULL) _cmsFree(e -> ContextID, e -> Sizes); + e->Offsets = e ->Sizes = NULL; +} + +// Get rid of whole array +static +void FreeArray( _cmsDICarray* a) +{ + if (a ->Name.Offsets != NULL) FreeElem(&a->Name); + if (a ->Value.Offsets != NULL) FreeElem(&a ->Value); + if (a ->DisplayName.Offsets != NULL) FreeElem(&a->DisplayName); + if (a ->DisplayValue.Offsets != NULL) FreeElem(&a ->DisplayValue); +} + + +// Allocate whole array +static +cmsBool AllocArray(cmsContext ContextID, _cmsDICarray* a, cmsUInt32Number Count, cmsUInt32Number Length) +{ + // Empty values + memset(a, 0, sizeof(_cmsDICarray)); + + // On depending on record size, create column arrays + if (!AllocElem(ContextID, &a ->Name, Count)) goto Error; + if (!AllocElem(ContextID, &a ->Value, Count)) goto Error; + + if (Length > 16) { + if (!AllocElem(ContextID, &a -> DisplayName, Count)) goto Error; + + } + if (Length > 24) { + if (!AllocElem(ContextID, &a ->DisplayValue, Count)) goto Error; + } + return TRUE; + +Error: + FreeArray(a); + return FALSE; +} + +// Read one element +static +cmsBool ReadOneElem(cmsIOHANDLER* io, _cmsDICelem* e, cmsUInt32Number i, cmsUInt32Number BaseOffset) +{ + if (!_cmsReadUInt32Number(io, &e->Offsets[i])) return FALSE; + if (!_cmsReadUInt32Number(io, &e ->Sizes[i])) return FALSE; + + // An offset of zero has special meaning and shal be preserved + if (e ->Offsets[i] > 0) + e ->Offsets[i] += BaseOffset; + return TRUE; +} + + +static +cmsBool ReadOffsetArray(cmsIOHANDLER* io, _cmsDICarray* a, cmsUInt32Number Count, cmsUInt32Number Length, cmsUInt32Number BaseOffset) +{ + cmsUInt32Number i; + + // Read column arrays + for (i=0; i < Count; i++) { + + if (!ReadOneElem(io, &a -> Name, i, BaseOffset)) return FALSE; + if (!ReadOneElem(io, &a -> Value, i, BaseOffset)) return FALSE; + + if (Length > 16) { + + if (!ReadOneElem(io, &a ->DisplayName, i, BaseOffset)) return FALSE; + + } + + if (Length > 24) { + + if (!ReadOneElem(io, & a -> DisplayValue, i, BaseOffset)) return FALSE; + } + } + return TRUE; +} + + +// Write one element +static +cmsBool WriteOneElem(cmsIOHANDLER* io, _cmsDICelem* e, cmsUInt32Number i) +{ + if (!_cmsWriteUInt32Number(io, e->Offsets[i])) return FALSE; + if (!_cmsWriteUInt32Number(io, e ->Sizes[i])) return FALSE; + + return TRUE; +} + +static +cmsBool WriteOffsetArray(cmsIOHANDLER* io, _cmsDICarray* a, cmsUInt32Number Count, cmsUInt32Number Length) +{ + cmsUInt32Number i; + + for (i=0; i < Count; i++) { + + if (!WriteOneElem(io, &a -> Name, i)) return FALSE; + if (!WriteOneElem(io, &a -> Value, i)) return FALSE; + + if (Length > 16) { + + if (!WriteOneElem(io, &a -> DisplayName, i)) return FALSE; + } + + if (Length > 24) { + + if (!WriteOneElem(io, &a -> DisplayValue, i)) return FALSE; + } + } + + return TRUE; +} + +static +cmsBool ReadOneWChar(cmsIOHANDLER* io, _cmsDICelem* e, cmsUInt32Number i, wchar_t ** wcstr) +{ + + cmsUInt32Number nChars; + + // Special case for undefined strings (see ICC Votable + // Proposal Submission, Dictionary Type and Metadata TAG Definition) + if (e -> Offsets[i] == 0) { + + *wcstr = NULL; + return TRUE; + } + + if (!io -> Seek(io, e -> Offsets[i])) return FALSE; + + nChars = e ->Sizes[i] / sizeof(cmsUInt16Number); + + + *wcstr = (wchar_t*) _cmsMallocZero(e ->ContextID, (nChars + 1) * sizeof(wchar_t)); + if (*wcstr == NULL) return FALSE; + + if (!_cmsReadWCharArray(io, nChars, *wcstr)) { + _cmsFree(e ->ContextID, *wcstr); + return FALSE; + } + + // End of string marker + (*wcstr)[nChars] = 0; + return TRUE; +} + +static +cmsUInt32Number mywcslen(const wchar_t *s) +{ + const wchar_t *p; + + p = s; + while (*p) + p++; + + return (cmsUInt32Number)(p - s); +} + +static +cmsBool WriteOneWChar(cmsIOHANDLER* io, _cmsDICelem* e, cmsUInt32Number i, const wchar_t * wcstr, cmsUInt32Number BaseOffset) +{ + cmsUInt32Number Before = io ->Tell(io); + cmsUInt32Number n; + + e ->Offsets[i] = Before - BaseOffset; + + if (wcstr == NULL) { + e ->Sizes[i] = 0; + e ->Offsets[i] = 0; + return TRUE; + } + + n = mywcslen(wcstr); + if (!_cmsWriteWCharArray(io, n, wcstr)) return FALSE; + + e ->Sizes[i] = io ->Tell(io) - Before; + return TRUE; +} + +static +cmsBool ReadOneMLUC(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, _cmsDICelem* e, cmsUInt32Number i, cmsMLU** mlu) +{ + cmsUInt32Number nItems = 0; + + // A way to get null MLUCs + if (e -> Offsets[i] == 0 || e ->Sizes[i] == 0) { + + *mlu = NULL; + return TRUE; + } + + if (!io -> Seek(io, e -> Offsets[i])) return FALSE; + + *mlu = (cmsMLU*) Type_MLU_Read(self, io, &nItems, e ->Sizes[i]); + return *mlu != NULL; +} + +static +cmsBool WriteOneMLUC(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, _cmsDICelem* e, cmsUInt32Number i, const cmsMLU* mlu, cmsUInt32Number BaseOffset) +{ + cmsUInt32Number Before; + + // Special case for undefined strings (see ICC Votable + // Proposal Submission, Dictionary Type and Metadata TAG Definition) + if (mlu == NULL) { + e ->Sizes[i] = 0; + e ->Offsets[i] = 0; + return TRUE; + } + + Before = io ->Tell(io); + e ->Offsets[i] = Before - BaseOffset; + + if (!Type_MLU_Write(self, io, (void*) mlu, 1)) return FALSE; + + e ->Sizes[i] = io ->Tell(io) - Before; + return TRUE; +} + + +static +void *Type_Dictionary_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) +{ + cmsHANDLE hDict; + cmsUInt32Number i, Count, Length; + cmsUInt32Number BaseOffset; + _cmsDICarray a; + wchar_t *NameWCS = NULL, *ValueWCS = NULL; + cmsMLU *DisplayNameMLU = NULL, *DisplayValueMLU=NULL; + cmsBool rc; + + *nItems = 0; + + // Get actual position as a basis for element offsets + BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase); + + // Get name-value record count + if (!_cmsReadUInt32Number(io, &Count)) return NULL; + SizeOfTag -= sizeof(cmsUInt32Number); + + // Get rec length + if (!_cmsReadUInt32Number(io, &Length)) return NULL; + SizeOfTag -= sizeof(cmsUInt32Number); + + // Check for valid lengths + if (Length != 16 && Length != 24 && Length != 32) { + cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown record length in dictionary '%d'", Length); + return NULL; + } + + // Creates an empty dictionary + hDict = cmsDictAlloc(self -> ContextID); + if (hDict == NULL) return NULL; + + // On depending on record size, create column arrays + if (!AllocArray(self -> ContextID, &a, Count, Length)) goto Error; + + // Read column arrays + if (!ReadOffsetArray(io, &a, Count, Length, BaseOffset)) goto Error; + + // Seek to each element and read it + for (i=0; i < Count; i++) { + + if (!ReadOneWChar(io, &a.Name, i, &NameWCS)) goto Error; + if (!ReadOneWChar(io, &a.Value, i, &ValueWCS)) goto Error; + + if (Length > 16) { + if (!ReadOneMLUC(self, io, &a.DisplayName, i, &DisplayNameMLU)) goto Error; + } + + if (Length > 24) { + if (!ReadOneMLUC(self, io, &a.DisplayValue, i, &DisplayValueMLU)) goto Error; + } + + if (NameWCS == NULL || ValueWCS == NULL) { + + cmsSignalError(self->ContextID, cmsERROR_CORRUPTION_DETECTED, "Bad dictionary Name/Value"); + rc = FALSE; + } + else { + + rc = cmsDictAddEntry(hDict, NameWCS, ValueWCS, DisplayNameMLU, DisplayValueMLU); + } + + if (NameWCS != NULL) _cmsFree(self ->ContextID, NameWCS); + if (ValueWCS != NULL) _cmsFree(self ->ContextID, ValueWCS); + if (DisplayNameMLU != NULL) cmsMLUfree(DisplayNameMLU); + if (DisplayValueMLU != NULL) cmsMLUfree(DisplayValueMLU); + + if (!rc) goto Error; + } + + FreeArray(&a); + *nItems = 1; + return (void*) hDict; + +Error: + FreeArray(&a); + cmsDictFree(hDict); + return NULL; +} + + +static +cmsBool Type_Dictionary_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) +{ + cmsHANDLE hDict = (cmsHANDLE) Ptr; + const cmsDICTentry* p; + cmsBool AnyName, AnyValue; + cmsUInt32Number i, Count, Length; + cmsUInt32Number DirectoryPos, CurrentPos, BaseOffset; + _cmsDICarray a; + + if (hDict == NULL) return FALSE; + + BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase); + + // Let's inspect the dictionary + Count = 0; AnyName = FALSE; AnyValue = FALSE; + for (p = cmsDictGetEntryList(hDict); p != NULL; p = cmsDictNextEntry(p)) { + + if (p ->DisplayName != NULL) AnyName = TRUE; + if (p ->DisplayValue != NULL) AnyValue = TRUE; + Count++; + } + + Length = 16; + if (AnyName) Length += 8; + if (AnyValue) Length += 8; + + if (!_cmsWriteUInt32Number(io, Count)) return FALSE; + if (!_cmsWriteUInt32Number(io, Length)) return FALSE; + + // Keep starting position of offsets table + DirectoryPos = io ->Tell(io); + + // Allocate offsets array + if (!AllocArray(self ->ContextID, &a, Count, Length)) goto Error; + + // Write a fake directory to be filled latter on + if (!WriteOffsetArray(io, &a, Count, Length)) goto Error; + + // Write each element. Keep track of the size as well. + p = cmsDictGetEntryList(hDict); + for (i=0; i < Count; i++) { + + if (!WriteOneWChar(io, &a.Name, i, p ->Name, BaseOffset)) goto Error; + if (!WriteOneWChar(io, &a.Value, i, p ->Value, BaseOffset)) goto Error; + + if (p ->DisplayName != NULL) { + if (!WriteOneMLUC(self, io, &a.DisplayName, i, p ->DisplayName, BaseOffset)) goto Error; + } + + if (p ->DisplayValue != NULL) { + if (!WriteOneMLUC(self, io, &a.DisplayValue, i, p ->DisplayValue, BaseOffset)) goto Error; + } + + p = cmsDictNextEntry(p); + } + + // Write the directory + CurrentPos = io ->Tell(io); + if (!io ->Seek(io, DirectoryPos)) goto Error; + + if (!WriteOffsetArray(io, &a, Count, Length)) goto Error; + + if (!io ->Seek(io, CurrentPos)) goto Error; + + FreeArray(&a); + return TRUE; + +Error: + FreeArray(&a); + return FALSE; + + cmsUNUSED_PARAMETER(nItems); +} + + +static +void* Type_Dictionary_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) +{ + return (void*) cmsDictDup((cmsHANDLE) Ptr); + + cmsUNUSED_PARAMETER(n); + cmsUNUSED_PARAMETER(self); +} + + +static +void Type_Dictionary_Free(struct _cms_typehandler_struct* self, void* Ptr) +{ + cmsDictFree((cmsHANDLE) Ptr); + cmsUNUSED_PARAMETER(self); +} + + +// ******************************************************************************** +// Type support main routines +// ******************************************************************************** + + +// This is the list of built-in types +static _cmsTagTypeLinkedList SupportedTagTypes[] = { + +{TYPE_HANDLER(cmsSigChromaticityType, Chromaticity), &SupportedTagTypes[1] }, +{TYPE_HANDLER(cmsSigColorantOrderType, ColorantOrderType), &SupportedTagTypes[2] }, +{TYPE_HANDLER(cmsSigS15Fixed16ArrayType, S15Fixed16), &SupportedTagTypes[3] }, +{TYPE_HANDLER(cmsSigU16Fixed16ArrayType, U16Fixed16), &SupportedTagTypes[4] }, +{TYPE_HANDLER(cmsSigTextType, Text), &SupportedTagTypes[5] }, +{TYPE_HANDLER(cmsSigTextDescriptionType, Text_Description), &SupportedTagTypes[6] }, +{TYPE_HANDLER(cmsSigCurveType, Curve), &SupportedTagTypes[7] }, +{TYPE_HANDLER(cmsSigParametricCurveType, ParametricCurve), &SupportedTagTypes[8] }, +{TYPE_HANDLER(cmsSigDateTimeType, DateTime), &SupportedTagTypes[9] }, +{TYPE_HANDLER(cmsSigLut8Type, LUT8), &SupportedTagTypes[10] }, +{TYPE_HANDLER(cmsSigLut16Type, LUT16), &SupportedTagTypes[11] }, +{TYPE_HANDLER(cmsSigColorantTableType, ColorantTable), &SupportedTagTypes[12] }, +{TYPE_HANDLER(cmsSigNamedColor2Type, NamedColor), &SupportedTagTypes[13] }, +{TYPE_HANDLER(cmsSigMultiLocalizedUnicodeType, MLU), &SupportedTagTypes[14] }, +{TYPE_HANDLER(cmsSigProfileSequenceDescType, ProfileSequenceDesc), &SupportedTagTypes[15] }, +{TYPE_HANDLER(cmsSigSignatureType, Signature), &SupportedTagTypes[16] }, +{TYPE_HANDLER(cmsSigMeasurementType, Measurement), &SupportedTagTypes[17] }, +{TYPE_HANDLER(cmsSigDataType, Data), &SupportedTagTypes[18] }, +{TYPE_HANDLER(cmsSigLutAtoBType, LUTA2B), &SupportedTagTypes[19] }, +{TYPE_HANDLER(cmsSigLutBtoAType, LUTB2A), &SupportedTagTypes[20] }, +{TYPE_HANDLER(cmsSigUcrBgType, UcrBg), &SupportedTagTypes[21] }, +{TYPE_HANDLER(cmsSigCrdInfoType, CrdInfo), &SupportedTagTypes[22] }, +{TYPE_HANDLER(cmsSigMultiProcessElementType, MPE), &SupportedTagTypes[23] }, +{TYPE_HANDLER(cmsSigScreeningType, Screening), &SupportedTagTypes[24] }, +{TYPE_HANDLER(cmsSigViewingConditionsType, ViewingConditions), &SupportedTagTypes[25] }, +{TYPE_HANDLER(cmsSigXYZType, XYZ), &SupportedTagTypes[26] }, +{TYPE_HANDLER(cmsCorbisBrokenXYZtype, XYZ), &SupportedTagTypes[27] }, +{TYPE_HANDLER(cmsMonacoBrokenCurveType, Curve), &SupportedTagTypes[28] }, +{TYPE_HANDLER(cmsSigProfileSequenceIdType, ProfileSequenceId), &SupportedTagTypes[29] }, +{TYPE_HANDLER(cmsSigDictType, Dictionary), &SupportedTagTypes[30] }, +{TYPE_HANDLER(cmsSigVcgtType, vcgt), NULL } +}; + +#define DEFAULT_TAG_TYPE_COUNT (sizeof(SupportedTagTypes) / sizeof(_cmsTagTypeLinkedList)) + +// Both kind of plug-ins share same structure +cmsBool _cmsRegisterTagTypePlugin(cmsContext id, cmsPluginBase* Data) +{ + return RegisterTypesPlugin(id, Data, SupportedTagTypes, DEFAULT_TAG_TYPE_COUNT); +} + +cmsBool _cmsRegisterMultiProcessElementPlugin(cmsContext id, cmsPluginBase* Data) +{ + return RegisterTypesPlugin(id, Data, SupportedMPEtypes, DEFAULT_MPE_TYPE_COUNT); +} + + +// Wrapper for tag types +cmsTagTypeHandler* _cmsGetTagTypeHandler(cmsTagTypeSignature sig) +{ + return GetHandler(sig, SupportedTagTypes); +} + +// ******************************************************************************** +// Tag support main routines +// ******************************************************************************** + +typedef struct _cmsTagLinkedList_st { + + cmsTagSignature Signature; + cmsTagDescriptor Descriptor; + struct _cmsTagLinkedList_st* Next; + +} _cmsTagLinkedList; + +// This is the list of built-in tags +static _cmsTagLinkedList SupportedTags[] = { + + { cmsSigAToB0Tag, { 1, 3, { cmsSigLut16Type, cmsSigLutAtoBType, cmsSigLut8Type}, DecideLUTtypeA2B}, &SupportedTags[1]}, + { cmsSigAToB1Tag, { 1, 3, { cmsSigLut16Type, cmsSigLutAtoBType, cmsSigLut8Type}, DecideLUTtypeA2B}, &SupportedTags[2]}, + { cmsSigAToB2Tag, { 1, 3, { cmsSigLut16Type, cmsSigLutAtoBType, cmsSigLut8Type}, DecideLUTtypeA2B}, &SupportedTags[3]}, + { cmsSigBToA0Tag, { 1, 3, { cmsSigLut16Type, cmsSigLutBtoAType, cmsSigLut8Type}, DecideLUTtypeB2A}, &SupportedTags[4]}, + { cmsSigBToA1Tag, { 1, 3, { cmsSigLut16Type, cmsSigLutBtoAType, cmsSigLut8Type}, DecideLUTtypeB2A}, &SupportedTags[5]}, + { cmsSigBToA2Tag, { 1, 3, { cmsSigLut16Type, cmsSigLutBtoAType, cmsSigLut8Type}, DecideLUTtypeB2A}, &SupportedTags[6]}, + + // Allow corbis and its broken XYZ type + { cmsSigRedColorantTag, { 1, 2, { cmsSigXYZType, cmsCorbisBrokenXYZtype }, DecideXYZtype}, &SupportedTags[7]}, + { cmsSigGreenColorantTag, { 1, 2, { cmsSigXYZType, cmsCorbisBrokenXYZtype }, DecideXYZtype}, &SupportedTags[8]}, + { cmsSigBlueColorantTag, { 1, 2, { cmsSigXYZType, cmsCorbisBrokenXYZtype }, DecideXYZtype}, &SupportedTags[9]}, + + { cmsSigRedTRCTag, { 1, 3, { cmsSigCurveType, cmsSigParametricCurveType, cmsMonacoBrokenCurveType }, DecideCurveType}, &SupportedTags[10]}, + { cmsSigGreenTRCTag, { 1, 3, { cmsSigCurveType, cmsSigParametricCurveType, cmsMonacoBrokenCurveType }, DecideCurveType}, &SupportedTags[11]}, + { cmsSigBlueTRCTag, { 1, 3, { cmsSigCurveType, cmsSigParametricCurveType, cmsMonacoBrokenCurveType }, DecideCurveType}, &SupportedTags[12]}, + + { cmsSigCalibrationDateTimeTag, { 1, 1, { cmsSigDateTimeType }, NULL}, &SupportedTags[13]}, + { cmsSigCharTargetTag, { 1, 1, { cmsSigTextType }, NULL}, &SupportedTags[14]}, + + { cmsSigChromaticAdaptationTag, { 9, 1, { cmsSigS15Fixed16ArrayType }, NULL}, &SupportedTags[15]}, + { cmsSigChromaticityTag, { 1, 1, { cmsSigChromaticityType }, NULL}, &SupportedTags[16]}, + { cmsSigColorantOrderTag, { 1, 1, { cmsSigColorantOrderType }, NULL}, &SupportedTags[17]}, + { cmsSigColorantTableTag, { 1, 1, { cmsSigColorantTableType }, NULL}, &SupportedTags[18]}, + { cmsSigColorantTableOutTag, { 1, 1, { cmsSigColorantTableType }, NULL}, &SupportedTags[19]}, + + { cmsSigCopyrightTag, { 1, 3, { cmsSigTextType, cmsSigMultiLocalizedUnicodeType, cmsSigTextDescriptionType}, DecideTextType}, &SupportedTags[20]}, + { cmsSigDateTimeTag, { 1, 1, { cmsSigDateTimeType }, NULL}, &SupportedTags[21]}, + + { cmsSigDeviceMfgDescTag, { 1, 3, { cmsSigTextDescriptionType, cmsSigMultiLocalizedUnicodeType, cmsSigTextType}, DecideTextDescType}, &SupportedTags[22]}, + { cmsSigDeviceModelDescTag, { 1, 3, { cmsSigTextDescriptionType, cmsSigMultiLocalizedUnicodeType, cmsSigTextType}, DecideTextDescType}, &SupportedTags[23]}, + + { cmsSigGamutTag, { 1, 3, { cmsSigLut16Type, cmsSigLutBtoAType, cmsSigLut8Type }, DecideLUTtypeB2A}, &SupportedTags[24]}, + + { cmsSigGrayTRCTag, { 1, 2, { cmsSigCurveType, cmsSigParametricCurveType }, DecideCurveType}, &SupportedTags[25]}, + { cmsSigLuminanceTag, { 1, 1, { cmsSigXYZType }, NULL}, &SupportedTags[26]}, + + { cmsSigMediaBlackPointTag, { 1, 2, { cmsSigXYZType, cmsCorbisBrokenXYZtype }, NULL}, &SupportedTags[27]}, + { cmsSigMediaWhitePointTag, { 1, 2, { cmsSigXYZType, cmsCorbisBrokenXYZtype }, NULL}, &SupportedTags[28]}, + + { cmsSigNamedColor2Tag, { 1, 1, { cmsSigNamedColor2Type }, NULL}, &SupportedTags[29]}, + + { cmsSigPreview0Tag, { 1, 3, { cmsSigLut16Type, cmsSigLutBtoAType, cmsSigLut8Type }, DecideLUTtypeB2A}, &SupportedTags[30]}, + { cmsSigPreview1Tag, { 1, 3, { cmsSigLut16Type, cmsSigLutBtoAType, cmsSigLut8Type }, DecideLUTtypeB2A}, &SupportedTags[31]}, + { cmsSigPreview2Tag, { 1, 3, { cmsSigLut16Type, cmsSigLutBtoAType, cmsSigLut8Type }, DecideLUTtypeB2A}, &SupportedTags[32]}, + + { cmsSigProfileDescriptionTag, { 1, 3, { cmsSigTextDescriptionType, cmsSigMultiLocalizedUnicodeType, cmsSigTextType}, DecideTextDescType}, &SupportedTags[33]}, + { cmsSigProfileSequenceDescTag, { 1, 1, { cmsSigProfileSequenceDescType }, NULL}, &SupportedTags[34]}, + { cmsSigTechnologyTag, { 1, 1, { cmsSigSignatureType }, NULL}, &SupportedTags[35]}, + + { cmsSigColorimetricIntentImageStateTag, { 1, 1, { cmsSigSignatureType }, NULL}, &SupportedTags[36]}, + { cmsSigPerceptualRenderingIntentGamutTag, { 1, 1, { cmsSigSignatureType }, NULL}, &SupportedTags[37]}, + { cmsSigSaturationRenderingIntentGamutTag, { 1, 1, { cmsSigSignatureType }, NULL}, &SupportedTags[38]}, + + { cmsSigMeasurementTag, { 1, 1, { cmsSigMeasurementType }, NULL}, &SupportedTags[39]}, + + { cmsSigPs2CRD0Tag, { 1, 1, { cmsSigDataType }, NULL}, &SupportedTags[40]}, + { cmsSigPs2CRD1Tag, { 1, 1, { cmsSigDataType }, NULL}, &SupportedTags[41]}, + { cmsSigPs2CRD2Tag, { 1, 1, { cmsSigDataType }, NULL}, &SupportedTags[42]}, + { cmsSigPs2CRD3Tag, { 1, 1, { cmsSigDataType }, NULL}, &SupportedTags[43]}, + { cmsSigPs2CSATag, { 1, 1, { cmsSigDataType }, NULL}, &SupportedTags[44]}, + { cmsSigPs2RenderingIntentTag, { 1, 1, { cmsSigDataType }, NULL}, &SupportedTags[45]}, + + { cmsSigViewingCondDescTag, { 1, 3, { cmsSigTextDescriptionType, cmsSigMultiLocalizedUnicodeType, cmsSigTextType}, DecideTextDescType}, &SupportedTags[46]}, + + { cmsSigUcrBgTag, { 1, 1, { cmsSigUcrBgType}, NULL}, &SupportedTags[47]}, + { cmsSigCrdInfoTag, { 1, 1, { cmsSigCrdInfoType}, NULL}, &SupportedTags[48]}, + + { cmsSigDToB0Tag, { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[49]}, + { cmsSigDToB1Tag, { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[50]}, + { cmsSigDToB2Tag, { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[51]}, + { cmsSigDToB3Tag, { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[52]}, + { cmsSigBToD0Tag, { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[53]}, + { cmsSigBToD1Tag, { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[54]}, + { cmsSigBToD2Tag, { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[55]}, + { cmsSigBToD3Tag, { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[56]}, + + { cmsSigScreeningDescTag, { 1, 1, { cmsSigTextDescriptionType }, NULL}, &SupportedTags[57]}, + { cmsSigViewingConditionsTag, { 1, 1, { cmsSigViewingConditionsType }, NULL}, &SupportedTags[58]}, + + { cmsSigScreeningTag, { 1, 1, { cmsSigScreeningType}, NULL }, &SupportedTags[59]}, + { cmsSigVcgtTag, { 1, 1, { cmsSigVcgtType}, NULL }, &SupportedTags[60]}, + { cmsSigMetaTag, { 1, 1, { cmsSigDictType}, NULL }, &SupportedTags[61]}, + { cmsSigProfileSequenceIdTag, { 1, 1, { cmsSigProfileSequenceIdType}, NULL }, &SupportedTags[62]}, + { cmsSigProfileDescriptionMLTag,{ 1, 1, { cmsSigMultiLocalizedUnicodeType}, NULL}, NULL} + + +}; + +/* + Not supported Why + ======================= ========================================= + cmsSigOutputResponseTag ==> WARNING, POSSIBLE PATENT ON THIS SUBJECT! + cmsSigNamedColorTag ==> Deprecated + cmsSigDataTag ==> Ancient, unused + cmsSigDeviceSettingsTag ==> Deprecated, useless +*/ + +#define DEFAULT_TAG_COUNT (sizeof(SupportedTags) / sizeof(_cmsTagLinkedList)) + +cmsBool _cmsRegisterTagPlugin(cmsContext id, cmsPluginBase* Data) +{ + cmsPluginTag* Plugin = (cmsPluginTag*) Data; + _cmsTagLinkedList *pt, *Anterior; + + + if (Data == NULL) { + + SupportedTags[DEFAULT_TAG_COUNT-1].Next = NULL; + return TRUE; + } + + pt = Anterior = SupportedTags; + while (pt != NULL) { + + if (Plugin->Signature == pt -> Signature) { + pt ->Descriptor = Plugin ->Descriptor; // Replace old behaviour + return TRUE; + } + + Anterior = pt; + pt = pt ->Next; + } + + pt = (_cmsTagLinkedList*) _cmsPluginMalloc(id, sizeof(_cmsTagLinkedList)); + if (pt == NULL) return FALSE; + + pt ->Signature = Plugin ->Signature; + pt ->Descriptor = Plugin ->Descriptor; + pt ->Next = NULL; + + if (Anterior != NULL) Anterior -> Next = pt; + + return TRUE; +} + +// Return a descriptor for a given tag or NULL +cmsTagDescriptor* _cmsGetTagDescriptor(cmsTagSignature sig) +{ + _cmsTagLinkedList* pt; + + for (pt = SupportedTags; + pt != NULL; + pt = pt ->Next) { + + if (sig == pt -> Signature) return &pt ->Descriptor; + } + + return NULL; +} + diff --git a/jni/lcms2-2.5/src/cmsvirt.c b/jni/lcms2-2.5/src/cmsvirt.c new file mode 100644 index 00000000..953377a8 --- /dev/null +++ b/jni/lcms2-2.5/src/cmsvirt.c @@ -0,0 +1,1194 @@ +//--------------------------------------------------------------------------------- +// +// Little Color Management System +// Copyright (c) 1998-2011 Marti Maria Saguer +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//--------------------------------------------------------------------------------- +// + +#include "lcms2_internal.h" + +// Virtual (built-in) profiles +// ----------------------------------------------------------------------------------- + +static +cmsBool SetTextTags(cmsHPROFILE hProfile, const wchar_t* Description) +{ + cmsMLU *DescriptionMLU, *CopyrightMLU; + cmsBool rc = FALSE; + cmsContext ContextID = cmsGetProfileContextID(hProfile); + + DescriptionMLU = cmsMLUalloc(ContextID, 1); + CopyrightMLU = cmsMLUalloc(ContextID, 1); + + if (DescriptionMLU == NULL || CopyrightMLU == NULL) goto Error; + + if (!cmsMLUsetWide(DescriptionMLU, "en", "US", Description)) goto Error; + if (!cmsMLUsetWide(CopyrightMLU, "en", "US", L"No copyright, use freely")) goto Error; + + if (!cmsWriteTag(hProfile, cmsSigProfileDescriptionTag, DescriptionMLU)) goto Error; + if (!cmsWriteTag(hProfile, cmsSigCopyrightTag, CopyrightMLU)) goto Error; + + rc = TRUE; + +Error: + + if (DescriptionMLU) + cmsMLUfree(DescriptionMLU); + if (CopyrightMLU) + cmsMLUfree(CopyrightMLU); + return rc; +} + + +static +cmsBool SetSeqDescTag(cmsHPROFILE hProfile, const char* Model) +{ + cmsBool rc = FALSE; + cmsContext ContextID = cmsGetProfileContextID(hProfile); + cmsSEQ* Seq = cmsAllocProfileSequenceDescription(ContextID, 1); + + if (Seq == NULL) return FALSE; + + Seq->seq[0].deviceMfg = (cmsSignature) 0; + Seq->seq[0].deviceModel = (cmsSignature) 0; + +#ifdef CMS_DONT_USE_INT64 + Seq->seq[0].attributes[0] = 0; + Seq->seq[0].attributes[1] = 0; +#else + Seq->seq[0].attributes = 0; +#endif + + Seq->seq[0].technology = (cmsTechnologySignature) 0; + + cmsMLUsetASCII( Seq->seq[0].Manufacturer, cmsNoLanguage, cmsNoCountry, "Little CMS"); + cmsMLUsetASCII( Seq->seq[0].Model, cmsNoLanguage, cmsNoCountry, Model); + + if (!_cmsWriteProfileSequence(hProfile, Seq)) goto Error; + + rc = TRUE; + +Error: + if (Seq) + cmsFreeProfileSequenceDescription(Seq); + + return rc; +} + + + +// This function creates a profile based on White point, primaries and +// transfer functions. +cmsHPROFILE CMSEXPORT cmsCreateRGBProfileTHR(cmsContext ContextID, + const cmsCIExyY* WhitePoint, + const cmsCIExyYTRIPLE* Primaries, + cmsToneCurve* const TransferFunction[3]) +{ + cmsHPROFILE hICC; + cmsMAT3 MColorants; + cmsCIEXYZTRIPLE Colorants; + cmsCIExyY MaxWhite; + cmsMAT3 CHAD; + cmsCIEXYZ WhitePointXYZ; + + hICC = cmsCreateProfilePlaceholder(ContextID); + if (!hICC) // can't allocate + return NULL; + + cmsSetProfileVersion(hICC, 4.3); + + cmsSetDeviceClass(hICC, cmsSigDisplayClass); + cmsSetColorSpace(hICC, cmsSigRgbData); + cmsSetPCS(hICC, cmsSigXYZData); + + cmsSetHeaderRenderingIntent(hICC, INTENT_PERCEPTUAL); + + + // Implement profile using following tags: + // + // 1 cmsSigProfileDescriptionTag + // 2 cmsSigMediaWhitePointTag + // 3 cmsSigRedColorantTag + // 4 cmsSigGreenColorantTag + // 5 cmsSigBlueColorantTag + // 6 cmsSigRedTRCTag + // 7 cmsSigGreenTRCTag + // 8 cmsSigBlueTRCTag + // 9 Chromatic adaptation Tag + // This conforms a standard RGB DisplayProfile as says ICC, and then I add (As per addendum II) + // 10 cmsSigChromaticityTag + + + if (!SetTextTags(hICC, L"RGB built-in")) goto Error; + + if (WhitePoint) { + + if (!cmsWriteTag(hICC, cmsSigMediaWhitePointTag, cmsD50_XYZ())) goto Error; + + cmsxyY2XYZ(&WhitePointXYZ, WhitePoint); + _cmsAdaptationMatrix(&CHAD, NULL, &WhitePointXYZ, cmsD50_XYZ()); + + // This is a V4 tag, but many CMM does read and understand it no matter which version + if (!cmsWriteTag(hICC, cmsSigChromaticAdaptationTag, (void*) &CHAD)) goto Error; + } + + if (WhitePoint && Primaries) { + + MaxWhite.x = WhitePoint -> x; + MaxWhite.y = WhitePoint -> y; + MaxWhite.Y = 1.0; + + if (!_cmsBuildRGB2XYZtransferMatrix(&MColorants, &MaxWhite, Primaries)) goto Error; + + Colorants.Red.X = MColorants.v[0].n[0]; + Colorants.Red.Y = MColorants.v[1].n[0]; + Colorants.Red.Z = MColorants.v[2].n[0]; + + Colorants.Green.X = MColorants.v[0].n[1]; + Colorants.Green.Y = MColorants.v[1].n[1]; + Colorants.Green.Z = MColorants.v[2].n[1]; + + Colorants.Blue.X = MColorants.v[0].n[2]; + Colorants.Blue.Y = MColorants.v[1].n[2]; + Colorants.Blue.Z = MColorants.v[2].n[2]; + + if (!cmsWriteTag(hICC, cmsSigRedColorantTag, (void*) &Colorants.Red)) goto Error; + if (!cmsWriteTag(hICC, cmsSigBlueColorantTag, (void*) &Colorants.Blue)) goto Error; + if (!cmsWriteTag(hICC, cmsSigGreenColorantTag, (void*) &Colorants.Green)) goto Error; + } + + + if (TransferFunction) { + + // Tries to minimize space. Thanks to Richard Hughes for this nice idea + if (!cmsWriteTag(hICC, cmsSigRedTRCTag, (void*) TransferFunction[0])) goto Error; + + if (TransferFunction[1] == TransferFunction[0]) { + + if (!cmsLinkTag (hICC, cmsSigGreenTRCTag, cmsSigRedTRCTag)) goto Error; + + } else { + + if (!cmsWriteTag(hICC, cmsSigGreenTRCTag, (void*) TransferFunction[1])) goto Error; + } + + if (TransferFunction[2] == TransferFunction[0]) { + + if (!cmsLinkTag (hICC, cmsSigBlueTRCTag, cmsSigRedTRCTag)) goto Error; + + } else { + + if (!cmsWriteTag(hICC, cmsSigBlueTRCTag, (void*) TransferFunction[2])) goto Error; + } + } + + if (Primaries) { + if (!cmsWriteTag(hICC, cmsSigChromaticityTag, (void*) Primaries)) goto Error; + } + + + return hICC; + +Error: + if (hICC) + cmsCloseProfile(hICC); + return NULL; +} + +cmsHPROFILE CMSEXPORT cmsCreateRGBProfile(const cmsCIExyY* WhitePoint, + const cmsCIExyYTRIPLE* Primaries, + cmsToneCurve* const TransferFunction[3]) +{ + return cmsCreateRGBProfileTHR(NULL, WhitePoint, Primaries, TransferFunction); +} + + + +// This function creates a profile based on White point and transfer function. +cmsHPROFILE CMSEXPORT cmsCreateGrayProfileTHR(cmsContext ContextID, + const cmsCIExyY* WhitePoint, + const cmsToneCurve* TransferFunction) +{ + cmsHPROFILE hICC; + cmsCIEXYZ tmp; + + hICC = cmsCreateProfilePlaceholder(ContextID); + if (!hICC) // can't allocate + return NULL; + + cmsSetProfileVersion(hICC, 4.3); + + cmsSetDeviceClass(hICC, cmsSigDisplayClass); + cmsSetColorSpace(hICC, cmsSigGrayData); + cmsSetPCS(hICC, cmsSigXYZData); + cmsSetHeaderRenderingIntent(hICC, INTENT_PERCEPTUAL); + + + // Implement profile using following tags: + // + // 1 cmsSigProfileDescriptionTag + // 2 cmsSigMediaWhitePointTag + // 3 cmsSigGrayTRCTag + + // This conforms a standard Gray DisplayProfile + + // Fill-in the tags + + if (!SetTextTags(hICC, L"gray built-in")) goto Error; + + + if (WhitePoint) { + + cmsxyY2XYZ(&tmp, WhitePoint); + if (!cmsWriteTag(hICC, cmsSigMediaWhitePointTag, (void*) &tmp)) goto Error; + } + + if (TransferFunction) { + + if (!cmsWriteTag(hICC, cmsSigGrayTRCTag, (void*) TransferFunction)) goto Error; + } + + return hICC; + +Error: + if (hICC) + cmsCloseProfile(hICC); + return NULL; +} + + + +cmsHPROFILE CMSEXPORT cmsCreateGrayProfile(const cmsCIExyY* WhitePoint, + const cmsToneCurve* TransferFunction) +{ + return cmsCreateGrayProfileTHR(NULL, WhitePoint, TransferFunction); +} + +// This is a devicelink operating in the target colorspace with as many transfer functions as components + +cmsHPROFILE CMSEXPORT cmsCreateLinearizationDeviceLinkTHR(cmsContext ContextID, + cmsColorSpaceSignature ColorSpace, + cmsToneCurve* const TransferFunctions[]) +{ + cmsHPROFILE hICC; + cmsPipeline* Pipeline; + int nChannels; + + hICC = cmsCreateProfilePlaceholder(ContextID); + if (!hICC) + return NULL; + + cmsSetProfileVersion(hICC, 4.3); + + cmsSetDeviceClass(hICC, cmsSigLinkClass); + cmsSetColorSpace(hICC, ColorSpace); + cmsSetPCS(hICC, ColorSpace); + + cmsSetHeaderRenderingIntent(hICC, INTENT_PERCEPTUAL); + + // Set up channels + nChannels = cmsChannelsOf(ColorSpace); + + // Creates a Pipeline with prelinearization step only + Pipeline = cmsPipelineAlloc(ContextID, nChannels, nChannels); + if (Pipeline == NULL) goto Error; + + + // Copy tables to Pipeline + if (!cmsPipelineInsertStage(Pipeline, cmsAT_BEGIN, cmsStageAllocToneCurves(ContextID, nChannels, TransferFunctions))) + goto Error; + + // Create tags + if (!SetTextTags(hICC, L"Linearization built-in")) goto Error; + if (!cmsWriteTag(hICC, cmsSigAToB0Tag, (void*) Pipeline)) goto Error; + if (!SetSeqDescTag(hICC, "Linearization built-in")) goto Error; + + // Pipeline is already on virtual profile + cmsPipelineFree(Pipeline); + + // Ok, done + return hICC; + +Error: + cmsPipelineFree(Pipeline); + if (hICC) + cmsCloseProfile(hICC); + + + return NULL; +} + +cmsHPROFILE CMSEXPORT cmsCreateLinearizationDeviceLink(cmsColorSpaceSignature ColorSpace, + cmsToneCurve* const TransferFunctions[]) +{ + return cmsCreateLinearizationDeviceLinkTHR(NULL, ColorSpace, TransferFunctions); +} + +// Ink-limiting algorithm +// +// Sum = C + M + Y + K +// If Sum > InkLimit +// Ratio= 1 - (Sum - InkLimit) / (C + M + Y) +// if Ratio <0 +// Ratio=0 +// endif +// Else +// Ratio=1 +// endif +// +// C = Ratio * C +// M = Ratio * M +// Y = Ratio * Y +// K: Does not change + +static +int InkLimitingSampler(register const cmsUInt16Number In[], register cmsUInt16Number Out[], register void* Cargo) +{ + cmsFloat64Number InkLimit = *(cmsFloat64Number *) Cargo; + cmsFloat64Number SumCMY, SumCMYK, Ratio; + + InkLimit = (InkLimit * 655.35); + + SumCMY = In[0] + In[1] + In[2]; + SumCMYK = SumCMY + In[3]; + + if (SumCMYK > InkLimit) { + + Ratio = 1 - ((SumCMYK - InkLimit) / SumCMY); + if (Ratio < 0) + Ratio = 0; + } + else Ratio = 1; + + Out[0] = _cmsQuickSaturateWord(In[0] * Ratio); // C + Out[1] = _cmsQuickSaturateWord(In[1] * Ratio); // M + Out[2] = _cmsQuickSaturateWord(In[2] * Ratio); // Y + + Out[3] = In[3]; // K (untouched) + + return TRUE; +} + +// This is a devicelink operating in CMYK for ink-limiting + +cmsHPROFILE CMSEXPORT cmsCreateInkLimitingDeviceLinkTHR(cmsContext ContextID, + cmsColorSpaceSignature ColorSpace, + cmsFloat64Number Limit) +{ + cmsHPROFILE hICC; + cmsPipeline* LUT; + cmsStage* CLUT; + int nChannels; + + if (ColorSpace != cmsSigCmykData) { + cmsSignalError(ContextID, cmsERROR_COLORSPACE_CHECK, "InkLimiting: Only CMYK currently supported"); + return NULL; + } + + if (Limit < 0.0 || Limit > 400) { + + cmsSignalError(ContextID, cmsERROR_RANGE, "InkLimiting: Limit should be between 0..400"); + if (Limit < 0) Limit = 0; + if (Limit > 400) Limit = 400; + + } + + hICC = cmsCreateProfilePlaceholder(ContextID); + if (!hICC) // can't allocate + return NULL; + + cmsSetProfileVersion(hICC, 4.3); + + cmsSetDeviceClass(hICC, cmsSigLinkClass); + cmsSetColorSpace(hICC, ColorSpace); + cmsSetPCS(hICC, ColorSpace); + + cmsSetHeaderRenderingIntent(hICC, INTENT_PERCEPTUAL); + + + // Creates a Pipeline with 3D grid only + LUT = cmsPipelineAlloc(ContextID, 4, 4); + if (LUT == NULL) goto Error; + + + nChannels = cmsChannelsOf(ColorSpace); + + CLUT = cmsStageAllocCLut16bit(ContextID, 17, nChannels, nChannels, NULL); + if (CLUT == NULL) goto Error; + + if (!cmsStageSampleCLut16bit(CLUT, InkLimitingSampler, (void*) &Limit, 0)) goto Error; + + if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, nChannels)) || + !cmsPipelineInsertStage(LUT, cmsAT_END, CLUT) || + !cmsPipelineInsertStage(LUT, cmsAT_END, _cmsStageAllocIdentityCurves(ContextID, nChannels))) + goto Error; + + // Create tags + if (!SetTextTags(hICC, L"ink-limiting built-in")) goto Error; + + if (!cmsWriteTag(hICC, cmsSigAToB0Tag, (void*) LUT)) goto Error; + if (!SetSeqDescTag(hICC, "ink-limiting built-in")) goto Error; + + // cmsPipeline is already on virtual profile + cmsPipelineFree(LUT); + + // Ok, done + return hICC; + +Error: + if (LUT != NULL) + cmsPipelineFree(LUT); + + if (hICC != NULL) + cmsCloseProfile(hICC); + + return NULL; +} + +cmsHPROFILE CMSEXPORT cmsCreateInkLimitingDeviceLink(cmsColorSpaceSignature ColorSpace, cmsFloat64Number Limit) +{ + return cmsCreateInkLimitingDeviceLinkTHR(NULL, ColorSpace, Limit); +} + + +// Creates a fake Lab identity. +cmsHPROFILE CMSEXPORT cmsCreateLab2ProfileTHR(cmsContext ContextID, const cmsCIExyY* WhitePoint) +{ + cmsHPROFILE hProfile; + cmsPipeline* LUT = NULL; + + hProfile = cmsCreateRGBProfileTHR(ContextID, WhitePoint == NULL ? cmsD50_xyY() : WhitePoint, NULL, NULL); + if (hProfile == NULL) return NULL; + + cmsSetProfileVersion(hProfile, 2.1); + + cmsSetDeviceClass(hProfile, cmsSigAbstractClass); + cmsSetColorSpace(hProfile, cmsSigLabData); + cmsSetPCS(hProfile, cmsSigLabData); + + if (!SetTextTags(hProfile, L"Lab identity built-in")) return NULL; + + // An identity LUT is all we need + LUT = cmsPipelineAlloc(ContextID, 3, 3); + if (LUT == NULL) goto Error; + + if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCLut(ContextID, 3))) + goto Error; + + if (!cmsWriteTag(hProfile, cmsSigAToB0Tag, LUT)) goto Error; + cmsPipelineFree(LUT); + + return hProfile; + +Error: + + if (LUT != NULL) + cmsPipelineFree(LUT); + + if (hProfile != NULL) + cmsCloseProfile(hProfile); + + return NULL; +} + + +cmsHPROFILE CMSEXPORT cmsCreateLab2Profile(const cmsCIExyY* WhitePoint) +{ + return cmsCreateLab2ProfileTHR(NULL, WhitePoint); +} + + +// Creates a fake Lab V4 identity. +cmsHPROFILE CMSEXPORT cmsCreateLab4ProfileTHR(cmsContext ContextID, const cmsCIExyY* WhitePoint) +{ + cmsHPROFILE hProfile; + cmsPipeline* LUT = NULL; + + hProfile = cmsCreateRGBProfileTHR(ContextID, WhitePoint == NULL ? cmsD50_xyY() : WhitePoint, NULL, NULL); + if (hProfile == NULL) return NULL; + + cmsSetProfileVersion(hProfile, 4.3); + + cmsSetDeviceClass(hProfile, cmsSigAbstractClass); + cmsSetColorSpace(hProfile, cmsSigLabData); + cmsSetPCS(hProfile, cmsSigLabData); + + if (!SetTextTags(hProfile, L"Lab identity built-in")) goto Error; + + // An empty LUTs is all we need + LUT = cmsPipelineAlloc(ContextID, 3, 3); + if (LUT == NULL) goto Error; + + if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, 3))) + goto Error; + + if (!cmsWriteTag(hProfile, cmsSigAToB0Tag, LUT)) goto Error; + cmsPipelineFree(LUT); + + return hProfile; + +Error: + + if (LUT != NULL) + cmsPipelineFree(LUT); + + if (hProfile != NULL) + cmsCloseProfile(hProfile); + + return NULL; +} + +cmsHPROFILE CMSEXPORT cmsCreateLab4Profile(const cmsCIExyY* WhitePoint) +{ + return cmsCreateLab4ProfileTHR(NULL, WhitePoint); +} + + +// Creates a fake XYZ identity +cmsHPROFILE CMSEXPORT cmsCreateXYZProfileTHR(cmsContext ContextID) +{ + cmsHPROFILE hProfile; + cmsPipeline* LUT = NULL; + + hProfile = cmsCreateRGBProfileTHR(ContextID, cmsD50_xyY(), NULL, NULL); + if (hProfile == NULL) return NULL; + + cmsSetProfileVersion(hProfile, 4.3); + + cmsSetDeviceClass(hProfile, cmsSigAbstractClass); + cmsSetColorSpace(hProfile, cmsSigXYZData); + cmsSetPCS(hProfile, cmsSigXYZData); + + if (!SetTextTags(hProfile, L"XYZ identity built-in")) goto Error; + + // An identity LUT is all we need + LUT = cmsPipelineAlloc(ContextID, 3, 3); + if (LUT == NULL) goto Error; + + if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, 3))) + goto Error; + + if (!cmsWriteTag(hProfile, cmsSigAToB0Tag, LUT)) goto Error; + cmsPipelineFree(LUT); + + return hProfile; + +Error: + + if (LUT != NULL) + cmsPipelineFree(LUT); + + if (hProfile != NULL) + cmsCloseProfile(hProfile); + + return NULL; +} + + +cmsHPROFILE CMSEXPORT cmsCreateXYZProfile(void) +{ + return cmsCreateXYZProfileTHR(NULL); +} + + +//sRGB Curves are defined by: +// +//If R’sRGB,G’sRGB, B’sRGB < 0.04045 +// +// R = R’sRGB / 12.92 +// G = G’sRGB / 12.92 +// B = B’sRGB / 12.92 +// +// +//else if R’sRGB,G’sRGB, B’sRGB >= 0.04045 +// +// R = ((R’sRGB + 0.055) / 1.055)^2.4 +// G = ((G’sRGB + 0.055) / 1.055)^2.4 +// B = ((B’sRGB + 0.055) / 1.055)^2.4 + +static +cmsToneCurve* Build_sRGBGamma(cmsContext ContextID) +{ + cmsFloat64Number Parameters[5]; + + Parameters[0] = 2.4; + Parameters[1] = 1. / 1.055; + Parameters[2] = 0.055 / 1.055; + Parameters[3] = 1. / 12.92; + Parameters[4] = 0.04045; + + return cmsBuildParametricToneCurve(ContextID, 4, Parameters); +} + +// Create the ICC virtual profile for sRGB space +cmsHPROFILE CMSEXPORT cmsCreate_sRGBProfileTHR(cmsContext ContextID) +{ + cmsCIExyY D65; + cmsCIExyYTRIPLE Rec709Primaries = { + {0.6400, 0.3300, 1.0}, + {0.3000, 0.6000, 1.0}, + {0.1500, 0.0600, 1.0} + }; + cmsToneCurve* Gamma22[3]; + cmsHPROFILE hsRGB; + + cmsWhitePointFromTemp(&D65, 6504); + Gamma22[0] = Gamma22[1] = Gamma22[2] = Build_sRGBGamma(ContextID); + if (Gamma22[0] == NULL) return NULL; + + hsRGB = cmsCreateRGBProfileTHR(ContextID, &D65, &Rec709Primaries, Gamma22); + cmsFreeToneCurve(Gamma22[0]); + if (hsRGB == NULL) return NULL; + + if (!SetTextTags(hsRGB, L"sRGB built-in")) { + cmsCloseProfile(hsRGB); + return NULL; + } + + return hsRGB; +} + +cmsHPROFILE CMSEXPORT cmsCreate_sRGBProfile(void) +{ + return cmsCreate_sRGBProfileTHR(NULL); +} + + + +typedef struct { + cmsFloat64Number Brightness; + cmsFloat64Number Contrast; + cmsFloat64Number Hue; + cmsFloat64Number Saturation; + cmsCIEXYZ WPsrc, WPdest; + +} BCHSWADJUSTS, *LPBCHSWADJUSTS; + + +static +int bchswSampler(register const cmsUInt16Number In[], register cmsUInt16Number Out[], register void* Cargo) +{ + cmsCIELab LabIn, LabOut; + cmsCIELCh LChIn, LChOut; + cmsCIEXYZ XYZ; + LPBCHSWADJUSTS bchsw = (LPBCHSWADJUSTS) Cargo; + + + cmsLabEncoded2Float(&LabIn, In); + + + cmsLab2LCh(&LChIn, &LabIn); + + // Do some adjusts on LCh + + LChOut.L = LChIn.L * bchsw ->Contrast + bchsw ->Brightness; + LChOut.C = LChIn.C + bchsw -> Saturation; + LChOut.h = LChIn.h + bchsw -> Hue; + + + cmsLCh2Lab(&LabOut, &LChOut); + + // Move white point in Lab + + cmsLab2XYZ(&bchsw ->WPsrc, &XYZ, &LabOut); + cmsXYZ2Lab(&bchsw ->WPdest, &LabOut, &XYZ); + + // Back to encoded + + cmsFloat2LabEncoded(Out, &LabOut); + + return TRUE; +} + + +// Creates an abstract profile operating in Lab space for Brightness, +// contrast, Saturation and white point displacement + +cmsHPROFILE CMSEXPORT cmsCreateBCHSWabstractProfileTHR(cmsContext ContextID, + int nLUTPoints, + cmsFloat64Number Bright, + cmsFloat64Number Contrast, + cmsFloat64Number Hue, + cmsFloat64Number Saturation, + int TempSrc, + int TempDest) +{ + cmsHPROFILE hICC; + cmsPipeline* Pipeline; + BCHSWADJUSTS bchsw; + cmsCIExyY WhitePnt; + cmsStage* CLUT; + cmsUInt32Number Dimensions[MAX_INPUT_DIMENSIONS]; + int i; + + bchsw.Brightness = Bright; + bchsw.Contrast = Contrast; + bchsw.Hue = Hue; + bchsw.Saturation = Saturation; + + cmsWhitePointFromTemp(&WhitePnt, TempSrc ); + cmsxyY2XYZ(&bchsw.WPsrc, &WhitePnt); + + cmsWhitePointFromTemp(&WhitePnt, TempDest); + cmsxyY2XYZ(&bchsw.WPdest, &WhitePnt); + + hICC = cmsCreateProfilePlaceholder(ContextID); + if (!hICC) // can't allocate + return NULL; + + + cmsSetDeviceClass(hICC, cmsSigAbstractClass); + cmsSetColorSpace(hICC, cmsSigLabData); + cmsSetPCS(hICC, cmsSigLabData); + + cmsSetHeaderRenderingIntent(hICC, INTENT_PERCEPTUAL); + + // Creates a Pipeline with 3D grid only + Pipeline = cmsPipelineAlloc(ContextID, 3, 3); + if (Pipeline == NULL) { + cmsCloseProfile(hICC); + return NULL; + } + + for (i=0; i < MAX_INPUT_DIMENSIONS; i++) Dimensions[i] = nLUTPoints; + CLUT = cmsStageAllocCLut16bitGranular(ContextID, Dimensions, 3, 3, NULL); + if (CLUT == NULL) return NULL; + + + if (!cmsStageSampleCLut16bit(CLUT, bchswSampler, (void*) &bchsw, 0)) { + + // Shouldn't reach here + goto Error; + } + + if (!cmsPipelineInsertStage(Pipeline, cmsAT_END, CLUT)) { + goto Error; + } + + // Create tags + if (!SetTextTags(hICC, L"BCHS built-in")) return NULL; + + cmsWriteTag(hICC, cmsSigMediaWhitePointTag, (void*) cmsD50_XYZ()); + + cmsWriteTag(hICC, cmsSigAToB0Tag, (void*) Pipeline); + + // Pipeline is already on virtual profile + cmsPipelineFree(Pipeline); + + // Ok, done + return hICC; + +Error: + cmsPipelineFree(Pipeline); + cmsCloseProfile(hICC); + return NULL; +} + + +CMSAPI cmsHPROFILE CMSEXPORT cmsCreateBCHSWabstractProfile(int nLUTPoints, + cmsFloat64Number Bright, + cmsFloat64Number Contrast, + cmsFloat64Number Hue, + cmsFloat64Number Saturation, + int TempSrc, + int TempDest) +{ + return cmsCreateBCHSWabstractProfileTHR(NULL, nLUTPoints, Bright, Contrast, Hue, Saturation, TempSrc, TempDest); +} + + +// Creates a fake NULL profile. This profile return 1 channel as always 0. +// Is useful only for gamut checking tricks +cmsHPROFILE CMSEXPORT cmsCreateNULLProfileTHR(cmsContext ContextID) +{ + cmsHPROFILE hProfile; + cmsPipeline* LUT = NULL; + cmsStage* PostLin; + cmsToneCurve* EmptyTab; + cmsUInt16Number Zero[2] = { 0, 0 }; + + hProfile = cmsCreateProfilePlaceholder(ContextID); + if (!hProfile) // can't allocate + return NULL; + + cmsSetProfileVersion(hProfile, 4.3); + + if (!SetTextTags(hProfile, L"NULL profile built-in")) goto Error; + + + + cmsSetDeviceClass(hProfile, cmsSigOutputClass); + cmsSetColorSpace(hProfile, cmsSigGrayData); + cmsSetPCS(hProfile, cmsSigLabData); + + // An empty LUTs is all we need + LUT = cmsPipelineAlloc(ContextID, 1, 1); + if (LUT == NULL) goto Error; + + EmptyTab = cmsBuildTabulatedToneCurve16(ContextID, 2, Zero); + PostLin = cmsStageAllocToneCurves(ContextID, 1, &EmptyTab); + cmsFreeToneCurve(EmptyTab); + + if (!cmsPipelineInsertStage(LUT, cmsAT_END, PostLin)) + goto Error; + + if (!cmsWriteTag(hProfile, cmsSigBToA0Tag, (void*) LUT)) goto Error; + if (!cmsWriteTag(hProfile, cmsSigMediaWhitePointTag, cmsD50_XYZ())) goto Error; + + cmsPipelineFree(LUT); + return hProfile; + +Error: + + if (LUT != NULL) + cmsPipelineFree(LUT); + + if (hProfile != NULL) + cmsCloseProfile(hProfile); + + return NULL; +} + +cmsHPROFILE CMSEXPORT cmsCreateNULLProfile(void) +{ + return cmsCreateNULLProfileTHR(NULL); +} + + +static +int IsPCS(cmsColorSpaceSignature ColorSpace) +{ + return (ColorSpace == cmsSigXYZData || + ColorSpace == cmsSigLabData); +} + + +static +void FixColorSpaces(cmsHPROFILE hProfile, + cmsColorSpaceSignature ColorSpace, + cmsColorSpaceSignature PCS, + cmsUInt32Number dwFlags) +{ + if (dwFlags & cmsFLAGS_GUESSDEVICECLASS) { + + if (IsPCS(ColorSpace) && IsPCS(PCS)) { + + cmsSetDeviceClass(hProfile, cmsSigAbstractClass); + cmsSetColorSpace(hProfile, ColorSpace); + cmsSetPCS(hProfile, PCS); + return; + } + + if (IsPCS(ColorSpace) && !IsPCS(PCS)) { + + cmsSetDeviceClass(hProfile, cmsSigOutputClass); + cmsSetPCS(hProfile, ColorSpace); + cmsSetColorSpace(hProfile, PCS); + return; + } + + if (IsPCS(PCS) && !IsPCS(ColorSpace)) { + + cmsSetDeviceClass(hProfile, cmsSigInputClass); + cmsSetColorSpace(hProfile, ColorSpace); + cmsSetPCS(hProfile, PCS); + return; + } + } + + cmsSetDeviceClass(hProfile, cmsSigLinkClass); + cmsSetColorSpace(hProfile, ColorSpace); + cmsSetPCS(hProfile, PCS); +} + + + +// This function creates a named color profile dumping all the contents of transform to a single profile +// In this way, LittleCMS may be used to "group" several named color databases into a single profile. +// It has, however, several minor limitations. PCS is always Lab, which is not very critic since this +// is the normal PCS for named color profiles. +static +cmsHPROFILE CreateNamedColorDevicelink(cmsHTRANSFORM xform) +{ + _cmsTRANSFORM* v = (_cmsTRANSFORM*) xform; + cmsHPROFILE hICC = NULL; + int i, nColors; + cmsNAMEDCOLORLIST *nc2 = NULL, *Original = NULL; + + // Create an empty placeholder + hICC = cmsCreateProfilePlaceholder(v->ContextID); + if (hICC == NULL) return NULL; + + // Critical information + cmsSetDeviceClass(hICC, cmsSigNamedColorClass); + cmsSetColorSpace(hICC, v ->ExitColorSpace); + cmsSetPCS(hICC, cmsSigLabData); + + // Tag profile with information + if (!SetTextTags(hICC, L"Named color devicelink")) goto Error; + + Original = cmsGetNamedColorList(xform); + if (Original == NULL) goto Error; + + nColors = cmsNamedColorCount(Original); + nc2 = cmsDupNamedColorList(Original); + if (nc2 == NULL) goto Error; + + // Colorant count now depends on the output space + nc2 ->ColorantCount = cmsPipelineOutputChannels(v ->Lut); + + // Make sure we have proper formatters + cmsChangeBuffersFormat(xform, TYPE_NAMED_COLOR_INDEX, + FLOAT_SH(0) | COLORSPACE_SH(_cmsLCMScolorSpace(v ->ExitColorSpace)) + | BYTES_SH(2) | CHANNELS_SH(cmsChannelsOf(v ->ExitColorSpace))); + + // Apply the transfor to colorants. + for (i=0; i < nColors; i++) { + cmsDoTransform(xform, &i, nc2 ->List[i].DeviceColorant, 1); + } + + if (!cmsWriteTag(hICC, cmsSigNamedColor2Tag, (void*) nc2)) goto Error; + cmsFreeNamedColorList(nc2); + + return hICC; + +Error: + if (hICC != NULL) cmsCloseProfile(hICC); + return NULL; +} + + +// This structure holds information about which MPU can be stored on a profile based on the version + +typedef struct { + cmsBool IsV4; // Is a V4 tag? + cmsTagSignature RequiredTag; // Set to 0 for both types + cmsTagTypeSignature LutType; // The LUT type + int nTypes; // Number of types (up to 5) + cmsStageSignature MpeTypes[5]; // 5 is the maximum number + +} cmsAllowedLUT; + +static const cmsAllowedLUT AllowedLUTTypes[] = { + + { FALSE, 0, cmsSigLut16Type, 4, { cmsSigMatrixElemType, cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType}}, + { FALSE, 0, cmsSigLut16Type, 3, { cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType}}, + { FALSE, 0, cmsSigLut16Type, 2, { cmsSigCurveSetElemType, cmsSigCLutElemType}}, + { TRUE , 0, cmsSigLutAtoBType, 1, { cmsSigCurveSetElemType }}, + { TRUE , cmsSigAToB0Tag, cmsSigLutAtoBType, 3, { cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType } }, + { TRUE , cmsSigAToB0Tag, cmsSigLutAtoBType, 3, { cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType } }, + { TRUE , cmsSigAToB0Tag, cmsSigLutAtoBType, 5, { cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType }}, + { TRUE , cmsSigBToA0Tag, cmsSigLutBtoAType, 1, { cmsSigCurveSetElemType }}, + { TRUE , cmsSigBToA0Tag, cmsSigLutBtoAType, 3, { cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType }}, + { TRUE , cmsSigBToA0Tag, cmsSigLutBtoAType, 3, { cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType }}, + { TRUE , cmsSigBToA0Tag, cmsSigLutBtoAType, 5, { cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType }} +}; + +#define SIZE_OF_ALLOWED_LUT (sizeof(AllowedLUTTypes)/sizeof(cmsAllowedLUT)) + +// Check a single entry +static +cmsBool CheckOne(const cmsAllowedLUT* Tab, const cmsPipeline* Lut) +{ + cmsStage* mpe; + int n; + + for (n=0, mpe = Lut ->Elements; mpe != NULL; mpe = mpe ->Next, n++) { + + if (n > Tab ->nTypes) return FALSE; + if (cmsStageType(mpe) != Tab ->MpeTypes[n]) return FALSE; + } + + return (n == Tab ->nTypes); +} + + +static +const cmsAllowedLUT* FindCombination(const cmsPipeline* Lut, cmsBool IsV4, cmsTagSignature DestinationTag) +{ + cmsUInt32Number n; + + for (n=0; n < SIZE_OF_ALLOWED_LUT; n++) { + + const cmsAllowedLUT* Tab = AllowedLUTTypes + n; + + if (IsV4 ^ Tab -> IsV4) continue; + if ((Tab ->RequiredTag != 0) && (Tab ->RequiredTag != DestinationTag)) continue; + + if (CheckOne(Tab, Lut)) return Tab; + } + + return NULL; +} + + +// Does convert a transform into a device link profile +cmsHPROFILE CMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, cmsFloat64Number Version, cmsUInt32Number dwFlags) +{ + cmsHPROFILE hProfile = NULL; + cmsUInt32Number FrmIn, FrmOut, ChansIn, ChansOut; + cmsUInt32Number ColorSpaceBitsIn, ColorSpaceBitsOut; + _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform; + cmsPipeline* LUT = NULL; + cmsStage* mpe; + cmsContext ContextID = cmsGetTransformContextID(hTransform); + const cmsAllowedLUT* AllowedLUT; + cmsTagSignature DestinationTag; + cmsProfileClassSignature deviceClass; + + _cmsAssert(hTransform != NULL); + + // Get the first mpe to check for named color + mpe = cmsPipelineGetPtrToFirstStage(xform ->Lut); + + // Check if is a named color transform + if (mpe != NULL) { + + if (cmsStageType(mpe) == cmsSigNamedColorElemType) { + return CreateNamedColorDevicelink(hTransform); + } + } + + // First thing to do is to get a copy of the transformation + LUT = cmsPipelineDup(xform ->Lut); + if (LUT == NULL) return NULL; + + // Time to fix the Lab2/Lab4 issue. + if ((xform ->EntryColorSpace == cmsSigLabData) && (Version < 4.0)) { + + if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocLabV2ToV4curves(ContextID))) + goto Error; + } + + // On the output side too + if ((xform ->ExitColorSpace) == cmsSigLabData && (Version < 4.0)) { + + if (!cmsPipelineInsertStage(LUT, cmsAT_END, _cmsStageAllocLabV4ToV2(ContextID))) + goto Error; + } + + + hProfile = cmsCreateProfilePlaceholder(ContextID); + if (!hProfile) goto Error; // can't allocate + + cmsSetProfileVersion(hProfile, Version); + + FixColorSpaces(hProfile, xform -> EntryColorSpace, xform -> ExitColorSpace, dwFlags); + + // Optimize the LUT and precalculate a devicelink + + ChansIn = cmsChannelsOf(xform -> EntryColorSpace); + ChansOut = cmsChannelsOf(xform -> ExitColorSpace); + + ColorSpaceBitsIn = _cmsLCMScolorSpace(xform -> EntryColorSpace); + ColorSpaceBitsOut = _cmsLCMScolorSpace(xform -> ExitColorSpace); + + FrmIn = COLORSPACE_SH(ColorSpaceBitsIn) | CHANNELS_SH(ChansIn)|BYTES_SH(2); + FrmOut = COLORSPACE_SH(ColorSpaceBitsOut) | CHANNELS_SH(ChansOut)|BYTES_SH(2); + + deviceClass = cmsGetDeviceClass(hProfile); + + if (deviceClass == cmsSigOutputClass) + DestinationTag = cmsSigBToA0Tag; + else + DestinationTag = cmsSigAToB0Tag; + + // Check if the profile/version can store the result + if (dwFlags & cmsFLAGS_FORCE_CLUT) + AllowedLUT = NULL; + else + AllowedLUT = FindCombination(LUT, Version >= 4.0, DestinationTag); + + if (AllowedLUT == NULL) { + + // Try to optimize + _cmsOptimizePipeline(&LUT, xform ->RenderingIntent, &FrmIn, &FrmOut, &dwFlags); + AllowedLUT = FindCombination(LUT, Version >= 4.0, DestinationTag); + + } + + // If no way, then force CLUT that for sure can be written + if (AllowedLUT == NULL) { + + dwFlags |= cmsFLAGS_FORCE_CLUT; + _cmsOptimizePipeline(&LUT, xform ->RenderingIntent, &FrmIn, &FrmOut, &dwFlags); + + // Put identity curves if needed + if (cmsPipelineGetPtrToFirstStage(LUT) ->Type != cmsSigCurveSetElemType) + if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, ChansIn))) + goto Error; + + if (cmsPipelineGetPtrToLastStage(LUT) ->Type != cmsSigCurveSetElemType) + if (!cmsPipelineInsertStage(LUT, cmsAT_END, _cmsStageAllocIdentityCurves(ContextID, ChansOut))) + goto Error; + + AllowedLUT = FindCombination(LUT, Version >= 4.0, DestinationTag); + } + + // Somethings is wrong... + if (AllowedLUT == NULL) { + goto Error; + } + + + if (dwFlags & cmsFLAGS_8BITS_DEVICELINK) + cmsPipelineSetSaveAs8bitsFlag(LUT, TRUE); + + // Tag profile with information + if (!SetTextTags(hProfile, L"devicelink")) goto Error; + + // Store result + if (!cmsWriteTag(hProfile, DestinationTag, LUT)) goto Error; + + + if (xform -> InputColorant != NULL) { + if (!cmsWriteTag(hProfile, cmsSigColorantTableTag, xform->InputColorant)) goto Error; + } + + if (xform -> OutputColorant != NULL) { + if (!cmsWriteTag(hProfile, cmsSigColorantTableOutTag, xform->OutputColorant)) goto Error; + } + + if ((deviceClass == cmsSigLinkClass) && (xform ->Sequence != NULL)) { + if (!_cmsWriteProfileSequence(hProfile, xform ->Sequence)) goto Error; + } + + // Set the white point + if (deviceClass == cmsSigInputClass) { + if (!cmsWriteTag(hProfile, cmsSigMediaWhitePointTag, &xform ->EntryWhitePoint)) goto Error; + } + else { + if (!cmsWriteTag(hProfile, cmsSigMediaWhitePointTag, &xform ->ExitWhitePoint)) goto Error; + } + + + // Per 7.2.15 in spec 4.3 + cmsSetHeaderRenderingIntent(hProfile, xform ->RenderingIntent); + + cmsPipelineFree(LUT); + return hProfile; + +Error: + if (LUT != NULL) cmsPipelineFree(LUT); + cmsCloseProfile(hProfile); + return NULL; +} diff --git a/jni/lcms2-2.5/src/cmswtpnt.c b/jni/lcms2-2.5/src/cmswtpnt.c new file mode 100644 index 00000000..84e3a329 --- /dev/null +++ b/jni/lcms2-2.5/src/cmswtpnt.c @@ -0,0 +1,351 @@ +//--------------------------------------------------------------------------------- +// +// Little Color Management System +// Copyright (c) 1998-2012 Marti Maria Saguer +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//--------------------------------------------------------------------------------- +// + +#include "lcms2_internal.h" + + +// D50 - Widely used +const cmsCIEXYZ* CMSEXPORT cmsD50_XYZ(void) +{ + static cmsCIEXYZ D50XYZ = {cmsD50X, cmsD50Y, cmsD50Z}; + + return &D50XYZ; +} + +const cmsCIExyY* CMSEXPORT cmsD50_xyY(void) +{ + static cmsCIExyY D50xyY; + + cmsXYZ2xyY(&D50xyY, cmsD50_XYZ()); + + return &D50xyY; +} + +// Obtains WhitePoint from Temperature +cmsBool CMSEXPORT cmsWhitePointFromTemp(cmsCIExyY* WhitePoint, cmsFloat64Number TempK) +{ + cmsFloat64Number x, y; + cmsFloat64Number T, T2, T3; + // cmsFloat64Number M1, M2; + + _cmsAssert(WhitePoint != NULL); + + T = TempK; + T2 = T*T; // Square + T3 = T2*T; // Cube + + // For correlated color temperature (T) between 4000K and 7000K: + + if (T >= 4000. && T <= 7000.) + { + x = -4.6070*(1E9/T3) + 2.9678*(1E6/T2) + 0.09911*(1E3/T) + 0.244063; + } + else + // or for correlated color temperature (T) between 7000K and 25000K: + + if (T > 7000.0 && T <= 25000.0) + { + x = -2.0064*(1E9/T3) + 1.9018*(1E6/T2) + 0.24748*(1E3/T) + 0.237040; + } + else { + cmsSignalError(0, cmsERROR_RANGE, "cmsWhitePointFromTemp: invalid temp"); + return FALSE; + } + + // Obtain y(x) + + y = -3.000*(x*x) + 2.870*x - 0.275; + + // wave factors (not used, but here for futures extensions) + + // M1 = (-1.3515 - 1.7703*x + 5.9114 *y)/(0.0241 + 0.2562*x - 0.7341*y); + // M2 = (0.0300 - 31.4424*x + 30.0717*y)/(0.0241 + 0.2562*x - 0.7341*y); + + WhitePoint -> x = x; + WhitePoint -> y = y; + WhitePoint -> Y = 1.0; + + return TRUE; +} + + + +typedef struct { + + cmsFloat64Number mirek; // temp (in microreciprocal kelvin) + cmsFloat64Number ut; // u coord of intersection w/ blackbody locus + cmsFloat64Number vt; // v coord of intersection w/ blackbody locus + cmsFloat64Number tt; // slope of ISOTEMPERATURE. line + + } ISOTEMPERATURE; + +static ISOTEMPERATURE isotempdata[] = { +// {Mirek, Ut, Vt, Tt } + {0, 0.18006, 0.26352, -0.24341}, + {10, 0.18066, 0.26589, -0.25479}, + {20, 0.18133, 0.26846, -0.26876}, + {30, 0.18208, 0.27119, -0.28539}, + {40, 0.18293, 0.27407, -0.30470}, + {50, 0.18388, 0.27709, -0.32675}, + {60, 0.18494, 0.28021, -0.35156}, + {70, 0.18611, 0.28342, -0.37915}, + {80, 0.18740, 0.28668, -0.40955}, + {90, 0.18880, 0.28997, -0.44278}, + {100, 0.19032, 0.29326, -0.47888}, + {125, 0.19462, 0.30141, -0.58204}, + {150, 0.19962, 0.30921, -0.70471}, + {175, 0.20525, 0.31647, -0.84901}, + {200, 0.21142, 0.32312, -1.0182 }, + {225, 0.21807, 0.32909, -1.2168 }, + {250, 0.22511, 0.33439, -1.4512 }, + {275, 0.23247, 0.33904, -1.7298 }, + {300, 0.24010, 0.34308, -2.0637 }, + {325, 0.24702, 0.34655, -2.4681 }, + {350, 0.25591, 0.34951, -2.9641 }, + {375, 0.26400, 0.35200, -3.5814 }, + {400, 0.27218, 0.35407, -4.3633 }, + {425, 0.28039, 0.35577, -5.3762 }, + {450, 0.28863, 0.35714, -6.7262 }, + {475, 0.29685, 0.35823, -8.5955 }, + {500, 0.30505, 0.35907, -11.324 }, + {525, 0.31320, 0.35968, -15.628 }, + {550, 0.32129, 0.36011, -23.325 }, + {575, 0.32931, 0.36038, -40.770 }, + {600, 0.33724, 0.36051, -116.45 } +}; + +#define NISO sizeof(isotempdata)/sizeof(ISOTEMPERATURE) + + +// Robertson's method +cmsBool CMSEXPORT cmsTempFromWhitePoint(cmsFloat64Number* TempK, const cmsCIExyY* WhitePoint) +{ + cmsUInt32Number j; + cmsFloat64Number us,vs; + cmsFloat64Number uj,vj,tj,di,dj,mi,mj; + cmsFloat64Number xs, ys; + + _cmsAssert(WhitePoint != NULL); + _cmsAssert(TempK != NULL); + + di = mi = 0; + xs = WhitePoint -> x; + ys = WhitePoint -> y; + + // convert (x,y) to CIE 1960 (u,WhitePoint) + + us = (2*xs) / (-xs + 6*ys + 1.5); + vs = (3*ys) / (-xs + 6*ys + 1.5); + + + for (j=0; j < NISO; j++) { + + uj = isotempdata[j].ut; + vj = isotempdata[j].vt; + tj = isotempdata[j].tt; + mj = isotempdata[j].mirek; + + dj = ((vs - vj) - tj * (us - uj)) / sqrt(1.0 + tj * tj); + + if ((j != 0) && (di/dj < 0.0)) { + + // Found a match + *TempK = 1000000.0 / (mi + (di / (di - dj)) * (mj - mi)); + return TRUE; + } + + di = dj; + mi = mj; + } + + // Not found + return FALSE; +} + + +// Compute chromatic adaptation matrix using Chad as cone matrix + +static +cmsBool ComputeChromaticAdaptation(cmsMAT3* Conversion, + const cmsCIEXYZ* SourceWhitePoint, + const cmsCIEXYZ* DestWhitePoint, + const cmsMAT3* Chad) + +{ + + cmsMAT3 Chad_Inv; + cmsVEC3 ConeSourceXYZ, ConeSourceRGB; + cmsVEC3 ConeDestXYZ, ConeDestRGB; + cmsMAT3 Cone, Tmp; + + + Tmp = *Chad; + if (!_cmsMAT3inverse(&Tmp, &Chad_Inv)) return FALSE; + + _cmsVEC3init(&ConeSourceXYZ, SourceWhitePoint -> X, + SourceWhitePoint -> Y, + SourceWhitePoint -> Z); + + _cmsVEC3init(&ConeDestXYZ, DestWhitePoint -> X, + DestWhitePoint -> Y, + DestWhitePoint -> Z); + + _cmsMAT3eval(&ConeSourceRGB, Chad, &ConeSourceXYZ); + _cmsMAT3eval(&ConeDestRGB, Chad, &ConeDestXYZ); + + // Build matrix + _cmsVEC3init(&Cone.v[0], ConeDestRGB.n[0]/ConeSourceRGB.n[0], 0.0, 0.0); + _cmsVEC3init(&Cone.v[1], 0.0, ConeDestRGB.n[1]/ConeSourceRGB.n[1], 0.0); + _cmsVEC3init(&Cone.v[2], 0.0, 0.0, ConeDestRGB.n[2]/ConeSourceRGB.n[2]); + + + // Normalize + _cmsMAT3per(&Tmp, &Cone, Chad); + _cmsMAT3per(Conversion, &Chad_Inv, &Tmp); + + return TRUE; +} + +// Returns the final chrmatic adaptation from illuminant FromIll to Illuminant ToIll +// The cone matrix can be specified in ConeMatrix. If NULL, Bradford is assumed +cmsBool _cmsAdaptationMatrix(cmsMAT3* r, const cmsMAT3* ConeMatrix, const cmsCIEXYZ* FromIll, const cmsCIEXYZ* ToIll) +{ + cmsMAT3 LamRigg = {{ // Bradford matrix + {{ 0.8951, 0.2664, -0.1614 }}, + {{ -0.7502, 1.7135, 0.0367 }}, + {{ 0.0389, -0.0685, 1.0296 }} + }}; + + if (ConeMatrix == NULL) + ConeMatrix = &LamRigg; + + return ComputeChromaticAdaptation(r, FromIll, ToIll, ConeMatrix); +} + +// Same as anterior, but assuming D50 destination. White point is given in xyY +static +cmsBool _cmsAdaptMatrixToD50(cmsMAT3* r, const cmsCIExyY* SourceWhitePt) +{ + cmsCIEXYZ Dn; + cmsMAT3 Bradford; + cmsMAT3 Tmp; + + cmsxyY2XYZ(&Dn, SourceWhitePt); + + if (!_cmsAdaptationMatrix(&Bradford, NULL, &Dn, cmsD50_XYZ())) return FALSE; + + Tmp = *r; + _cmsMAT3per(r, &Bradford, &Tmp); + + return TRUE; +} + +// Build a White point, primary chromas transfer matrix from RGB to CIE XYZ +// This is just an approximation, I am not handling all the non-linear +// aspects of the RGB to XYZ process, and assumming that the gamma correction +// has transitive property in the tranformation chain. +// +// the alghoritm: +// +// - First I build the absolute conversion matrix using +// primaries in XYZ. This matrix is next inverted +// - Then I eval the source white point across this matrix +// obtaining the coeficients of the transformation +// - Then, I apply these coeficients to the original matrix +// +cmsBool _cmsBuildRGB2XYZtransferMatrix(cmsMAT3* r, const cmsCIExyY* WhitePt, const cmsCIExyYTRIPLE* Primrs) +{ + cmsVEC3 WhitePoint, Coef; + cmsMAT3 Result, Primaries; + cmsFloat64Number xn, yn; + cmsFloat64Number xr, yr; + cmsFloat64Number xg, yg; + cmsFloat64Number xb, yb; + + xn = WhitePt -> x; + yn = WhitePt -> y; + xr = Primrs -> Red.x; + yr = Primrs -> Red.y; + xg = Primrs -> Green.x; + yg = Primrs -> Green.y; + xb = Primrs -> Blue.x; + yb = Primrs -> Blue.y; + + // Build Primaries matrix + _cmsVEC3init(&Primaries.v[0], xr, xg, xb); + _cmsVEC3init(&Primaries.v[1], yr, yg, yb); + _cmsVEC3init(&Primaries.v[2], (1-xr-yr), (1-xg-yg), (1-xb-yb)); + + + // Result = Primaries ^ (-1) inverse matrix + if (!_cmsMAT3inverse(&Primaries, &Result)) + return FALSE; + + + _cmsVEC3init(&WhitePoint, xn/yn, 1.0, (1.0-xn-yn)/yn); + + // Across inverse primaries ... + _cmsMAT3eval(&Coef, &Result, &WhitePoint); + + // Give us the Coefs, then I build transformation matrix + _cmsVEC3init(&r -> v[0], Coef.n[VX]*xr, Coef.n[VY]*xg, Coef.n[VZ]*xb); + _cmsVEC3init(&r -> v[1], Coef.n[VX]*yr, Coef.n[VY]*yg, Coef.n[VZ]*yb); + _cmsVEC3init(&r -> v[2], Coef.n[VX]*(1.0-xr-yr), Coef.n[VY]*(1.0-xg-yg), Coef.n[VZ]*(1.0-xb-yb)); + + + return _cmsAdaptMatrixToD50(r, WhitePt); + +} + + +// Adapts a color to a given illuminant. Original color is expected to have +// a SourceWhitePt white point. +cmsBool CMSEXPORT cmsAdaptToIlluminant(cmsCIEXYZ* Result, + const cmsCIEXYZ* SourceWhitePt, + const cmsCIEXYZ* Illuminant, + const cmsCIEXYZ* Value) +{ + cmsMAT3 Bradford; + cmsVEC3 In, Out; + + _cmsAssert(Result != NULL); + _cmsAssert(SourceWhitePt != NULL); + _cmsAssert(Illuminant != NULL); + _cmsAssert(Value != NULL); + + if (!_cmsAdaptationMatrix(&Bradford, NULL, SourceWhitePt, Illuminant)) return FALSE; + + _cmsVEC3init(&In, Value -> X, Value -> Y, Value -> Z); + _cmsMAT3eval(&Out, &Bradford, &In); + + Result -> X = Out.n[0]; + Result -> Y = Out.n[1]; + Result -> Z = Out.n[2]; + + return TRUE; +} + + diff --git a/jni/lcms2-2.5/src/cmsxform.c b/jni/lcms2-2.5/src/cmsxform.c new file mode 100644 index 00000000..37a21b3a --- /dev/null +++ b/jni/lcms2-2.5/src/cmsxform.c @@ -0,0 +1,972 @@ +//--------------------------------------------------------------------------------- +// +// Little Color Management System +// Copyright (c) 1998-2011 Marti Maria Saguer +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//--------------------------------------------------------------------------------- +// + +#include "lcms2_internal.h" + +// Transformations stuff +// ----------------------------------------------------------------------- + +// Alarm codes for 16-bit transformations, because the fixed range of containers there are +// no values left to mark out of gamut. volatile is C99 per 6.2.5 +static volatile cmsUInt16Number Alarm[cmsMAXCHANNELS] = { 0x7F00, 0x7F00, 0x7F00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static volatile cmsFloat64Number GlobalAdaptationState = 1; + +// The adaptation state may be defaulted by this function. If you don't like it, use the extended transform routine +cmsFloat64Number CMSEXPORT cmsSetAdaptationState(cmsFloat64Number d) +{ + cmsFloat64Number OldVal = GlobalAdaptationState; + + if (d >= 0) + GlobalAdaptationState = d; + + return OldVal; +} + +// Alarm codes are always global +void CMSEXPORT cmsSetAlarmCodes(cmsUInt16Number NewAlarm[cmsMAXCHANNELS]) +{ + int i; + + _cmsAssert(NewAlarm != NULL); + + for (i=0; i < cmsMAXCHANNELS; i++) + Alarm[i] = NewAlarm[i]; +} + +// You can get the codes cas well +void CMSEXPORT cmsGetAlarmCodes(cmsUInt16Number OldAlarm[cmsMAXCHANNELS]) +{ + int i; + + _cmsAssert(OldAlarm != NULL); + + for (i=0; i < cmsMAXCHANNELS; i++) + OldAlarm[i] = Alarm[i]; +} + +// Get rid of transform resources +void CMSEXPORT cmsDeleteTransform(cmsHTRANSFORM hTransform) +{ + _cmsTRANSFORM* p = (_cmsTRANSFORM*) hTransform; + + _cmsAssert(p != NULL); + + if (p -> GamutCheck) + cmsPipelineFree(p -> GamutCheck); + + if (p -> Lut) + cmsPipelineFree(p -> Lut); + + if (p ->InputColorant) + cmsFreeNamedColorList(p ->InputColorant); + + if (p -> OutputColorant) + cmsFreeNamedColorList(p ->OutputColorant); + + if (p ->Sequence) + cmsFreeProfileSequenceDescription(p ->Sequence); + + if (p ->UserData) + p ->FreeUserData(p ->ContextID, p ->UserData); + + _cmsFree(p ->ContextID, (void *) p); +} + +// Apply transform. +void CMSEXPORT cmsDoTransform(cmsHTRANSFORM Transform, + const void* InputBuffer, + void* OutputBuffer, + cmsUInt32Number Size) + +{ + _cmsTRANSFORM* p = (_cmsTRANSFORM*) Transform; + + p -> xform(p, InputBuffer, OutputBuffer, Size, Size); +} + + +// Apply transform. +void CMSEXPORT cmsDoTransformStride(cmsHTRANSFORM Transform, + const void* InputBuffer, + void* OutputBuffer, + cmsUInt32Number Size, cmsUInt32Number Stride) + +{ + _cmsTRANSFORM* p = (_cmsTRANSFORM*) Transform; + + p -> xform(p, InputBuffer, OutputBuffer, Size, Stride); +} + + +// Transform routines ---------------------------------------------------------------------------------------------------------- + +// Float xform converts floats. Since there are no performance issues, one routine does all job, including gamut check. +// Note that because extended range, we can use a -1.0 value for out of gamut in this case. +static +void FloatXFORM(_cmsTRANSFORM* p, + const void* in, + void* out, cmsUInt32Number Size, cmsUInt32Number Stride) +{ + cmsUInt8Number* accum; + cmsUInt8Number* output; + cmsFloat32Number fIn[cmsMAXCHANNELS], fOut[cmsMAXCHANNELS]; + cmsFloat32Number OutOfGamut; + cmsUInt32Number i, j; + + accum = (cmsUInt8Number*) in; + output = (cmsUInt8Number*) out; + + for (i=0; i < Size; i++) { + + accum = p -> FromInputFloat(p, fIn, accum, Stride); + + // Any gamut chack to do? + if (p ->GamutCheck != NULL) { + + // Evaluate gamut marker. + cmsPipelineEvalFloat( fIn, &OutOfGamut, p ->GamutCheck); + + // Is current color out of gamut? + if (OutOfGamut > 0.0) { + + // Certainly, out of gamut + for (j=0; j < cmsMAXCHANNELS; j++) + fOut[j] = -1.0; + + } + else { + // No, proceed normally + cmsPipelineEvalFloat(fIn, fOut, p -> Lut); + } + } + else { + + // No gamut check at all + cmsPipelineEvalFloat(fIn, fOut, p -> Lut); + } + + // Back to asked representation + output = p -> ToOutputFloat(p, fOut, output, Stride); + } +} + +// 16 bit precision ----------------------------------------------------------------------------------------------------------- + +// Null transformation, only applies formatters. No caché +static +void NullXFORM(_cmsTRANSFORM* p, + const void* in, + void* out, cmsUInt32Number Size, + cmsUInt32Number Stride) +{ + cmsUInt8Number* accum; + cmsUInt8Number* output; + cmsUInt16Number wIn[cmsMAXCHANNELS]; + cmsUInt32Number i, n; + + accum = (cmsUInt8Number*) in; + output = (cmsUInt8Number*) out; + n = Size; // Buffer len + + for (i=0; i < n; i++) { + + accum = p -> FromInput(p, wIn, accum, Stride); + output = p -> ToOutput(p, wIn, output, Stride); + } +} + + +// No gamut check, no cache, 16 bits +static +void PrecalculatedXFORM(_cmsTRANSFORM* p, + const void* in, + void* out, cmsUInt32Number Size, cmsUInt32Number Stride) +{ + register cmsUInt8Number* accum; + register cmsUInt8Number* output; + cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS]; + cmsUInt32Number i, n; + + accum = (cmsUInt8Number*) in; + output = (cmsUInt8Number*) out; + n = Size; + + for (i=0; i < n; i++) { + + accum = p -> FromInput(p, wIn, accum, Stride); + p ->Lut ->Eval16Fn(wIn, wOut, p -> Lut->Data); + output = p -> ToOutput(p, wOut, output, Stride); + } +} + + +// Auxiliar: Handle precalculated gamut check +static +void TransformOnePixelWithGamutCheck(_cmsTRANSFORM* p, + const cmsUInt16Number wIn[], + cmsUInt16Number wOut[]) +{ + cmsUInt16Number wOutOfGamut; + + p ->GamutCheck ->Eval16Fn(wIn, &wOutOfGamut, p ->GamutCheck ->Data); + if (wOutOfGamut >= 1) { + + cmsUInt16Number i; + + for (i=0; i < p ->Lut->OutputChannels; i++) + wOut[i] = Alarm[i]; + } + else + p ->Lut ->Eval16Fn(wIn, wOut, p -> Lut->Data); +} + +// Gamut check, No caché, 16 bits. +static +void PrecalculatedXFORMGamutCheck(_cmsTRANSFORM* p, + const void* in, + void* out, cmsUInt32Number Size, cmsUInt32Number Stride) +{ + cmsUInt8Number* accum; + cmsUInt8Number* output; + cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS]; + cmsUInt32Number i, n; + + accum = (cmsUInt8Number*) in; + output = (cmsUInt8Number*) out; + n = Size; // Buffer len + + for (i=0; i < n; i++) { + + accum = p -> FromInput(p, wIn, accum, Stride); + TransformOnePixelWithGamutCheck(p, wIn, wOut); + output = p -> ToOutput(p, wOut, output, Stride); + } +} + + +// No gamut check, Caché, 16 bits, +static +void CachedXFORM(_cmsTRANSFORM* p, + const void* in, + void* out, cmsUInt32Number Size, cmsUInt32Number Stride) +{ + cmsUInt8Number* accum; + cmsUInt8Number* output; + cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS]; + cmsUInt32Number i, n; + _cmsCACHE Cache; + + accum = (cmsUInt8Number*) in; + output = (cmsUInt8Number*) out; + n = Size; // Buffer len + + // Empty buffers for quick memcmp + memset(wIn, 0, sizeof(wIn)); + memset(wOut, 0, sizeof(wOut)); + + // Get copy of zero cache + memcpy(&Cache, &p ->Cache, sizeof(Cache)); + + for (i=0; i < n; i++) { + + accum = p -> FromInput(p, wIn, accum, Stride); + + if (memcmp(wIn, Cache.CacheIn, sizeof(Cache.CacheIn)) == 0) { + + memcpy(wOut, Cache.CacheOut, sizeof(Cache.CacheOut)); + } + else { + + p ->Lut ->Eval16Fn(wIn, wOut, p -> Lut->Data); + + memcpy(Cache.CacheIn, wIn, sizeof(Cache.CacheIn)); + memcpy(Cache.CacheOut, wOut, sizeof(Cache.CacheOut)); + } + + output = p -> ToOutput(p, wOut, output, Stride); + } + +} + + +// All those nice features together +static +void CachedXFORMGamutCheck(_cmsTRANSFORM* p, + const void* in, + void* out, cmsUInt32Number Size, cmsUInt32Number Stride) +{ + cmsUInt8Number* accum; + cmsUInt8Number* output; + cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS]; + cmsUInt32Number i, n; + _cmsCACHE Cache; + + accum = (cmsUInt8Number*) in; + output = (cmsUInt8Number*) out; + n = Size; // Buffer len + + // Empty buffers for quick memcmp + memset(wIn, 0, sizeof(cmsUInt16Number) * cmsMAXCHANNELS); + memset(wOut, 0, sizeof(cmsUInt16Number) * cmsMAXCHANNELS); + + // Get copy of zero cache + memcpy(&Cache, &p ->Cache, sizeof(Cache)); + + for (i=0; i < n; i++) { + + accum = p -> FromInput(p, wIn, accum, Stride); + + if (memcmp(wIn, Cache.CacheIn, sizeof(Cache.CacheIn)) == 0) { + memcpy(wOut, Cache.CacheOut, sizeof(Cache.CacheOut)); + } + else { + TransformOnePixelWithGamutCheck(p, wIn, wOut); + memcpy(Cache.CacheIn, wIn, sizeof(Cache.CacheIn)); + memcpy(Cache.CacheOut, wOut, sizeof(Cache.CacheOut)); + } + + output = p -> ToOutput(p, wOut, output, Stride); + } + +} + +// ------------------------------------------------------------------------------------------------------------- + +// List of used-defined transform factories +typedef struct _cmsTransformCollection_st { + + _cmsTransformFactory Factory; + struct _cmsTransformCollection_st *Next; + +} _cmsTransformCollection; + +// The linked list head +static _cmsTransformCollection* TransformCollection = NULL; + +// Register new ways to transform +cmsBool _cmsRegisterTransformPlugin(cmsContext id, cmsPluginBase* Data) +{ + cmsPluginTransform* Plugin = (cmsPluginTransform*) Data; + _cmsTransformCollection* fl; + + if (Data == NULL) { + + // Free the chain. Memory is safely freed at exit + TransformCollection = NULL; + return TRUE; + } + + // Factory callback is required + if (Plugin ->Factory == NULL) return FALSE; + + + fl = (_cmsTransformCollection*) _cmsPluginMalloc(id, sizeof(_cmsTransformCollection)); + if (fl == NULL) return FALSE; + + // Copy the parameters + fl ->Factory = Plugin ->Factory; + + // Keep linked list + fl ->Next = TransformCollection; + TransformCollection = fl; + + // All is ok + return TRUE; +} + + +void CMSEXPORT _cmsSetTransformUserData(struct _cmstransform_struct *CMMcargo, void* ptr, _cmsFreeUserDataFn FreePrivateDataFn) +{ + _cmsAssert(CMMcargo != NULL); + CMMcargo ->UserData = ptr; + CMMcargo ->FreeUserData = FreePrivateDataFn; +} + +// returns the pointer defined by the plug-in to store private data +void * CMSEXPORT _cmsGetTransformUserData(struct _cmstransform_struct *CMMcargo) +{ + _cmsAssert(CMMcargo != NULL); + return CMMcargo ->UserData; +} + +// returns the current formatters +void CMSEXPORT _cmsGetTransformFormatters16(struct _cmstransform_struct *CMMcargo, cmsFormatter16* FromInput, cmsFormatter16* ToOutput) +{ + _cmsAssert(CMMcargo != NULL); + if (FromInput) *FromInput = CMMcargo ->FromInput; + if (ToOutput) *ToOutput = CMMcargo ->ToOutput; +} + +void CMSEXPORT _cmsGetTransformFormattersFloat(struct _cmstransform_struct *CMMcargo, cmsFormatterFloat* FromInput, cmsFormatterFloat* ToOutput) +{ + _cmsAssert(CMMcargo != NULL); + if (FromInput) *FromInput = CMMcargo ->FromInputFloat; + if (ToOutput) *ToOutput = CMMcargo ->ToOutputFloat; +} + + +// Allocate transform struct and set it to defaults. Ask the optimization plug-in about if those formats are proper +// for separated transforms. If this is the case, +static +_cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut, + cmsUInt32Number Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags) +{ + _cmsTransformCollection* Plugin; + + // Allocate needed memory + _cmsTRANSFORM* p = (_cmsTRANSFORM*) _cmsMallocZero(ContextID, sizeof(_cmsTRANSFORM)); + if (!p) return NULL; + + // Store the proposed pipeline + p ->Lut = lut; + + // Let's see if any plug-in want to do the transform by itself + for (Plugin = TransformCollection; + Plugin != NULL; + Plugin = Plugin ->Next) { + + if (Plugin ->Factory(&p->xform, &p->UserData, &p ->FreeUserData, &p ->Lut, InputFormat, OutputFormat, dwFlags)) { + + // Last plugin in the declaration order takes control. We just keep + // the original parameters as a logging. + // Note that cmsFLAGS_CAN_CHANGE_FORMATTER is not set, so by default + // an optimized transform is not reusable. The plug-in can, however, change + // the flags and make it suitable. + + p ->ContextID = ContextID; + p ->InputFormat = *InputFormat; + p ->OutputFormat = *OutputFormat; + p ->dwOriginalFlags = *dwFlags; + + // Fill the formatters just in case the optimized routine is interested. + // No error is thrown if the formatter doesn't exist. It is up to the optimization + // factory to decide what to do in those cases. + p ->FromInput = _cmsGetFormatter(*InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16; + p ->ToOutput = _cmsGetFormatter(*OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16; + p ->FromInputFloat = _cmsGetFormatter(*InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat; + p ->ToOutputFloat = _cmsGetFormatter(*OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat; + + return p; + } + } + + // Not suitable for the transform plug-in, let's check the pipeline plug-in + if (p ->Lut != NULL) + _cmsOptimizePipeline(&p->Lut, Intent, InputFormat, OutputFormat, dwFlags); + + // Check whatever this is a true floating point transform + if (_cmsFormatterIsFloat(*InputFormat) && _cmsFormatterIsFloat(*OutputFormat)) { + + // Get formatter function always return a valid union, but the contents of this union may be NULL. + p ->FromInputFloat = _cmsGetFormatter(*InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat; + p ->ToOutputFloat = _cmsGetFormatter(*OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat; + *dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER; + + if (p ->FromInputFloat == NULL || p ->ToOutputFloat == NULL) { + + cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format"); + _cmsFree(ContextID, p); + return NULL; + } + + // Float transforms don't use caché, always are non-NULL + p ->xform = FloatXFORM; + } + else { + + if (*InputFormat == 0 && *OutputFormat == 0) { + p ->FromInput = p ->ToOutput = NULL; + *dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER; + } + else { + + int BytesPerPixelInput; + + p ->FromInput = _cmsGetFormatter(*InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16; + p ->ToOutput = _cmsGetFormatter(*OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16; + + if (p ->FromInput == NULL || p ->ToOutput == NULL) { + + cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format"); + _cmsFree(ContextID, p); + return NULL; + } + + BytesPerPixelInput = T_BYTES(p ->InputFormat); + if (BytesPerPixelInput == 0 || BytesPerPixelInput >= 2) + *dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER; + + } + + if (*dwFlags & cmsFLAGS_NULLTRANSFORM) { + + p ->xform = NullXFORM; + } + else { + if (*dwFlags & cmsFLAGS_NOCACHE) { + + if (*dwFlags & cmsFLAGS_GAMUTCHECK) + p ->xform = PrecalculatedXFORMGamutCheck; // Gamut check, no caché + else + p ->xform = PrecalculatedXFORM; // No caché, no gamut check + } + else { + + if (*dwFlags & cmsFLAGS_GAMUTCHECK) + p ->xform = CachedXFORMGamutCheck; // Gamut check, caché + else + p ->xform = CachedXFORM; // No gamut check, caché + + } + } + } + + p ->InputFormat = *InputFormat; + p ->OutputFormat = *OutputFormat; + p ->dwOriginalFlags = *dwFlags; + p ->ContextID = ContextID; + p ->UserData = NULL; + return p; +} + +static +cmsBool GetXFormColorSpaces(int nProfiles, cmsHPROFILE hProfiles[], cmsColorSpaceSignature* Input, cmsColorSpaceSignature* Output) +{ + cmsColorSpaceSignature ColorSpaceIn, ColorSpaceOut; + cmsColorSpaceSignature PostColorSpace; + int i; + + if (nProfiles <= 0) return FALSE; + if (hProfiles[0] == NULL) return FALSE; + + *Input = PostColorSpace = cmsGetColorSpace(hProfiles[0]); + + for (i=0; i < nProfiles; i++) { + + cmsProfileClassSignature cls; + cmsHPROFILE hProfile = hProfiles[i]; + + int lIsInput = (PostColorSpace != cmsSigXYZData) && + (PostColorSpace != cmsSigLabData); + + if (hProfile == NULL) return FALSE; + + cls = cmsGetDeviceClass(hProfile); + + if (cls == cmsSigNamedColorClass) { + + ColorSpaceIn = cmsSig1colorData; + ColorSpaceOut = (nProfiles > 1) ? cmsGetPCS(hProfile) : cmsGetColorSpace(hProfile); + } + else + if (lIsInput || (cls == cmsSigLinkClass)) { + + ColorSpaceIn = cmsGetColorSpace(hProfile); + ColorSpaceOut = cmsGetPCS(hProfile); + } + else + { + ColorSpaceIn = cmsGetPCS(hProfile); + ColorSpaceOut = cmsGetColorSpace(hProfile); + } + + if (i==0) + *Input = ColorSpaceIn; + + PostColorSpace = ColorSpaceOut; + } + + *Output = PostColorSpace; + + return TRUE; +} + +// Check colorspace +static +cmsBool IsProperColorSpace(cmsColorSpaceSignature Check, cmsUInt32Number dwFormat) +{ + int Space1 = T_COLORSPACE(dwFormat); + int Space2 = _cmsLCMScolorSpace(Check); + + if (Space1 == PT_ANY) return TRUE; + if (Space1 == Space2) return TRUE; + + if (Space1 == PT_LabV2 && Space2 == PT_Lab) return TRUE; + if (Space1 == PT_Lab && Space2 == PT_LabV2) return TRUE; + + return FALSE; +} + +// ---------------------------------------------------------------------------------------------------------------- + +static +void SetWhitePoint(cmsCIEXYZ* wtPt, const cmsCIEXYZ* src) +{ + if (src == NULL) { + wtPt ->X = cmsD50X; + wtPt ->Y = cmsD50Y; + wtPt ->Z = cmsD50Z; + } + else { + wtPt ->X = src->X; + wtPt ->Y = src->Y; + wtPt ->Z = src->Z; + } + +} + +// New to lcms 2.0 -- have all parameters available. +cmsHTRANSFORM CMSEXPORT cmsCreateExtendedTransform(cmsContext ContextID, + cmsUInt32Number nProfiles, cmsHPROFILE hProfiles[], + cmsBool BPC[], + cmsUInt32Number Intents[], + cmsFloat64Number AdaptationStates[], + cmsHPROFILE hGamutProfile, + cmsUInt32Number nGamutPCSposition, + cmsUInt32Number InputFormat, + cmsUInt32Number OutputFormat, + cmsUInt32Number dwFlags) +{ + _cmsTRANSFORM* xform; + cmsColorSpaceSignature EntryColorSpace; + cmsColorSpaceSignature ExitColorSpace; + cmsPipeline* Lut; + cmsUInt32Number LastIntent = Intents[nProfiles-1]; + + // If it is a fake transform + if (dwFlags & cmsFLAGS_NULLTRANSFORM) + { + return AllocEmptyTransform(ContextID, NULL, INTENT_PERCEPTUAL, &InputFormat, &OutputFormat, &dwFlags); + } + + // If gamut check is requested, make sure we have a gamut profile + if (dwFlags & cmsFLAGS_GAMUTCHECK) { + if (hGamutProfile == NULL) dwFlags &= ~cmsFLAGS_GAMUTCHECK; + } + + // On floating point transforms, inhibit cache + if (_cmsFormatterIsFloat(InputFormat) || _cmsFormatterIsFloat(OutputFormat)) + dwFlags |= cmsFLAGS_NOCACHE; + + // Mark entry/exit spaces + if (!GetXFormColorSpaces(nProfiles, hProfiles, &EntryColorSpace, &ExitColorSpace)) { + cmsSignalError(ContextID, cmsERROR_NULL, "NULL input profiles on transform"); + return NULL; + } + + // Check if proper colorspaces + if (!IsProperColorSpace(EntryColorSpace, InputFormat)) { + cmsSignalError(ContextID, cmsERROR_COLORSPACE_CHECK, "Wrong input color space on transform"); + return NULL; + } + + if (!IsProperColorSpace(ExitColorSpace, OutputFormat)) { + cmsSignalError(ContextID, cmsERROR_COLORSPACE_CHECK, "Wrong output color space on transform"); + return NULL; + } + + // Create a pipeline with all transformations + Lut = _cmsLinkProfiles(ContextID, nProfiles, Intents, hProfiles, BPC, AdaptationStates, dwFlags); + if (Lut == NULL) { + cmsSignalError(ContextID, cmsERROR_NOT_SUITABLE, "Couldn't link the profiles"); + return NULL; + } + + // Check channel count + if ((cmsChannelsOf(EntryColorSpace) != cmsPipelineInputChannels(Lut)) || + (cmsChannelsOf(ExitColorSpace) != cmsPipelineOutputChannels(Lut))) { + cmsSignalError(ContextID, cmsERROR_NOT_SUITABLE, "Channel count doesn't match. Profile is corrupted"); + return NULL; + } + + + // All seems ok + xform = AllocEmptyTransform(ContextID, Lut, LastIntent, &InputFormat, &OutputFormat, &dwFlags); + if (xform == NULL) { + return NULL; + } + + // Keep values + xform ->EntryColorSpace = EntryColorSpace; + xform ->ExitColorSpace = ExitColorSpace; + xform ->RenderingIntent = Intents[nProfiles-1]; + + // Take white points + SetWhitePoint(&xform->EntryWhitePoint, (cmsCIEXYZ*) cmsReadTag(hProfiles[0], cmsSigMediaWhitePointTag)); + SetWhitePoint(&xform->ExitWhitePoint, (cmsCIEXYZ*) cmsReadTag(hProfiles[nProfiles-1], cmsSigMediaWhitePointTag)); + + + // Create a gamut check LUT if requested + if (hGamutProfile != NULL && (dwFlags & cmsFLAGS_GAMUTCHECK)) + xform ->GamutCheck = _cmsCreateGamutCheckPipeline(ContextID, hProfiles, + BPC, Intents, + AdaptationStates, + nGamutPCSposition, + hGamutProfile); + + + // Try to read input and output colorant table + if (cmsIsTag(hProfiles[0], cmsSigColorantTableTag)) { + + // Input table can only come in this way. + xform ->InputColorant = cmsDupNamedColorList((cmsNAMEDCOLORLIST*) cmsReadTag(hProfiles[0], cmsSigColorantTableTag)); + } + + // Output is a little bit more complex. + if (cmsGetDeviceClass(hProfiles[nProfiles-1]) == cmsSigLinkClass) { + + // This tag may exist only on devicelink profiles. + if (cmsIsTag(hProfiles[nProfiles-1], cmsSigColorantTableOutTag)) { + + // It may be NULL if error + xform ->OutputColorant = cmsDupNamedColorList((cmsNAMEDCOLORLIST*) cmsReadTag(hProfiles[nProfiles-1], cmsSigColorantTableOutTag)); + } + + } else { + + if (cmsIsTag(hProfiles[nProfiles-1], cmsSigColorantTableTag)) { + + xform -> OutputColorant = cmsDupNamedColorList((cmsNAMEDCOLORLIST*) cmsReadTag(hProfiles[nProfiles-1], cmsSigColorantTableTag)); + } + } + + // Store the sequence of profiles + if (dwFlags & cmsFLAGS_KEEP_SEQUENCE) { + xform ->Sequence = _cmsCompileProfileSequence(ContextID, nProfiles, hProfiles); + } + else + xform ->Sequence = NULL; + + // If this is a cached transform, init first value, which is zero (16 bits only) + if (!(dwFlags & cmsFLAGS_NOCACHE)) { + + memset(&xform ->Cache.CacheIn, 0, sizeof(xform ->Cache.CacheIn)); + + if (xform ->GamutCheck != NULL) { + TransformOnePixelWithGamutCheck(xform, xform ->Cache.CacheIn, xform->Cache.CacheOut); + } + else { + + xform ->Lut ->Eval16Fn(xform ->Cache.CacheIn, xform->Cache.CacheOut, xform -> Lut->Data); + } + + } + + return (cmsHTRANSFORM) xform; +} + +// Multiprofile transforms: Gamut check is not available here, as it is unclear from which profile the gamut comes. +cmsHTRANSFORM CMSEXPORT cmsCreateMultiprofileTransformTHR(cmsContext ContextID, + cmsHPROFILE hProfiles[], + cmsUInt32Number nProfiles, + cmsUInt32Number InputFormat, + cmsUInt32Number OutputFormat, + cmsUInt32Number Intent, + cmsUInt32Number dwFlags) +{ + cmsUInt32Number i; + cmsBool BPC[256]; + cmsUInt32Number Intents[256]; + cmsFloat64Number AdaptationStates[256]; + + if (nProfiles <= 0 || nProfiles > 255) { + cmsSignalError(ContextID, cmsERROR_RANGE, "Wrong number of profiles. 1..255 expected, %d found.", nProfiles); + return NULL; + } + + for (i=0; i < nProfiles; i++) { + BPC[i] = dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION ? TRUE : FALSE; + Intents[i] = Intent; + AdaptationStates[i] = GlobalAdaptationState; + } + + + return cmsCreateExtendedTransform(ContextID, nProfiles, hProfiles, BPC, Intents, AdaptationStates, NULL, 0, InputFormat, OutputFormat, dwFlags); +} + + + +cmsHTRANSFORM CMSEXPORT cmsCreateMultiprofileTransform(cmsHPROFILE hProfiles[], + cmsUInt32Number nProfiles, + cmsUInt32Number InputFormat, + cmsUInt32Number OutputFormat, + cmsUInt32Number Intent, + cmsUInt32Number dwFlags) +{ + + if (nProfiles <= 0 || nProfiles > 255) { + cmsSignalError(NULL, cmsERROR_RANGE, "Wrong number of profiles. 1..255 expected, %d found.", nProfiles); + return NULL; + } + + return cmsCreateMultiprofileTransformTHR(cmsGetProfileContextID(hProfiles[0]), + hProfiles, + nProfiles, + InputFormat, + OutputFormat, + Intent, + dwFlags); +} + +cmsHTRANSFORM CMSEXPORT cmsCreateTransformTHR(cmsContext ContextID, + cmsHPROFILE Input, + cmsUInt32Number InputFormat, + cmsHPROFILE Output, + cmsUInt32Number OutputFormat, + cmsUInt32Number Intent, + cmsUInt32Number dwFlags) +{ + + cmsHPROFILE hArray[2]; + + hArray[0] = Input; + hArray[1] = Output; + + return cmsCreateMultiprofileTransformTHR(ContextID, hArray, Output == NULL ? 1 : 2, InputFormat, OutputFormat, Intent, dwFlags); +} + +CMSAPI cmsHTRANSFORM CMSEXPORT cmsCreateTransform(cmsHPROFILE Input, + cmsUInt32Number InputFormat, + cmsHPROFILE Output, + cmsUInt32Number OutputFormat, + cmsUInt32Number Intent, + cmsUInt32Number dwFlags) +{ + return cmsCreateTransformTHR(cmsGetProfileContextID(Input), Input, InputFormat, Output, OutputFormat, Intent, dwFlags); +} + + +cmsHTRANSFORM CMSEXPORT cmsCreateProofingTransformTHR(cmsContext ContextID, + cmsHPROFILE InputProfile, + cmsUInt32Number InputFormat, + cmsHPROFILE OutputProfile, + cmsUInt32Number OutputFormat, + cmsHPROFILE ProofingProfile, + cmsUInt32Number nIntent, + cmsUInt32Number ProofingIntent, + cmsUInt32Number dwFlags) +{ + cmsHPROFILE hArray[4]; + cmsUInt32Number Intents[4]; + cmsBool BPC[4]; + cmsFloat64Number Adaptation[4]; + cmsBool DoBPC = (dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION) ? TRUE : FALSE; + + + hArray[0] = InputProfile; hArray[1] = ProofingProfile; hArray[2] = ProofingProfile; hArray[3] = OutputProfile; + Intents[0] = nIntent; Intents[1] = nIntent; Intents[2] = INTENT_RELATIVE_COLORIMETRIC; Intents[3] = ProofingIntent; + BPC[0] = DoBPC; BPC[1] = DoBPC; BPC[2] = 0; BPC[3] = 0; + + Adaptation[0] = Adaptation[1] = Adaptation[2] = Adaptation[3] = GlobalAdaptationState; + + if (!(dwFlags & (cmsFLAGS_SOFTPROOFING|cmsFLAGS_GAMUTCHECK))) + return cmsCreateTransformTHR(ContextID, InputProfile, InputFormat, OutputProfile, OutputFormat, nIntent, dwFlags); + + return cmsCreateExtendedTransform(ContextID, 4, hArray, BPC, Intents, Adaptation, + ProofingProfile, 1, InputFormat, OutputFormat, dwFlags); + +} + + +cmsHTRANSFORM CMSEXPORT cmsCreateProofingTransform(cmsHPROFILE InputProfile, + cmsUInt32Number InputFormat, + cmsHPROFILE OutputProfile, + cmsUInt32Number OutputFormat, + cmsHPROFILE ProofingProfile, + cmsUInt32Number nIntent, + cmsUInt32Number ProofingIntent, + cmsUInt32Number dwFlags) +{ + return cmsCreateProofingTransformTHR(cmsGetProfileContextID(InputProfile), + InputProfile, + InputFormat, + OutputProfile, + OutputFormat, + ProofingProfile, + nIntent, + ProofingIntent, + dwFlags); +} + + +// Grab the ContextID from an open transform. Returns NULL if a NULL transform is passed +cmsContext CMSEXPORT cmsGetTransformContextID(cmsHTRANSFORM hTransform) +{ + _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform; + + if (xform == NULL) return NULL; + return xform -> ContextID; +} + +// Grab the input/output formats +cmsUInt32Number CMSEXPORT cmsGetTransformInputFormat(cmsHTRANSFORM hTransform) +{ + _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform; + + if (xform == NULL) return 0; + return xform->InputFormat; +} + +cmsUInt32Number CMSEXPORT cmsGetTransformOutputFormat(cmsHTRANSFORM hTransform) +{ + _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform; + + if (xform == NULL) return 0; + return xform->OutputFormat; +} + +// For backwards compatibility +cmsBool CMSEXPORT cmsChangeBuffersFormat(cmsHTRANSFORM hTransform, + cmsUInt32Number InputFormat, + cmsUInt32Number OutputFormat) +{ + + _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform; + cmsFormatter16 FromInput, ToOutput; + + + // We only can afford to change formatters if previous transform is at least 16 bits + if (!(xform ->dwOriginalFlags & cmsFLAGS_CAN_CHANGE_FORMATTER)) { + + cmsSignalError(xform ->ContextID, cmsERROR_NOT_SUITABLE, "cmsChangeBuffersFormat works only on transforms created originally with at least 16 bits of precision"); + return FALSE; + } + + FromInput = _cmsGetFormatter(InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16; + ToOutput = _cmsGetFormatter(OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16; + + if (FromInput == NULL || ToOutput == NULL) { + + cmsSignalError(xform -> ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format"); + return FALSE; + } + + xform ->InputFormat = InputFormat; + xform ->OutputFormat = OutputFormat; + xform ->FromInput = FromInput; + xform ->ToOutput = ToOutput; + return TRUE; +} diff --git a/jni/lcms2-2.5/src/lcms2.def b/jni/lcms2-2.5/src/lcms2.def new file mode 100644 index 00000000..def96803 --- /dev/null +++ b/jni/lcms2-2.5/src/lcms2.def @@ -0,0 +1,325 @@ +LIBRARY LCMS2.DLL + +EXPORTS + +_cms15Fixed16toDouble = _cms15Fixed16toDouble +_cms8Fixed8toDouble = _cms8Fixed8toDouble +cmsAdaptToIlluminant = cmsAdaptToIlluminant +_cmsAdjustEndianess16 = _cmsAdjustEndianess16 +_cmsAdjustEndianess32 = _cmsAdjustEndianess32 +_cmsAdjustEndianess64 = _cmsAdjustEndianess64 +cmsAllocNamedColorList = cmsAllocNamedColorList +cmsAllocProfileSequenceDescription = cmsAllocProfileSequenceDescription +cmsAppendNamedColor = cmsAppendNamedColor +cmsBFDdeltaE = cmsBFDdeltaE +cmsBuildGamma = cmsBuildGamma +cmsBuildParametricToneCurve = cmsBuildParametricToneCurve +cmsBuildSegmentedToneCurve = cmsBuildSegmentedToneCurve +cmsBuildTabulatedToneCurve16 = cmsBuildTabulatedToneCurve16 +cmsBuildTabulatedToneCurveFloat = cmsBuildTabulatedToneCurveFloat +_cmsCalloc = _cmsCalloc +cmsChannelsOf = cmsChannelsOf +cmsCIE2000DeltaE = cmsCIE2000DeltaE +cmsCIE94DeltaE = cmsCIE94DeltaE +cmsCIECAM02Done = cmsCIECAM02Done +cmsCIECAM02Forward = cmsCIECAM02Forward +cmsCIECAM02Init = cmsCIECAM02Init +cmsCIECAM02Reverse = cmsCIECAM02Reverse +cmsCloseIOhandler = cmsCloseIOhandler +cmsCloseProfile = cmsCloseProfile +cmsCMCdeltaE = cmsCMCdeltaE +cmsCreate_sRGBProfile = cmsCreate_sRGBProfile +cmsCreate_sRGBProfileTHR = cmsCreate_sRGBProfileTHR +cmsCreateBCHSWabstractProfile = cmsCreateBCHSWabstractProfile +cmsCreateBCHSWabstractProfileTHR = cmsCreateBCHSWabstractProfileTHR +cmsCreateExtendedTransform = cmsCreateExtendedTransform +cmsCreateGrayProfile = cmsCreateGrayProfile +cmsCreateGrayProfileTHR = cmsCreateGrayProfileTHR +cmsCreateInkLimitingDeviceLink = cmsCreateInkLimitingDeviceLink +cmsCreateInkLimitingDeviceLinkTHR = cmsCreateInkLimitingDeviceLinkTHR +cmsCreateLab2Profile = cmsCreateLab2Profile +cmsCreateLab2ProfileTHR = cmsCreateLab2ProfileTHR +cmsCreateLab4Profile = cmsCreateLab4Profile +cmsCreateLab4ProfileTHR = cmsCreateLab4ProfileTHR +cmsCreateLinearizationDeviceLink = cmsCreateLinearizationDeviceLink +cmsCreateLinearizationDeviceLinkTHR = cmsCreateLinearizationDeviceLinkTHR +cmsCreateMultiprofileTransform = cmsCreateMultiprofileTransform +cmsCreateMultiprofileTransformTHR = cmsCreateMultiprofileTransformTHR +cmsCreateNULLProfile = cmsCreateNULLProfile +cmsCreateNULLProfileTHR = cmsCreateNULLProfileTHR +cmsCreateProfilePlaceholder = cmsCreateProfilePlaceholder +cmsCreateProofingTransform = cmsCreateProofingTransform +cmsCreateProofingTransformTHR = cmsCreateProofingTransformTHR +cmsCreateRGBProfile = cmsCreateRGBProfile +cmsCreateRGBProfileTHR = cmsCreateRGBProfileTHR +cmsCreateTransform = cmsCreateTransform +cmsCreateTransformTHR = cmsCreateTransformTHR +cmsCreateXYZProfile = cmsCreateXYZProfile +cmsCreateXYZProfileTHR = cmsCreateXYZProfileTHR +cmsD50_xyY = cmsD50_xyY +cmsD50_XYZ = cmsD50_XYZ +_cmsDecodeDateTimeNumber = _cmsDecodeDateTimeNumber +_cmsDefaultICCintents = _cmsDefaultICCintents +cmsDeleteTransform = cmsDeleteTransform +cmsDeltaE = cmsDeltaE +cmsDetectBlackPoint = cmsDetectBlackPoint +cmsDetectDestinationBlackPoint = cmsDetectDestinationBlackPoint +cmsDetectTAC = cmsDetectTAC +cmsDesaturateLab = cmsDesaturateLab +cmsDoTransform = cmsDoTransform +cmsDoTransformStride = cmsDoTransformStride +_cmsDoubleTo15Fixed16 = _cmsDoubleTo15Fixed16 +_cmsDoubleTo8Fixed8 = _cmsDoubleTo8Fixed8 +_cmsDupMem = _cmsDupMem +cmsDupNamedColorList = cmsDupNamedColorList +cmsDupProfileSequenceDescription = cmsDupProfileSequenceDescription +cmsDupToneCurve = cmsDupToneCurve +_cmsEncodeDateTimeNumber = _cmsEncodeDateTimeNumber +cmsEstimateGamma = cmsEstimateGamma +cmsGetToneCurveEstimatedTableEntries = cmsGetToneCurveEstimatedTableEntries +cmsGetToneCurveEstimatedTable = cmsGetToneCurveEstimatedTable +cmsEvalToneCurve16 = cmsEvalToneCurve16 +cmsEvalToneCurveFloat = cmsEvalToneCurveFloat +cmsfilelength = cmsfilelength +cmsFloat2LabEncoded = cmsFloat2LabEncoded +cmsFloat2LabEncodedV2 = cmsFloat2LabEncodedV2 +cmsFloat2XYZEncoded = cmsFloat2XYZEncoded +cmsFormatterForColorspaceOfProfile = cmsFormatterForColorspaceOfProfile +cmsFormatterForPCSOfProfile = cmsFormatterForPCSOfProfile +_cmsFree = _cmsFree +cmsFreeNamedColorList = cmsFreeNamedColorList +cmsFreeProfileSequenceDescription = cmsFreeProfileSequenceDescription +cmsFreeToneCurve = cmsFreeToneCurve +cmsFreeToneCurveTriple = cmsFreeToneCurveTriple +cmsGBDAlloc = cmsGBDAlloc +cmsGBDFree = cmsGBDFree +cmsGDBAddPoint = cmsGDBAddPoint +cmsGDBCheckPoint = cmsGDBCheckPoint +cmsGDBCompute = cmsGDBCompute +cmsGetAlarmCodes = cmsGetAlarmCodes +cmsGetColorSpace = cmsGetColorSpace +cmsGetDeviceClass = cmsGetDeviceClass +cmsGetEncodedICCversion = cmsGetEncodedICCversion +cmsGetHeaderAttributes = cmsGetHeaderAttributes +cmsGetHeaderCreationDateTime = cmsGetHeaderCreationDateTime +cmsGetHeaderFlags = cmsGetHeaderFlags +cmsGetHeaderManufacturer = cmsGetHeaderManufacturer +cmsGetHeaderModel = cmsGetHeaderModel +cmsGetHeaderProfileID = cmsGetHeaderProfileID +cmsGetHeaderRenderingIntent = cmsGetHeaderRenderingIntent +cmsGetNamedColorList = cmsGetNamedColorList +cmsGetPCS = cmsGetPCS +cmsGetPostScriptColorResource = cmsGetPostScriptColorResource +cmsGetPostScriptCRD = cmsGetPostScriptCRD +cmsGetPostScriptCSA = cmsGetPostScriptCSA +cmsGetProfileInfo = cmsGetProfileInfo +cmsGetProfileInfoASCII = cmsGetProfileInfoASCII +cmsGetProfileContextID = cmsGetProfileContextID +cmsGetProfileVersion = cmsGetProfileVersion +cmsGetSupportedIntents = cmsGetSupportedIntents +cmsGetTagCount = cmsGetTagCount +cmsGetTagSignature = cmsGetTagSignature +cmsGetTransformContextID = cmsGetTransformContextID +_cmsICCcolorSpace = _cmsICCcolorSpace +_cmsIOPrintf = _cmsIOPrintf +cmsIsCLUT = cmsIsCLUT +cmsIsIntentSupported = cmsIsIntentSupported +cmsIsMatrixShaper = cmsIsMatrixShaper +cmsIsTag = cmsIsTag +cmsIsToneCurveDescending = cmsIsToneCurveDescending +cmsIsToneCurveLinear = cmsIsToneCurveLinear +cmsIsToneCurveMonotonic = cmsIsToneCurveMonotonic +cmsIsToneCurveMultisegment = cmsIsToneCurveMultisegment +cmsGetToneCurveParametricType = cmsGetToneCurveParametricType +cmsIT8Alloc = cmsIT8Alloc +cmsIT8DefineDblFormat = cmsIT8DefineDblFormat +cmsIT8EnumDataFormat = cmsIT8EnumDataFormat +cmsIT8EnumProperties = cmsIT8EnumProperties +cmsIT8EnumPropertyMulti = cmsIT8EnumPropertyMulti +cmsIT8Free = cmsIT8Free +cmsIT8GetData = cmsIT8GetData +cmsIT8GetDataDbl = cmsIT8GetDataDbl +cmsIT8FindDataFormat = cmsIT8FindDataFormat +cmsIT8GetDataRowCol = cmsIT8GetDataRowCol +cmsIT8GetDataRowColDbl = cmsIT8GetDataRowColDbl +cmsIT8GetPatchName = cmsIT8GetPatchName +cmsIT8GetPatchByName = cmsIT8GetPatchByName +cmsIT8GetProperty = cmsIT8GetProperty +cmsIT8GetPropertyDbl = cmsIT8GetPropertyDbl +cmsIT8GetPropertyMulti = cmsIT8GetPropertyMulti +cmsIT8GetSheetType = cmsIT8GetSheetType +cmsIT8LoadFromFile = cmsIT8LoadFromFile +cmsIT8LoadFromMem = cmsIT8LoadFromMem +cmsIT8SaveToFile = cmsIT8SaveToFile +cmsIT8SaveToMem = cmsIT8SaveToMem +cmsIT8SetComment = cmsIT8SetComment +cmsIT8SetData = cmsIT8SetData +cmsIT8SetDataDbl = cmsIT8SetDataDbl +cmsIT8SetDataFormat = cmsIT8SetDataFormat +cmsIT8SetDataRowCol = cmsIT8SetDataRowCol +cmsIT8SetDataRowColDbl = cmsIT8SetDataRowColDbl +cmsIT8SetPropertyDbl = cmsIT8SetPropertyDbl +cmsIT8SetPropertyHex = cmsIT8SetPropertyHex +cmsIT8SetPropertyStr = cmsIT8SetPropertyStr +cmsIT8SetPropertyMulti = cmsIT8SetPropertyMulti +cmsIT8SetPropertyUncooked = cmsIT8SetPropertyUncooked +cmsIT8SetSheetType = cmsIT8SetSheetType +cmsIT8SetTable = cmsIT8SetTable +cmsIT8SetTableByLabel = cmsIT8SetTableByLabel +cmsIT8SetIndexColumn = cmsIT8SetIndexColumn +cmsIT8TableCount = cmsIT8TableCount +cmsJoinToneCurve = cmsJoinToneCurve +cmsLab2LCh = cmsLab2LCh +cmsLab2XYZ = cmsLab2XYZ +cmsLabEncoded2Float = cmsLabEncoded2Float +cmsLabEncoded2FloatV2 = cmsLabEncoded2FloatV2 +cmsLCh2Lab = cmsLCh2Lab +_cmsLCMScolorSpace = _cmsLCMScolorSpace +cmsLinkTag = cmsLinkTag +cmsTagLinkedTo = cmsTagLinkedTo +cmsPipelineAlloc = cmsPipelineAlloc +cmsPipelineCat = cmsPipelineCat +cmsPipelineCheckAndRetreiveStages = cmsPipelineCheckAndRetreiveStages +cmsPipelineDup = cmsPipelineDup +cmsPipelineStageCount = cmsPipelineStageCount +cmsPipelineEval16 = cmsPipelineEval16 +cmsPipelineEvalFloat = cmsPipelineEvalFloat +cmsPipelineEvalReverseFloat = cmsPipelineEvalReverseFloat +cmsPipelineFree = cmsPipelineFree +cmsPipelineGetPtrToFirstStage = cmsPipelineGetPtrToFirstStage +cmsPipelineGetPtrToLastStage = cmsPipelineGetPtrToLastStage +cmsPipelineInputChannels = cmsPipelineInputChannels +cmsPipelineInsertStage = cmsPipelineInsertStage +cmsPipelineOutputChannels = cmsPipelineOutputChannels +cmsPipelineSetSaveAs8bitsFlag = cmsPipelineSetSaveAs8bitsFlag +_cmsPipelineSetOptimizationParameters = _cmsPipelineSetOptimizationParameters +cmsPipelineUnlinkStage = cmsPipelineUnlinkStage +_cmsMalloc = _cmsMalloc +_cmsMallocZero = _cmsMallocZero +_cmsMAT3eval = _cmsMAT3eval +_cmsMAT3identity = _cmsMAT3identity +_cmsMAT3inverse = _cmsMAT3inverse +_cmsMAT3isIdentity = _cmsMAT3isIdentity +_cmsMAT3per = _cmsMAT3per +_cmsMAT3solve = _cmsMAT3solve +cmsMD5computeID = cmsMD5computeID +cmsMLUalloc = cmsMLUalloc +cmsMLUdup = cmsMLUdup +cmsMLUfree = cmsMLUfree +cmsMLUgetASCII = cmsMLUgetASCII +cmsMLUgetTranslation = cmsMLUgetTranslation +cmsMLUgetWide = cmsMLUgetWide +cmsMLUsetASCII = cmsMLUsetASCII +cmsMLUsetWide = cmsMLUsetWide +cmsStageAllocCLut16bit = cmsStageAllocCLut16bit +cmsStageAllocCLut16bitGranular = cmsStageAllocCLut16bitGranular +cmsStageAllocCLutFloat = cmsStageAllocCLutFloat +cmsStageAllocCLutFloatGranular = cmsStageAllocCLutFloatGranular +cmsStageAllocToneCurves = cmsStageAllocToneCurves +cmsStageAllocIdentity = cmsStageAllocIdentity +cmsStageAllocMatrix = cmsStageAllocMatrix +_cmsStageAllocPlaceholder = _cmsStageAllocPlaceholder +cmsStageDup = cmsStageDup +cmsStageFree = cmsStageFree +cmsStageNext = cmsStageNext +cmsStageInputChannels = cmsStageInputChannels +cmsStageOutputChannels = cmsStageOutputChannels +cmsStageSampleCLut16bit = cmsStageSampleCLut16bit +cmsStageSampleCLutFloat = cmsStageSampleCLutFloat +cmsStageType = cmsStageType +cmsStageData = cmsStageData +cmsNamedColorCount = cmsNamedColorCount +cmsNamedColorIndex = cmsNamedColorIndex +cmsNamedColorInfo = cmsNamedColorInfo +cmsOpenIOhandlerFromFile = cmsOpenIOhandlerFromFile +cmsOpenIOhandlerFromMem = cmsOpenIOhandlerFromMem +cmsOpenIOhandlerFromNULL = cmsOpenIOhandlerFromNULL +cmsOpenIOhandlerFromStream = cmsOpenIOhandlerFromStream +cmsOpenProfileFromFile = cmsOpenProfileFromFile +cmsOpenProfileFromFileTHR = cmsOpenProfileFromFileTHR +cmsOpenProfileFromIOhandlerTHR = cmsOpenProfileFromIOhandlerTHR +cmsOpenProfileFromMem = cmsOpenProfileFromMem +cmsOpenProfileFromMemTHR = cmsOpenProfileFromMemTHR +cmsOpenProfileFromStream = cmsOpenProfileFromStream +cmsOpenProfileFromStreamTHR = cmsOpenProfileFromStreamTHR +cmsPlugin = cmsPlugin +_cmsRead15Fixed16Number = _cmsRead15Fixed16Number +_cmsReadAlignment = _cmsReadAlignment +_cmsReadFloat32Number = _cmsReadFloat32Number +cmsReadRawTag = cmsReadRawTag +cmsReadTag = cmsReadTag +_cmsReadTypeBase = _cmsReadTypeBase +_cmsReadUInt16Array = _cmsReadUInt16Array +_cmsReadUInt16Number = _cmsReadUInt16Number +_cmsReadUInt32Number = _cmsReadUInt32Number +_cmsReadUInt64Number = _cmsReadUInt64Number +_cmsReadUInt8Number = _cmsReadUInt8Number +_cmsReadXYZNumber = _cmsReadXYZNumber +_cmsRealloc = _cmsRealloc +cmsReverseToneCurve = cmsReverseToneCurve +cmsReverseToneCurveEx = cmsReverseToneCurveEx +cmsSaveProfileToFile = cmsSaveProfileToFile +cmsSaveProfileToIOhandler = cmsSaveProfileToIOhandler +cmsSaveProfileToMem = cmsSaveProfileToMem +cmsSaveProfileToStream = cmsSaveProfileToStream +cmsSetAdaptationState = cmsSetAdaptationState +cmsSetAlarmCodes = cmsSetAlarmCodes +cmsSetColorSpace = cmsSetColorSpace +cmsSetDeviceClass = cmsSetDeviceClass +cmsSetEncodedICCversion = cmsSetEncodedICCversion +cmsSetHeaderAttributes = cmsSetHeaderAttributes +cmsSetHeaderFlags = cmsSetHeaderFlags +cmsSetHeaderManufacturer = cmsSetHeaderManufacturer +cmsSetHeaderModel = cmsSetHeaderModel +cmsSetHeaderProfileID = cmsSetHeaderProfileID +cmsSetHeaderRenderingIntent = cmsSetHeaderRenderingIntent +cmsSetLogErrorHandler = cmsSetLogErrorHandler +cmsSetPCS = cmsSetPCS +cmsSetProfileVersion = cmsSetProfileVersion +cmsSignalError = cmsSignalError +cmsSmoothToneCurve = cmsSmoothToneCurve +cmsstrcasecmp = cmsstrcasecmp +cmsTempFromWhitePoint = cmsTempFromWhitePoint +cmsTransform2DeviceLink = cmsTransform2DeviceLink +cmsUnregisterPlugins = cmsUnregisterPlugins +_cmsVEC3cross = _cmsVEC3cross +_cmsVEC3distance = _cmsVEC3distance +_cmsVEC3dot = _cmsVEC3dot +_cmsVEC3init = _cmsVEC3init +_cmsVEC3length = _cmsVEC3length +_cmsVEC3minus = _cmsVEC3minus +cmsWhitePointFromTemp = cmsWhitePointFromTemp +_cmsWrite15Fixed16Number = _cmsWrite15Fixed16Number +_cmsWriteAlignment = _cmsWriteAlignment +_cmsWriteFloat32Number = _cmsWriteFloat32Number +cmsWriteRawTag = cmsWriteRawTag +cmsWriteTag = cmsWriteTag +_cmsWriteTypeBase = _cmsWriteTypeBase +_cmsWriteUInt16Array = _cmsWriteUInt16Array +_cmsWriteUInt16Number = _cmsWriteUInt16Number +_cmsWriteUInt32Number = _cmsWriteUInt32Number +_cmsWriteUInt64Number = _cmsWriteUInt64Number +_cmsWriteUInt8Number = _cmsWriteUInt8Number +_cmsWriteXYZNumber = _cmsWriteXYZNumber +cmsxyY2XYZ = cmsxyY2XYZ +cmsXYZ2Lab = cmsXYZ2Lab +cmsXYZ2xyY = cmsXYZ2xyY +cmsXYZEncoded2Float = cmsXYZEncoded2Float +cmsSliceSpace16 = cmsSliceSpace16 +cmsSliceSpaceFloat = cmsSliceSpaceFloat +cmsChangeBuffersFormat = cmsChangeBuffersFormat +cmsDictAlloc = cmsDictAlloc +cmsDictFree = cmsDictFree +cmsDictDup = cmsDictDup +cmsDictAddEntry = cmsDictAddEntry +cmsDictGetEntryList = cmsDictGetEntryList +cmsDictNextEntry = cmsDictNextEntry +_cmsGetTransformUserData = _cmsGetTransformUserData +_cmsSetTransformUserData = _cmsSetTransformUserData +_cmsGetTransformFormatters16 = _cmsGetTransformFormatters16 +_cmsGetTransformFormattersFloat = _cmsGetTransformFormattersFloat +cmsGetHeaderCreator = cmsGetHeaderCreator +cmsPluginTHR = cmsPluginTHR +cmsGetPipelineContextID = cmsGetPipelineContextID +cmsGetTransformInputFormat = cmsGetTransformInputFormat +cmsGetTransformOutputFormat = cmsGetTransformOutputFormat diff --git a/jni/lcms2-2.5/src/lcms2_internal.h b/jni/lcms2-2.5/src/lcms2_internal.h new file mode 100644 index 00000000..d6300dfb --- /dev/null +++ b/jni/lcms2-2.5/src/lcms2_internal.h @@ -0,0 +1,611 @@ + +// +// Little Color Management System +// Copyright (c) 1998-2011 Marti Maria Saguer +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +//--------------------------------------------------------------------------------- +// + +#ifndef _lcms_internal_H + +// Include plug-in foundation +#ifndef _lcms_plugin_H +# include "lcms2_plugin.h" +#endif + +// ctype is part of C99 as per 7.1.2 +#include + +// assert macro is part of C99 as per 7.2 +#include + +// Some needed constants +#ifndef M_PI +# define M_PI 3.14159265358979323846 +#endif + +#ifndef M_LOG10E +# define M_LOG10E 0.434294481903251827651 +#endif + +// BorlandC 5.5, VC2003 are broken on that +#if defined(__BORLANDC__) || (_MSC_VER < 1400) // 1400 == VC++ 8.0 +#define sinf(x) (float)sin((float)x) +#define sqrtf(x) (float)sqrt((float)x) +#endif + + +// Alignment of ICC file format uses 4 bytes (cmsUInt32Number) +#define _cmsALIGNLONG(x) (((x)+(sizeof(cmsUInt32Number)-1)) & ~(sizeof(cmsUInt32Number)-1)) + +// Alignment to memory pointer +#define _cmsALIGNMEM(x) (((x)+(sizeof(void *) - 1)) & ~(sizeof(void *) - 1)) + +// Maximum encodeable values in floating point +#define MAX_ENCODEABLE_XYZ (1.0 + 32767.0/32768.0) +#define MIN_ENCODEABLE_ab2 (-128.0) +#define MAX_ENCODEABLE_ab2 ((65535.0/256.0) - 128.0) +#define MIN_ENCODEABLE_ab4 (-128.0) +#define MAX_ENCODEABLE_ab4 (127.0) + +// Maximum of channels for internal pipeline evaluation +#define MAX_STAGE_CHANNELS 128 + +// Unused parameter warning supression +#define cmsUNUSED_PARAMETER(x) ((void)x) + +// The specification for "inline" is section 6.7.4 of the C99 standard (ISO/IEC 9899:1999). +// unfortunately VisualC++ does not conform that +#if defined(_MSC_VER) || defined(__BORLANDC__) +# define cmsINLINE __inline +#else +# define cmsINLINE static inline +#endif + +// Other replacement functions +#ifdef _MSC_VER +# ifndef snprintf +# define snprintf _snprintf +# endif +# ifndef vsnprintf +# define vsnprintf _vsnprintf +# endif +#endif + + +// A fast way to convert from/to 16 <-> 8 bits +#define FROM_8_TO_16(rgb) (cmsUInt16Number) ((((cmsUInt16Number) (rgb)) << 8)|(rgb)) +#define FROM_16_TO_8(rgb) (cmsUInt8Number) ((((rgb) * 65281 + 8388608) >> 24) & 0xFF) + +// Code analysis is broken on asserts +#ifdef _MSC_VER +# if (_MSC_VER >= 1500) +# define _cmsAssert(a) { assert((a)); __analysis_assume((a)); } +# else +# define _cmsAssert(a) assert((a)) +# endif +#else +# define _cmsAssert(a) assert((a)) +#endif + +//--------------------------------------------------------------------------------- + +// Determinant lower than that are assumed zero (used on matrix invert) +#define MATRIX_DET_TOLERANCE 0.0001 + +//--------------------------------------------------------------------------------- + +// Fixed point +#define FIXED_TO_INT(x) ((x)>>16) +#define FIXED_REST_TO_INT(x) ((x)&0xFFFFU) +#define ROUND_FIXED_TO_INT(x) (((x)+0x8000)>>16) + +cmsINLINE cmsS15Fixed16Number _cmsToFixedDomain(int a) { return a + ((a + 0x7fff) / 0xffff); } +cmsINLINE int _cmsFromFixedDomain(cmsS15Fixed16Number a) { return a - ((a + 0x7fff) >> 16); } + +// ----------------------------------------------------------------------------------------------------------- + +// Fast floor conversion logic. Thanks to Sree Kotay and Stuart Nixon +// note than this only works in the range ..-32767...+32767 because +// mantissa is interpreted as 15.16 fixed point. +// The union is to avoid pointer aliasing overoptimization. +cmsINLINE int _cmsQuickFloor(cmsFloat64Number val) +{ +#ifdef CMS_DONT_USE_FAST_FLOOR + return (int) floor(val); +#else + const cmsFloat64Number _lcms_double2fixmagic = 68719476736.0 * 1.5; // 2^36 * 1.5, (52-16=36) uses limited precision to floor + union { + cmsFloat64Number val; + int halves[2]; + } temp; + + temp.val = val + _lcms_double2fixmagic; + +#ifdef CMS_USE_BIG_ENDIAN + return temp.halves[1] >> 16; +#else + return temp.halves[0] >> 16; +#endif +#endif +} + +// Fast floor restricted to 0..65535.0 +cmsINLINE cmsUInt16Number _cmsQuickFloorWord(cmsFloat64Number d) +{ + return (cmsUInt16Number) _cmsQuickFloor(d - 32767.0) + 32767U; +} + +// Floor to word, taking care of saturation +cmsINLINE cmsUInt16Number _cmsQuickSaturateWord(cmsFloat64Number d) +{ + d += 0.5; + if (d <= 0) return 0; + if (d >= 65535.0) return 0xffff; + + return _cmsQuickFloorWord(d); +} + +// Plug-In registering --------------------------------------------------------------- + +// Specialized function for plug-in memory management. No pairing free() since whole pool is freed at once. +void* _cmsPluginMalloc(cmsContext ContextID, cmsUInt32Number size); + +// Memory management +cmsBool _cmsRegisterMemHandlerPlugin(cmsPluginBase* Plugin); + +// Interpolation +cmsBool _cmsRegisterInterpPlugin(cmsPluginBase* Plugin); + +// Parametric curves +cmsBool _cmsRegisterParametricCurvesPlugin(cmsContext ContextID, cmsPluginBase* Plugin); + +// Formatters management +cmsBool _cmsRegisterFormattersPlugin(cmsContext ContextID, cmsPluginBase* Plugin); + +// Tag type management +cmsBool _cmsRegisterTagTypePlugin(cmsContext ContextID, cmsPluginBase* Plugin); + +// Tag management +cmsBool _cmsRegisterTagPlugin(cmsContext ContextID, cmsPluginBase* Plugin); + +// Intent management +cmsBool _cmsRegisterRenderingIntentPlugin(cmsContext ContextID, cmsPluginBase* Plugin); + +// Multi Process elements +cmsBool _cmsRegisterMultiProcessElementPlugin(cmsContext ContextID, cmsPluginBase* Plugin); + +// Optimization +cmsBool _cmsRegisterOptimizationPlugin(cmsContext ContextID, cmsPluginBase* Plugin); + +// Transform +cmsBool _cmsRegisterTransformPlugin(cmsContext ContextID, cmsPluginBase* Plugin); + +// --------------------------------------------------------------------------------------------------------- + +// Suballocators. Those are blocks of memory that is freed at the end on whole block. +typedef struct _cmsSubAllocator_chunk_st { + + cmsUInt8Number* Block; + cmsUInt32Number BlockSize; + cmsUInt32Number Used; + + struct _cmsSubAllocator_chunk_st* next; + +} _cmsSubAllocator_chunk; + + +typedef struct { + + cmsContext ContextID; + _cmsSubAllocator_chunk* h; + +} _cmsSubAllocator; + + +_cmsSubAllocator* _cmsCreateSubAlloc(cmsContext ContextID, cmsUInt32Number Initial); +void _cmsSubAllocDestroy(_cmsSubAllocator* s); +void* _cmsSubAlloc(_cmsSubAllocator* s, cmsUInt32Number size); + +// ---------------------------------------------------------------------------------- + +// MLU internal representation +typedef struct { + + cmsUInt16Number Language; + cmsUInt16Number Country; + + cmsUInt32Number StrW; // Offset to current unicode string + cmsUInt32Number Len; // Length in bytes + +} _cmsMLUentry; + +struct _cms_MLU_struct { + + cmsContext ContextID; + + // The directory + int AllocatedEntries; + int UsedEntries; + _cmsMLUentry* Entries; // Array of pointers to strings allocated in MemPool + + // The Pool + cmsUInt32Number PoolSize; // The maximum allocated size + cmsUInt32Number PoolUsed; // The used size + void* MemPool; // Pointer to begin of memory pool +}; + +// Named color list internal representation +typedef struct { + + char Name[cmsMAX_PATH]; + cmsUInt16Number PCS[3]; + cmsUInt16Number DeviceColorant[cmsMAXCHANNELS]; + +} _cmsNAMEDCOLOR; + +struct _cms_NAMEDCOLORLIST_struct { + + cmsUInt32Number nColors; + cmsUInt32Number Allocated; + cmsUInt32Number ColorantCount; + + char Prefix[33]; // Prefix and suffix are defined to be 32 characters at most + char Suffix[33]; + + _cmsNAMEDCOLOR* List; + + cmsContext ContextID; +}; + + +// ---------------------------------------------------------------------------------- + +// This is the internal struct holding profile details. + +// Maximum supported tags in a profile +#define MAX_TABLE_TAG 100 + +typedef struct _cms_iccprofile_struct { + + // I/O handler + cmsIOHANDLER* IOhandler; + + // The thread ID + cmsContext ContextID; + + // Creation time + struct tm Created; + + // Only most important items found in ICC profiles + cmsUInt32Number Version; + cmsProfileClassSignature DeviceClass; + cmsColorSpaceSignature ColorSpace; + cmsColorSpaceSignature PCS; + cmsUInt32Number RenderingIntent; + + cmsUInt32Number flags; + cmsUInt32Number manufacturer, model; + cmsUInt64Number attributes; + cmsUInt32Number creator; + + cmsProfileID ProfileID; + + // Dictionary + cmsUInt32Number TagCount; + cmsTagSignature TagNames[MAX_TABLE_TAG]; + cmsTagSignature TagLinked[MAX_TABLE_TAG]; // The tag to wich is linked (0=none) + cmsUInt32Number TagSizes[MAX_TABLE_TAG]; // Size on disk + cmsUInt32Number TagOffsets[MAX_TABLE_TAG]; + cmsBool TagSaveAsRaw[MAX_TABLE_TAG]; // True to write uncooked + void * TagPtrs[MAX_TABLE_TAG]; + cmsTagTypeHandler* TagTypeHandlers[MAX_TABLE_TAG]; // Same structure may be serialized on different types + // depending on profile version, so we keep track of the // type handler for each tag in the list. + // Special + cmsBool IsWrite; + +} _cmsICCPROFILE; + +// IO helpers for profiles +cmsBool _cmsReadHeader(_cmsICCPROFILE* Icc); +cmsBool _cmsWriteHeader(_cmsICCPROFILE* Icc, cmsUInt32Number UsedSpace); +int _cmsSearchTag(_cmsICCPROFILE* Icc, cmsTagSignature sig, cmsBool lFollowLinks); + +// Tag types +cmsTagTypeHandler* _cmsGetTagTypeHandler(cmsTagTypeSignature sig); +cmsTagTypeSignature _cmsGetTagTrueType(cmsHPROFILE hProfile, cmsTagSignature sig); +cmsTagDescriptor* _cmsGetTagDescriptor(cmsTagSignature sig); + +// Error logging --------------------------------------------------------------------------------------------------------- + +void _cmsTagSignature2String(char String[5], cmsTagSignature sig); + +// Interpolation --------------------------------------------------------------------------------------------------------- + +cmsInterpParams* _cmsComputeInterpParams(cmsContext ContextID, int nSamples, int InputChan, int OutputChan, const void* Table, cmsUInt32Number dwFlags); +cmsInterpParams* _cmsComputeInterpParamsEx(cmsContext ContextID, const cmsUInt32Number nSamples[], int InputChan, int OutputChan, const void* Table, cmsUInt32Number dwFlags); +void _cmsFreeInterpParams(cmsInterpParams* p); +cmsBool _cmsSetInterpolationRoutine(cmsInterpParams* p); + +// Curves ---------------------------------------------------------------------------------------------------------------- + +// This struct holds information about a segment, plus a pointer to the function that implements the evaluation. +// In the case of table-based, Eval pointer is set to NULL + +// The gamma function main structure +struct _cms_curve_struct { + + cmsInterpParams* InterpParams; // Private optimizations for interpolation + + cmsUInt32Number nSegments; // Number of segments in the curve. Zero for a 16-bit based tables + cmsCurveSegment* Segments; // The segments + cmsInterpParams** SegInterp; // Array of private optimizations for interpolation in table-based segments + + cmsParametricCurveEvaluator* Evals; // Evaluators (one per segment) + + // 16 bit Table-based representation follows + cmsUInt32Number nEntries; // Number of table elements + cmsUInt16Number* Table16; // The table itself. +}; + + +// Pipelines & Stages --------------------------------------------------------------------------------------------- + +// A single stage +struct _cmsStage_struct { + + cmsContext ContextID; + + cmsStageSignature Type; // Identifies the stage + cmsStageSignature Implements; // Identifies the *function* of the stage (for optimizations) + + cmsUInt32Number InputChannels; // Input channels -- for optimization purposes + cmsUInt32Number OutputChannels; // Output channels -- for optimization purposes + + _cmsStageEvalFn EvalPtr; // Points to fn that evaluates the stage (always in floating point) + _cmsStageDupElemFn DupElemPtr; // Points to a fn that duplicates the *data* of the stage + _cmsStageFreeElemFn FreePtr; // Points to a fn that sets the *data* of the stage free + + // A generic pointer to whatever memory needed by the stage + void* Data; + + // Maintains linked list (used internally) + struct _cmsStage_struct* Next; +}; + + +// Special Stages (cannot be saved) +cmsStage* _cmsStageAllocLab2XYZ(cmsContext ContextID); +cmsStage* _cmsStageAllocXYZ2Lab(cmsContext ContextID); +cmsStage* _cmsStageAllocLabPrelin(cmsContext ContextID); +cmsStage* _cmsStageAllocLabV2ToV4(cmsContext ContextID); +cmsStage* _cmsStageAllocLabV2ToV4curves(cmsContext ContextID); +cmsStage* _cmsStageAllocLabV4ToV2(cmsContext ContextID); +cmsStage* _cmsStageAllocNamedColor(cmsNAMEDCOLORLIST* NamedColorList, cmsBool UsePCS); +cmsStage* _cmsStageAllocIdentityCurves(cmsContext ContextID, int nChannels); +cmsStage* _cmsStageAllocIdentityCLut(cmsContext ContextID, int nChan); +cmsStage* _cmsStageNormalizeFromLabFloat(cmsContext ContextID); +cmsStage* _cmsStageNormalizeFromXyzFloat(cmsContext ContextID); +cmsStage* _cmsStageNormalizeToLabFloat(cmsContext ContextID); +cmsStage* _cmsStageNormalizeToXyzFloat(cmsContext ContextID); + +// For curve set only +cmsToneCurve** _cmsStageGetPtrToCurveSet(const cmsStage* mpe); + + +// Pipeline Evaluator (in floating point) +typedef void (* _cmsPipelineEvalFloatFn)(const cmsFloat32Number In[], + cmsFloat32Number Out[], + const void* Data); + +struct _cmsPipeline_struct { + + cmsStage* Elements; // Points to elements chain + cmsUInt32Number InputChannels, OutputChannels; + + // Data & evaluators + void *Data; + + _cmsOPTeval16Fn Eval16Fn; + _cmsPipelineEvalFloatFn EvalFloatFn; + _cmsFreeUserDataFn FreeDataFn; + _cmsDupUserDataFn DupDataFn; + + cmsContext ContextID; // Environment + + cmsBool SaveAs8Bits; // Implementation-specific: save as 8 bits if possible +}; + +// LUT reading & creation ------------------------------------------------------------------------------------------- + +// Read tags using low-level function, provide necessary glue code to adapt versions, etc. All those return a brand new copy +// of the LUTS, since ownership of original is up to the profile. The user should free allocated resources. + +cmsPipeline* _cmsReadInputLUT(cmsHPROFILE hProfile, int Intent); +cmsPipeline* _cmsReadOutputLUT(cmsHPROFILE hProfile, int Intent); +cmsPipeline* _cmsReadDevicelinkLUT(cmsHPROFILE hProfile, int Intent); + +// Special values +cmsBool _cmsReadMediaWhitePoint(cmsCIEXYZ* Dest, cmsHPROFILE hProfile); +cmsBool _cmsReadCHAD(cmsMAT3* Dest, cmsHPROFILE hProfile); + +// Profile linker -------------------------------------------------------------------------------------------------- + +cmsPipeline* _cmsLinkProfiles(cmsContext ContextID, + cmsUInt32Number nProfiles, + cmsUInt32Number TheIntents[], + cmsHPROFILE hProfiles[], + cmsBool BPC[], + cmsFloat64Number AdaptationStates[], + cmsUInt32Number dwFlags); + +// Sequence -------------------------------------------------------------------------------------------------------- + +cmsSEQ* _cmsReadProfileSequence(cmsHPROFILE hProfile); +cmsBool _cmsWriteProfileSequence(cmsHPROFILE hProfile, const cmsSEQ* seq); +cmsSEQ* _cmsCompileProfileSequence(cmsContext ContextID, cmsUInt32Number nProfiles, cmsHPROFILE hProfiles[]); + + +// LUT optimization ------------------------------------------------------------------------------------------------ + +cmsUInt16Number _cmsQuantizeVal(cmsFloat64Number i, int MaxSamples); +int _cmsReasonableGridpointsByColorspace(cmsColorSpaceSignature Colorspace, cmsUInt32Number dwFlags); + +cmsBool _cmsEndPointsBySpace(cmsColorSpaceSignature Space, + cmsUInt16Number **White, + cmsUInt16Number **Black, + cmsUInt32Number *nOutputs); + +cmsBool _cmsOptimizePipeline(cmsPipeline** Lut, + int Intent, + cmsUInt32Number* InputFormat, + cmsUInt32Number* OutputFormat, + cmsUInt32Number* dwFlags ); + + +// Hi level LUT building ---------------------------------------------------------------------------------------------- + +cmsPipeline* _cmsCreateGamutCheckPipeline(cmsContext ContextID, + cmsHPROFILE hProfiles[], + cmsBool BPC[], + cmsUInt32Number Intents[], + cmsFloat64Number AdaptationStates[], + cmsUInt32Number nGamutPCSposition, + cmsHPROFILE hGamut); + + +// Formatters ------------------------------------------------------------------------------------------------------------ + +#define cmsFLAGS_CAN_CHANGE_FORMATTER 0x02000000 // Allow change buffer format + +cmsBool _cmsFormatterIsFloat(cmsUInt32Number Type); +cmsBool _cmsFormatterIs8bit(cmsUInt32Number Type); + +cmsFormatter _cmsGetFormatter(cmsUInt32Number Type, // Specific type, i.e. TYPE_RGB_8 + cmsFormatterDirection Dir, + cmsUInt32Number dwFlags); + + +#ifndef CMS_NO_HALF_SUPPORT + +// Half float +cmsFloat32Number _cmsHalf2Float(cmsUInt16Number h); +cmsUInt16Number _cmsFloat2Half(cmsFloat32Number flt); + +#endif + +// Transform logic ------------------------------------------------------------------------------------------------------ + +struct _cmstransform_struct; + +typedef struct { + + // 1-pixel cache (16 bits only) + cmsUInt16Number CacheIn[cmsMAXCHANNELS]; + cmsUInt16Number CacheOut[cmsMAXCHANNELS]; + +} _cmsCACHE; + + + +// Transformation +typedef struct _cmstransform_struct { + + cmsUInt32Number InputFormat, OutputFormat; // Keep formats for further reference + + // Points to transform code + _cmsTransformFn xform; + + // Formatters, cannot be embedded into LUT because cache + cmsFormatter16 FromInput; + cmsFormatter16 ToOutput; + + cmsFormatterFloat FromInputFloat; + cmsFormatterFloat ToOutputFloat; + + // 1-pixel cache seed for zero as input (16 bits, read only) + _cmsCACHE Cache; + + // A Pipeline holding the full (optimized) transform + cmsPipeline* Lut; + + // A Pipeline holding the gamut check. It goes from the input space to bilevel + cmsPipeline* GamutCheck; + + // Colorant tables + cmsNAMEDCOLORLIST* InputColorant; // Input Colorant table + cmsNAMEDCOLORLIST* OutputColorant; // Colorant table (for n chans > CMYK) + + // Informational only + cmsColorSpaceSignature EntryColorSpace; + cmsColorSpaceSignature ExitColorSpace; + + // White points (informative only) + cmsCIEXYZ EntryWhitePoint; + cmsCIEXYZ ExitWhitePoint; + + // Profiles used to create the transform + cmsSEQ* Sequence; + + cmsUInt32Number dwOriginalFlags; + cmsFloat64Number AdaptationState; + + // The intent of this transform. That is usually the last intent in the profilechain, but may differ + cmsUInt32Number RenderingIntent; + + // An id that uniquely identifies the running context. May be null. + cmsContext ContextID; + + // A user-defined pointer that can be used to store data for transform plug-ins + void* UserData; + _cmsFreeUserDataFn FreeUserData; + +} _cmsTRANSFORM; + +// -------------------------------------------------------------------------------------------------- + +cmsHTRANSFORM _cmsChain2Lab(cmsContext ContextID, + cmsUInt32Number nProfiles, + cmsUInt32Number InputFormat, + cmsUInt32Number OutputFormat, + const cmsUInt32Number Intents[], + const cmsHPROFILE hProfiles[], + const cmsBool BPC[], + const cmsFloat64Number AdaptationStates[], + cmsUInt32Number dwFlags); + + +cmsToneCurve* _cmsBuildKToneCurve(cmsContext ContextID, + cmsUInt32Number nPoints, + cmsUInt32Number nProfiles, + const cmsUInt32Number Intents[], + const cmsHPROFILE hProfiles[], + const cmsBool BPC[], + const cmsFloat64Number AdaptationStates[], + cmsUInt32Number dwFlags); + +cmsBool _cmsAdaptationMatrix(cmsMAT3* r, const cmsMAT3* ConeMatrix, const cmsCIEXYZ* FromIll, const cmsCIEXYZ* ToIll); + +cmsBool _cmsBuildRGB2XYZtransferMatrix(cmsMAT3* r, const cmsCIExyY* WhitePoint, const cmsCIExyYTRIPLE* Primaries); + + +#define _lcms_internal_H +#endif