/*
* Copyright 2006-2012 ICEsoft Technologies Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS
* IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
package org.icepdf.core.pobjects.graphics;
import org.icepdf.core.pobjects.Name;
import org.icepdf.core.pobjects.functions.Function;
import org.icepdf.core.util.ColorUtil;
import org.icepdf.core.util.Library;
import java.awt.*;
import java.util.Hashtable;
/**
* <p>Separation Color Space background:</p>
* <ul>
* <p>Color output devices produce full color by combining primary or process
* colorants in varying amounts. On an additive color device such as a display,
* the primary colorants consist of red, green, and blue phosphors; on a
* subtractive device such as a printer, they typically consist of cyan, magenta,
* yellow, and sometimes black inks. In addition, some devices can apply special
* colorants, often called spot colorants, to produce effects that cannot be
* achieved with the standard process colorants alone. Examples include metallic
* and fluorescent colors and special textures.</p>
* </ul>
* <p>A Separation color space (PDF 1.2) provides a means for specifying the use
* of additional colorants or for isolating the control of individual color
* components of a device color space for a subtractive device. When such a space
* is the current color space, the current color is a single-component value,
* called a tint, that controls the application of the given colorant or color
* components only.</p>
* <p>A Separation color space is defined as follows:<br />
* [/Separation name alternateSpace tintTransform]
* </p>
* <ul>
* <li>The <i>alternateSpace</i> parameter must be an array or name object that
* identifies the alternate color space, which can be any device or
* CIE-based color space but not another special color space (Pattern,
* Indexed, Separation, or DeviceN).</li>
* <li>The <i>tintTransform</i> parameter must be a function.
* During subsequent painting operations, an application
* calls this function to transform a tint value into color component values
* in the alternate color space. The function is called with the tint value
* and must return the corresponding color component values. That is, the
* number of components and the interpretation of their values depend on the
* alternate color space.</li>
* </ul>
*
* @since 1.0
*/
public class Separation extends PColorSpace {
// named colour reference if valid conversion took place
protected Color namedColor;
// alternative colour space, named colour can not be resolved.
protected PColorSpace alternate;
// transform for colour tint, named function type
protected Function tintTransform;
/**
* Create a new Seperation colour space. Separation is specified using
* [/Seperation name alternateSpace tintTransform]
*
* @param l library
* @param h dictionary entries
* @param name name of colourspace, always seperation
* @param alternateSpace name of alternative colour space
* @param tintTransform function which defines the tint transform
*/
protected Separation(Library l, Hashtable h, Object name, Object alternateSpace, Object tintTransform) {
super(l, h);
alternate = getColorSpace(l, alternateSpace);
this.tintTransform = Function.getFunction(l, l.getObject(tintTransform));
// see if name can be converted to a known colour.
if (name instanceof Name) {
String colorName = ((Name) name).getName();
// get colour value if any
int colorVaue = ColorUtil.convertNamedColor(colorName.toLowerCase());
if (colorVaue != -1) {
namedColor = new Color(colorVaue);
}
}
}
/**
* Returns the number of components in this colour space.
*
* @return number of components
*/
public int getNumComponents() {
return 1;
}
/**
* Gets the colour in RGB represened by the array of colour components
*
* @param components array of component colour data
* @return new RGB colour composed from the components array.
*/
public Color getColor(float[] components) {
// the function couldn't be initiated then use the alternative colour
// space. The alternate colour space can be any device or CIE-based
// colour space. However Separation is usually specified using only one
// component so we must generate the output colour
if (tintTransform == null) {
float colour = components[0];
// copy the colour values into the needed length of the alternate colour
float[] alternateColour = new float[alternate.getNumComponents()];
for (int i = 0, max = alternate.getNumComponents(); i < max; i++) {
alternateColour[i] = colour;
}
return alternate.getColor(alternateColour);
}
if (alternate != null){
float y[] = tintTransform.calculate(components);
return alternate.getColor(reverse(y));
}
// return the named colour if it was resolved, otherwise assemble the
// alternative colour.
// -- Only applies to subtractive devices, screens are additive but I'm
// leaving this in encase something goes horribly wrong.
return namedColor;
}
}