// Copyright 2001, FreeHEP. package org.freehep.postscript; import java.awt.Color; /** * Graphics State Operators for PostScript Processor * * @author Mark Donszelmann * @version $Id: GraphicsStateOperator.java 10178 2006-12-08 09:03:07Z duns $ */ public class GraphicsStateOperator extends PSOperator { public static Class[] operators = { GSave.class, GRestore.class, ClipSave.class, ClipRestore.class, GRestoreAll.class, InitGraphics.class, GState.class, SetGState.class, CurrentGState.class, SetLineWidth.class, CurrentLineWidth.class, SetLineCap.class, CurrentLineCap.class, SetLineJoin.class, CurrentLineJoin.class, SetMiterLimit.class, CurrentMiterLimit.class, SetStrokeAdjust.class, CurrentStrokeAdjust.class, SetDash.class, CurrentDash.class, SetColorSpace.class, CurrentColorSpace.class, SetColor.class, CurrentColor.class, SetGray.class, CurrentGray.class, SetHSBColor.class, CurrentHSBColor.class, SetRGBColor.class, CurrentRGBColor.class, SetCMYKColor.class, CurrentCMYKColor.class }; public boolean execute(OperandStack os) { throw new RuntimeException("Cannot execute class: "+getClass()); } } class GSave extends GraphicsStateOperator { public boolean execute(OperandStack os) { os.gsave(); return true; } } class GRestore extends GraphicsStateOperator { public boolean execute(OperandStack os) { os.grestore(); return true; } } class ClipSave extends GraphicsStateOperator { public boolean execute(OperandStack os) { // Level 3 error(os, new Unimplemented()); return true; } } class ClipRestore extends GraphicsStateOperator { public boolean execute(OperandStack os) { // Level 3 error(os, new Unimplemented()); return true; } } class GRestoreAll extends GraphicsStateOperator { public boolean execute(OperandStack os) { // FREEHEP-132: can only be implemented once we have Save and Restore error(os, new Unimplemented()); return true; } } class InitGraphics extends GraphicsStateOperator { public boolean execute(OperandStack os) { os.gstate().initGraphics(); return true; } } class GState extends GraphicsStateOperator { public boolean execute(OperandStack os) { os.push(os.gstate().copy()); return true; } } class SetGState extends GraphicsStateOperator { { operandTypes = new Class[] {PSGState.class}; } public boolean execute(OperandStack os) { PSGState gs = os.popGState(); gs.copyInto(os.gstate()); return true; } } class CurrentGState extends GraphicsStateOperator { { operandTypes = new Class[] {PSGState.class}; } public boolean execute(OperandStack os) { PSGState gs = os.popGState(); os.gstate().copyInto(gs); os.push(gs); return true; } } class SetLineWidth extends GraphicsStateOperator { { operandTypes = new Class[] {PSNumber.class}; } public boolean execute(OperandStack os) { PSNumber width = os.popNumber(); os.gstate().setLineWidth(width.getDouble()); return true; } } class CurrentLineWidth extends GraphicsStateOperator { public boolean execute(OperandStack os) { os.push(os.gstate().lineWidth()); return true; } } class SetLineCap extends GraphicsStateOperator { { operandTypes = new Class[] {PSInteger.class}; } public boolean execute(OperandStack os) { PSInteger n = os.popInteger(); os.gstate().setLineCap(n.getValue()); return true; } } class CurrentLineCap extends GraphicsStateOperator { public boolean execute(OperandStack os) { os.push(os.gstate().lineCap()); return true; } } class SetLineJoin extends GraphicsStateOperator { { operandTypes = new Class[] {PSInteger.class}; } public boolean execute(OperandStack os) { PSInteger n = os.popInteger(); os.gstate().setLineJoin(n.getValue()); return true; } } class CurrentLineJoin extends GraphicsStateOperator { public boolean execute(OperandStack os) { os.push(os.gstate().lineJoin()); return true; } } class SetMiterLimit extends GraphicsStateOperator { { operandTypes = new Class[] {PSNumber.class}; } public boolean execute(OperandStack os) { PSNumber n = os.popNumber(); os.gstate().setMiterLimit(n.getFloat()); return true; } } class CurrentMiterLimit extends GraphicsStateOperator { public boolean execute(OperandStack os) { os.push(os.gstate().miterLimit()); return true; } } class SetStrokeAdjust extends GraphicsStateOperator { { operandTypes = new Class[] {PSBoolean.class}; } public boolean execute(OperandStack os) { PSBoolean b = os.popBoolean(); os.gstate().setStrokeAdjust(b.getValue()); return true; } } class CurrentStrokeAdjust extends GraphicsStateOperator { public boolean execute(OperandStack os) { os.push(os.gstate().strokeAdjust()); return true; } } class SetDash extends GraphicsStateOperator { { operandTypes = new Class[] {PSPackedArray.class, PSNumber.class}; } public boolean execute(OperandStack os) { PSNumber offset = os.popNumber(); PSPackedArray array = os.popPackedArray(); os.gstate().setDash(array.toFloats(), offset.getFloat()); return true; } } class CurrentDash extends GraphicsStateOperator { public boolean execute(OperandStack os) { float[] dash = os.gstate().dash(); PSArray array = new PSArray(dash); os.push(array); os.push(os.gstate().dashPhase()); return true; } } class SetColorSpace extends GraphicsStateOperator { { operandTypes = new Class[] {PSObject.class}; } public boolean execute(OperandStack os) { String name; Object[] params; if (os.checkType(PSPackedArray.class)) { PSPackedArray a = os.popPackedArray(); name = a.get(0).cvs(); params = a.toObjects(); } else if (os.checkType(PSName.class)) { name = os.popName().cvs(); params = null; } else { name = "Undefined"; params = null; } if (!os.gstate().setColorSpace(name, params)) { error(os, new Undefined()); } return true; } } class CurrentColorSpace extends GraphicsStateOperator { public boolean execute(OperandStack os) { String space = os.gstate().colorSpace(); // FIXME: handle pattern color space parameters PSArray a = new PSArray(1); a.set(0, space); // for (int i=0; i<color.length; i++) { // a.set(1+i, color[i]); // } os.push(a); return true; } } class SetColor extends GraphicsStateOperator { { operandTypes = new Class[] {PSObject.class}; } // FIXME: handles only RGB, GRAY and CMYK public boolean execute(OperandStack os) { if (os.checkType(PSNumber.class)) { String space = os.gstate().colorSpace(); if (space.equals("DeviceGray")) { PSNumber g = os.popNumber(); os.gstate().setColor(new float[] { g.getFloat() }); } else if (space.equals("DeviceRGB")) { PSNumber blue = os.popNumber(); PSNumber green = os.popNumber(); PSNumber red = os.popNumber(); os.gstate().setColor(new float[] { red.getFloat(), green.getFloat(), blue.getFloat() }); } else if (space.equals("DeviceCMYK")) { PSNumber black = os.popNumber(); PSNumber yellow = os.popNumber(); PSNumber magenta = os.popNumber(); PSNumber cyan = os.popNumber(); os.gstate().setColor(new float[] { cyan.getFloat(), magenta.getFloat(), yellow.getFloat(), black.getFloat() }); } else { error(os, new Undefined()); } } else if (os.checkType(PSDictionary.class)) { PSDictionary pattern = os.popDictionary(); PSPaint paint = (PSPaint)pattern.get("Implementation"); int patternType = pattern.getInteger("PatternType"); int paintType = pattern.getInteger("PaintType"); if ((patternType == 1) && (paintType == 2)) { // FIXME: where is the color // FIXME: where is the pattern os.gstate().setColor(paint.getValue(), new PSObject[0]); } else { os.gstate().setColor(paint.getValue()); } } else { error(os, new TypeCheck()); } return true; } } class CurrentColor extends GraphicsStateOperator { // FIXME: this call should allow UCR and BG to be processed from DeviceCMYK public boolean execute(OperandStack os) { float[] color = os.gstate().color(); // FIXME: handle pattern color space for (int i=0; i<color.length; i++) { os.push(color[i]); } return true; } } class SetGray extends GraphicsStateOperator { { operandTypes = new Class[] {PSNumber.class}; } public boolean execute(OperandStack os) { PSNumber color = os.popNumber(); os.gstate().setColorSpace("DeviceGray"); os.gstate().setColor(new float[] { color.getFloat() }); return true; } } class CurrentGray extends GraphicsStateOperator { public boolean execute(OperandStack os) { float[] color = os.gstate().color("DeviceGray"); for (int i=0; i<color.length; i++) { os.push(color[i]); } return true; } } class SetHSBColor extends GraphicsStateOperator { { operandTypes = new Class[] {PSNumber.class, PSNumber.class, PSNumber.class}; } public boolean execute(OperandStack os) { PSNumber b = os.popNumber(); PSNumber s = os.popNumber(); PSNumber h = os.popNumber(); os.gstate().setColorSpace("DeviceRGB"); Color color = new Color(Color.HSBtoRGB(h.getFloat(), s.getFloat(), b.getFloat())); os.gstate().setColor(color.getColorComponents(null)); return true; } } class CurrentHSBColor extends GraphicsStateOperator { public boolean execute(OperandStack os) { float[] color = os.gstate().color("DeviceRGB"); float[] hsb = Color.RGBtoHSB((int)(color[0]*255), (int)(color[1]*255), (int)(color[2]*255), null); for (int i=0; i<hsb.length; i++) { os.push(hsb[i]); } return true; } } class SetRGBColor extends GraphicsStateOperator { { operandTypes = new Class[] {PSNumber.class, PSNumber.class, PSNumber.class}; } public boolean execute(OperandStack os) { PSNumber blue = os.popNumber(); PSNumber green = os.popNumber(); PSNumber red = os.popNumber(); os.gstate().setColorSpace("DeviceRGB"); os.gstate().setColor(new float[] { red.getFloat(), green.getFloat(), blue.getFloat() }); return true; } } class CurrentRGBColor extends GraphicsStateOperator { public boolean execute(OperandStack os) { float[] color = os.gstate().color("DeviceRGB"); for (int i=0; i<color.length; i++) { os.push(color[i]); } return true; } } class SetCMYKColor extends GraphicsStateOperator { { operandTypes = new Class[] {PSNumber.class, PSNumber.class, PSNumber.class, PSNumber.class}; } public boolean execute(OperandStack os) { float k = os.popNumber().getFloat(); float y = os.popNumber().getFloat(); float m = os.popNumber().getFloat(); float c = os.popNumber().getFloat(); os.gstate().setColorSpace("DeviceCMYK"); os.gstate().setColor(new float[] { c, m, y, k }); return true; } } class CurrentCMYKColor extends GraphicsStateOperator { private float[] cmyk; private float bg; private float ucr; public CurrentCMYKColor() { } private CurrentCMYKColor(float[] color) { cmyk = color; bg = -1.0f; ucr = -1.0f; } public boolean execute(OperandStack os) { if (cmyk == null) { float[] color = os.gstate().color("DeviceCMYK"); os.execStack().pop(); os.execStack().push(new CurrentCMYKColor(color)); os.push(color[3]); // K os.execStack().push(os.gstate().blackGeneration().copy()); return false; } if (bg < 0) { bg = ((PSNumber)os.popNumber()).getFloat(); os.push(cmyk[3]); os.execStack().push(os.gstate().underColorRemoval().copy()); return false; } ucr = ((PSNumber)os.popNumber()).getFloat(); cmyk[0] = Math.min(1.0f, Math.max(0.0f, cmyk[0] - ucr)); cmyk[1] = Math.min(1.0f, Math.max(0.0f, cmyk[1] - ucr)); cmyk[2] = Math.min(1.0f, Math.max(0.0f, cmyk[2] - ucr)); cmyk[3] = Math.min(1.0f, Math.max(0.0f, bg)); for (int i=0; i<cmyk.length; i++) { os.push(cmyk[i]); } return true; } }