/*
* 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.Dictionary;
import org.icepdf.core.pobjects.Reference;
import org.icepdf.core.util.Library;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.util.Hashtable;
import java.util.Vector;
import java.util.logging.Logger;
import java.util.logging.Level;
/**
* <p>Shading Pattern is a Base class for a all shading Types. It contains
* all common dictionary entries and acts a factory examing the patternType
* entry and returning a know Pattern Type implementation. Currently the
* factory only support Shading Type2 and Type3 patterns, as thses are the only
* types we have concrete examples of. </p>
*
* @author ICEsoft Technologies Inc.
* @since 3.0
*/
public abstract class ShadingPattern extends Dictionary implements Pattern {
private static final Logger logger =
Logger.getLogger(ShadingPattern.class.toString());
// pattern types by number.
public static final int SHADING_PATTERN_TYPE_1 = 1;
public static final int SHADING_PATTERN_TYPE_2 = 2;
public static final int SHADING_PATTERN_TYPE_3 = 3;
public static final int SHADING_PATTERN_TYPE_4 = 4;
public static final int SHADING_PATTERN_TYPE_5 = 5;
public static final int SHADING_PATTERN_TYPE_6 = 6;
// type of PObject, should always be "Pattern"
protected String type;
// A code identifying the type of pattern that this dictionary describes
protected int patternType;
// shading dictionary, entries vary depending on shading type.
protected Hashtable shading;
// shading type 1-7, most common, 2,3,6..
protected int shadingType;
// start of common shading dictionary entries.
// An array of four numbers in the pattern coordinate system giving the
// coordinates of the left, bottom, right, and top edges, respectively, of
// the pattern cell's bounding box. These boundaries are used to clip the
// pattern cell.
protected Rectangle2D bBox;
// any device, cie-based or special color except Pattern, required.
protected PColorSpace colorSpace;
// background colors (optional), not applicable on 'sh'
protected Vector background;
// turn on/off antiAliasing. (optional)
protected boolean antiAlias;
// end of common shading dictionary entries.
// An array of six numbers specifying the pattern matrix. The default value
// is the identity matrix [1 0 0 1 0 0].
protected AffineTransform matrix;
// graphics state for shading pattern
protected ExtGState extGState;
// initiated flag
protected boolean inited;
public ShadingPattern(Library library, Hashtable entries) {
super(library, entries);
type = library.getName(entries, "Type");
patternType = library.getInt(entries, "PatternType");
Object attribute = library.getObject(entries, "ExtGState");
if (attribute instanceof Hashtable) {
extGState = new ExtGState(library, (Hashtable) attribute);
} else if (attribute instanceof Reference) {
extGState = new ExtGState(library,
(Hashtable) library.getObject(
(Reference) attribute));
}
Vector v = (Vector) library.getObject(entries, "Matrix");
if (v != null) {
matrix = getAffineTransform(v);
} else {
// default is identity matrix
matrix = new AffineTransform();
}
}
/**
* Factory method to resolve the shading dictionaries ShaddingType. Currently
* only types 2 and 3 are supported. In test suite these are the most
* common of the pattern shading types
*
* @param library library for document
* @param attribute dictionary for potential shading object.
* @return returns a ShadingPatern object based ont he shadingType criteria.
* if the proper constructor cannot be found then null is returned.
*/
public static ShadingPattern getShadingPattern(Library library, Hashtable attribute) {
// factory type approach, find shading entries and get type
Hashtable shading =
library.getDictionary(attribute, "Shading");
if (shading != null) {
return shadingFactory(library, attribute, shading);
}
return null;
}
/**
* Factory call create a support pattern type. Currently only types 2 and
* 3 are supported.
*
* @param library document library
* @param entries entries in the the currently dictionary.
* @param shading shading dictionary.
* @return shading pattern
*/
public static ShadingPattern getShadingPattern(Library library,
Hashtable entries,
Hashtable shading) {
// resolve shading pattern
if (entries != null) {
ShadingPattern shadingPattern = shadingFactory(library, shading, shading);
// assign shading dictionary for sh instances that only define
// the shading dictionary and not the full pattern dictionary.
shadingPattern.setShading(shading);
return shadingPattern;
}
return null;
}
// create a new shading pattern.
private static ShadingPattern shadingFactory(Library library,
Hashtable attribute,
Hashtable patternDictionary) {
int shadingType = library.getInt(patternDictionary, "ShadingType");
if (shadingType == ShadingPattern.SHADING_PATTERN_TYPE_2) {
return new ShadingType2Pattern(library, attribute);
} else if (shadingType == ShadingPattern.SHADING_PATTERN_TYPE_3) {
return new ShadingType3Pattern(library, attribute);
} else {
if (logger.isLoggable(Level.FINE)) {
logger.fine("Shading pattern of Type " + shadingType +
" are not currently supported");
}
}
return null;
}
/**
* Utility method for parsing a vector of affinetranform values to an
* affine transform.
*
* @param v vectory containing affine transform values.
* @return affine tansform based on v
*/
private static AffineTransform getAffineTransform(Vector v) {
float f[] = new float[6];
for (int i = 0; i < 6; i++) {
f[i] = ((Number) v.elementAt(i)).floatValue();
}
return new AffineTransform(f);
}
/**
* Gets the Paint object need to fill a shape etc. Each individual
* implementation will return a particular paint type.
*
* @return Paint type for fill.
*/
public abstract Paint getPaint();
/**
* Initialized shading dictionary attributes. Discrepancies between sh and
* scn tokens cause us to handle initialization at a later time.
*/
public abstract void init();
public void setParentGraphicState(GraphicsState graphicsState) {
// nothing to be done for shading.
}
public void setMatrix(AffineTransform matrix) {
this.matrix = matrix;
}
public int getPatternType() {
return patternType;
}
public Rectangle2D getBBox() {
return bBox;
}
public AffineTransform getMatrix() {
return matrix;
}
public int getShadingType() {
return shadingType;
}
public void setShading(Hashtable shading) {
this.shading = shading;
}
public String getType() {
return type;
}
public PColorSpace getColorSpace() {
return colorSpace;
}
public Vector getBackground() {
return background;
}
public boolean isAntiAlias() {
return antiAlias;
}
public ExtGState getExtGState() {
return extGState;
}
public boolean isInited() {
return inited;
}
public String toString() {
return "Shading Pattern: \n" +
" type: pattern " +
"\n patternType: shading" +
"\n matrix: " + matrix +
"\n extGState: " + extGState +
"\n shading dictionary: " + shading +
"\n shadingType: " + shadingType +
"\n colourSpace: " + colorSpace +
"\n background: " + background +
"\n bbox: " + bBox +
"\n antiAlias: " + antiAlias;
}
}