/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
// This file is available under and governed by the GNU General Public
// License version 2 only, as published by the Free Software Foundation.
// However, the following notice accompanied the original version of this
// file:
//
//---------------------------------------------------------------------------------
//
// 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,
// 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 -----------------------------------------------------------------------------
#ifdef CMS_IS_WINDOWS_
# include <io.h>
#else
#endif
// Symbols
typedef enum {
// Keywords
} SYMBOL;
// How to write the value
typedef enum {
} WRITEMODE;
// Linked list of variable names
typedef struct _KeyVal {
} KEYVALUE;
// Linked list of memory chunks (Memory sink)
typedef struct _OwnedMem {
} OWNEDMEM;
// Suballocator
typedef struct _SubAllocator {
} SUBALLOCATOR;
// Table. Each individual table can hold properties and rows & cols
typedef struct _Table {
} TABLE;
// File stream being parsed
typedef struct _FileContext {
} FILECTX;
// This struct hold all information about an open IT8 handler.
typedef struct {
// Memory management
// Parser state machine
// Allowed keywords & datasets. They have visibility on whole stream
} cmsIT8;
// The stream for save operations
typedef struct {
} SAVESTREAM;
// ------------------------------------------------------ cmsIT8 parsing routines
// A keyword
typedef struct {
const char *id;
} KEYWORD;
// The keyword->symbol translation table. Sorting is required.
{"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}
};
// Predefined properties
// A property
typedef struct {
} PROPERTY;
{"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.
{"DIFFUSE_GEOMETRY", WRITE_STRINGIFY}, // The diffuse geometry used. Allowed values are "sphere" or "opal".
{"MANUFACTURER", WRITE_STRINGIFY},
{"PROD_DATE", WRITE_STRINGIFY}, // Identifies year and month of production of the target in the form yyyy:mm.
{"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".
// 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
// 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.
};
// 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
//Forward declaration of some internal functions
// Checks if c is a separator
static
{
return (c == ' ') || (c == '\t') || (c == '\r');
}
// Checks whatever if c is a valid identifier char
static
{
}
// Checks whatsever if c is a valid identifier middle char.
static
{
}
// Checks whatsever if c is a valid identifier first char.
static
{
}
// Guess whether the supplied path looks like an absolute path
static
{
return FALSE;
if (path[0] == 0)
return FALSE;
ThreeChars[3] = 0;
if(ThreeChars[0] == DIR_CHAR)
return TRUE;
#ifdef CMS_IS_WINDOWS_
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;
// Already absolute?
if (isabsolutepath(relPath)) {
return TRUE;
}
// No, search for last
// No need to assure zero terminator over here
return TRUE;
}
// Make sure no exploit is being even tried
static
{
return "**** CORRUPTED FORMAT STRING ***";
return str;
}
// Syntax error
static
{
Buffer[255] = 0;
snprintf(ErrMsg, 1023, "%s: Line %d, %s", it8->FileStack[it8 ->IncludeSP]->FileName, it8->lineno, Buffer);
ErrMsg[1023] = 0;
return FALSE;
}
// Check if current symbol is same as specified. issue an error else.
static
{
return TRUE;
}
// Read Next character from stream
static
{
} else
}
}
else {
}
}
// Try to see if current identifier is a keyword, if so return the referred symbol
static
{
int l = 1;
int r = NUMKEYS;
int x, res;
while (r >= l)
{
x = (l+r)/2;
if (res < 0) r = x - 1;
else l = x + 1;
}
return SNONE;
}
// 10 ^n
static
{
}
// Reads a Real number, tries to follow from integer number
static
{
}
prec++;
}
}
// Exponent, example 34.00E+20
int e;
int sgn;
}
else
sgn = +1;
}
e = 0;
}
e = sgn*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
{
Buffer++;
}
}
if (*Buffer == '.') {
prec++;
}
}
// Exponent, example 34.00E+20
int e;
int sgn;
sgn = 1;
if (*Buffer == '-') {
sgn = -1;
}
else
if (*Buffer == '+') {
sgn = +1;
}
e = 0;
}
e = sgn*e;
}
}
// Reads next symbol
static
{
register char *idptr;
register int k;
int sng;
do {
k = 0;
do {
*idptr = '\0';
}
else // Is a number?
{
sign = -1;
}
int j;
{
{
return;
}
}
return;
}
int j;
{
{
return;
}
}
return;
}
}
return;
}
}
return;
}
// Special case. Numbers followed by letters are taken as identifiers
}
else {
}
do {
*idptr = '\0';
}
return;
}
else
// EOF marker -- ignore it
case '\x1a':
break;
// Eof stream markers
case 0:
case -1:
break;
// Next line
case '\n':
break;
// Comment
case '#':
break;
// String.
case '\'':
case '\"':
k = 0;
else {
k++;
}
}
*idptr = '\0';
break;
default:
return;
}
// Handle the include special token
return;
}
//if(FileNest == NULL)
// TODO: how to manage out-of-memory conditions?
}
return;
}
return;
}
}
}
// Checks end of line separator
static
{
return TRUE;
}
// Skip a symbol
static
{
}
// Skip multiple EOLN
static
{
}
}
// Returns a string holding current value
static
{
break;
break;
default:
}
return TRUE;
}
// ---------------------------------------------------------- Table
static
{
}
}
// ---------------------------------------------------------- Memory management
// Frees an allocator and owned memory
{
return;
if (it8->MemorySink) {
OWNEDMEM* p;
OWNEDMEM* n;
n = p->Next;
}
}
if (it8->MemoryBlock)
}
// Allocates a chunk of data, keep linked list
static
{
return NULL;
}
}
return ptr;
}
// Suballocator.
static
{
else
}
return (void*) ptr;
}
// Allocates a string
static
{
char *ptr;
return ptr;
}
// Searches through linked list
static
{
break;
}
}
if (p == NULL)
return FALSE;
if (Subkey == 0)
return TRUE;
for (; p != NULL; p = p->NextSubkey) {
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;
// Check if property is already in list
// This may work for editing properties
// return SynError(it8, "duplicate key <%s>", Key);
}
else {
last = p;
// Allocate the container
if (p == NULL)
{
return NULL;
}
// Store name and value
// Keep the container in our list
*Head = p;
}
else
{
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
}
}
p->NextSubkey = NULL;
}
}
else {
}
return p;
}
static
{
}
static
{
}
static
{
TABLE* t;
t->HeaderList = NULL;
t->DataFormat = NULL;
it8 ->TablesCount++;
}
{
}
else {
return -1;
}
}
return nTable;
}
// Init an empty container
{
// Initialize predefined properties & data
for (i=0; i < NUMPREDEFINEDPROPS; i++)
for (i=0; i < NUMPREDEFINEDSAMPLEID; i++)
}
{
}
{
return TRUE;
}
{
}
// Sets a property
{
}
{
}
{
}
{
}
cmsBool CMSEXPORT cmsIT8SetPropertyMulti(cmsHANDLE hIT8, const char* Key, const char* SubKey, const char *Buffer)
{
}
// Gets a property
{
KEYVALUE* p;
{
return p -> Value;
}
return NULL;
}
{
return ParseFloatNumber(v);
}
{
KEYVALUE* p;
return p -> Value;
}
return NULL;
}
// ----------------------------------------------------------------- Datasets
static
{
if (t -> DataFormat) return; // Already allocated
if (t -> nSamples <= 0) {
t -> nSamples = 10;
}
if (t->DataFormat == NULL) {
}
}
static
{
if (t->DataFormat)
return t->DataFormat[n];
return NULL;
}
static
{
if (!t->DataFormat)
if (n > t -> nSamples) {
return FALSE;
}
if (t->DataFormat) {
}
return TRUE;
}
{
}
static
{
if (t -> Data) return; // Already allocated
}
}
static
{
return NULL;
}
static
{
if (!t->Data)
}
}
return TRUE;
}
// --------------------------------------------------------------- File I/O
// Writes a string to file
static
{
str = " ";
// Lenghth to write
if (f ->stream) { // Should I write it to a file?
return;
}
}
else { // Or to a memory block?
if (f ->Base) { // Am I just counting the bytes?
return;
}
}
}
}
// Write formatted
static
{
Buffer[4095] = 0;
}
// Writes full header
static
{
KEYVALUE* p;
// Writes the type
{
if (*p ->Keyword == '#') {
char* Pt;
if (*Pt == '\n') {
}
}
continue;
}
#ifdef CMS_STRICT_CGATS
#endif
}
if (p->Value) {
switch (p ->WriteAs) {
case WRITE_UNCOOKED:
break;
case WRITE_STRINGIFY:
break;
case WRITE_HEXADECIMAL:
break;
case WRITE_BINARY:
break;
case WRITE_PAIR:
break;
return;
}
}
}
}
// Writes the data format
static
{
int i, nSamples;
if (!t -> DataFormat) return;
for (i = 0; i < nSamples; i++) {
}
}
// Writes data array
static
{
int i, j;
if (!t->Data) return;
for (i = 0; i < t-> nPatches; i++) {
for (j = 0; j < t->nSamples; j++) {
else {
// If value contains whitespace, enclose within quote
}
else
}
}
}
}
// Saves whole file
{
for (i=0; i < it8 ->TablesCount; i++) {
cmsIT8SetTable(hIT8, i);
}
return TRUE;
}
// Saves to memory
{
else
for (i=0; i < it8 ->TablesCount; i++) {
cmsIT8SetTable(hIT8, i);
}
return TRUE;
}
// -------------------------------------------------------------- Higer level parsing
static
{
int iField = 0;
}
iField++;
}
}
return TRUE;
}
static
{
int iField = 0;
int iSet = 0;
if (!t->Data)
{
iField = 0;
iSet++;
}
return FALSE;
return FALSE;
iField++;
}
}
// Check for data completion.
return TRUE;
}
static
{
case SKEYWORD:
break;
case SDATA_FORMAT_ID:
break;
case SIDENT:
#ifdef CMS_STRICT_CGATS
#else
#endif
}
}
else {
const char *Subkey;
char *Nextkey;
// chop the string as a list of "subkey, value" pairs, using ';' as a separator
{
// identify token pair boundary
if(Nextkey)
*Nextkey++ = '\0';
// for each pair, split the subkey and the value
// gobble the spaces before the coma, and the coma itself
// gobble any space at the right
// trim the strings from the left
}
}
break;
case SEOLN: break;
default:
}
}
return TRUE;
}
static
{
// First line is a very special case.
}
*SheetTypePtr = 0;
}
static
{
if (nosheet == 0) {
}
case SBEGIN_DATA_FORMAT:
break;
case SBEGIN_DATA:
// Read sheet type if present. We only support identifier and string.
// <ident> <eoln> is a type string
// anything else, is not a type string
if (nosheet == 0) {
// May be a type sheet or may be a prop value statement. We cannot use insymbol in
// this special case...
// If a newline is found, then this is a type string
}
else
{
// It is not. Just continue
}
}
else
// Validate quoted strings
}
}
}
break;
case SEOLN:
break;
default:
}
}
}
// Init usefull pointers
static
{
int idField, i;
char* Fld;
for (j=0; j < it8 ->TablesCount; j++) {
t -> SampleID = 0;
{
if (t ->DataFormat == NULL){
return;
}
if (!Fld) continue;
for (i=0; i < t -> nPatches; i++) {
if (Data) {
Buffer[255] = 0;
else
}
}
}
// "LABEL" is an extension. It keeps references to forward tables
// Search for table references...
for (i=0; i < t -> nPatches; i++) {
if (Label) {
// This is the label, search for a table containing
// this property
for (k=0; k < it8 ->TablesCount; k++) {
KEYVALUE* p;
// Available, keep type and table
int nTable = k;
}
}
}
}
}
}
}
}
// 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 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':
case '\t':
case ' ':
space = 1;
break;
case '\"':
break;
default:
if (Buffer[i] < 32) return 0;
if (Buffer[i] > 127) return 0;
space = 0;
break;
}
}
return 0;
}
static
{
if (!fp) {
return FALSE;
}
return FALSE;
}
// ---------------------------------------------------------- Exported routines
{
int type;
_cmsAssert(len != 0);
return FALSE;
}
return hIT8;
}
{
int type;
return NULL;
}
return NULL;
}
return NULL;
}
return hIT8;
}
{
TABLE* t;
if (SampleNames)
*SampleNames = t -> DataFormat;
return t -> nSamples;
}
{
KEYVALUE* p;
char **Props;
TABLE* t;
// Pass#1 - count properties
n = 0;
n++;
}
// Pass#2 - Fill pointers
n = 0;
}
*PropertyNames = Props;
return n;
}
cmsUInt32Number CMSEXPORT cmsIT8EnumPropertyMulti(cmsHANDLE hIT8, const char* cProp, const char ***SubpropertyNames)
{
const char **Props;
TABLE* t;
*SubpropertyNames = 0;
return 0;
}
// Pass#1 - count properties
n = 0;
n++;
}
// Pass#2 - Fill pointers
n = 0;
}
return n;
}
static
{
int i;
const char *data;
for (i=0; i < t-> nPatches; i++) {
return i;
}
}
// SynError(it8, "Couldn't find patch '%s'\n", cPatch);
return -1;
}
static
{
int i;
const char *data;
for (i=0; i < t-> nPatches; i++) {
return i;
}
return -1;
}
static
{
int i;
const char *fld;
for (i=0; i < t->nSamples; i++) {
return i;
}
return -1;
}
{
}
{
}
{
const char* Buffer;
return ParseFloatNumber(Buffer);
}
{
}
{
}
{
if (iField < 0) {
return NULL;
}
if (iSet < 0) {
return NULL;
}
}
{
const char* Buffer;
return ParseFloatNumber(Buffer);
}
cmsBool CMSEXPORT cmsIT8SetData(cmsHANDLE hIT8, const char* cPatch, const char* cSample, const char *Val)
{
TABLE* t;
if (iField < 0)
return FALSE;
if (t-> nPatches == 0) {
}
if (iSet < 0) {
}
}
else {
if (iSet < 0) {
return FALSE;
}
}
}
const char* cSample,
{
}
// Buffer should get MAXSTR at least
{
TABLE* t;
char* Data;
return buffer;
}
{
}
{
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;
int nTable;
cField = "LABEL";
cField = "LABEL";
if (!cLabelFld) return -1;
return -1;
ExpectedType = NULL;
if (ExpectedType) {
}
}
{
int pos;
if(pos == -1)
return FALSE;
return TRUE;
}
{
else
}