001: /**
002: * Copyright (c) 2003, www.pdfbox.org
003: * All rights reserved.
004: *
005: * Redistribution and use in source and binary forms, with or without
006: * modification, are permitted provided that the following conditions are met:
007: *
008: * 1. Redistributions of source code must retain the above copyright notice,
009: * this list of conditions and the following disclaimer.
010: * 2. Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: * 3. Neither the name of pdfbox; nor the names of its
014: * contributors may be used to endorse or promote products derived from this
015: * software without specific prior written permission.
016: *
017: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
018: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
019: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
020: * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
021: * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
022: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
023: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
024: * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
025: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
026: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
027: *
028: * http://www.pdfbox.org
029: *
030: */package org.pdfbox.pdmodel.graphics;
031:
032: import org.pdfbox.cos.COSArray;
033: import org.pdfbox.cos.COSBase;
034: import org.pdfbox.cos.COSDictionary;
035: import org.pdfbox.cos.COSFloat;
036: import org.pdfbox.cos.COSName;
037: import org.pdfbox.cos.COSNumber;
038:
039: import org.pdfbox.pdmodel.common.COSObjectable;
040:
041: import java.io.IOException;
042:
043: import java.util.Iterator;
044:
045: /**
046: * This class represents the graphics state dictionary that is stored in the PDF document.
047: * The PDGraphicsStateValue holds the current runtime values as a stream is being executed.
048: *
049: * @author <a href="mailto:ben@benlitchfield.com">Ben Litchfield</a>
050: * @version $Revision: 1.5 $
051: */
052: public class PDExtendedGraphicsState implements COSObjectable {
053: private static final COSName LW = COSName.getPDFName("LW");
054: private static final COSName LC = COSName.getPDFName("LC");
055: private static final COSName LJ = COSName.getPDFName("LJ");
056: private static final COSName ML = COSName.getPDFName("ML");
057: private static final COSName D = COSName.getPDFName("D");
058: private static final COSName RI = COSName.getPDFName("RI");
059: private static final COSName OP = COSName.getPDFName("OP");
060: private static final COSName OP_NS = COSName.getPDFName("op");
061: private static final COSName OPM = COSName.getPDFName("OPM");
062: private static final COSName FONT = COSName.getPDFName("Font");
063: private static final COSName FL = COSName.getPDFName("FL");
064: private static final COSName SM = COSName.getPDFName("SM");
065: private static final COSName SA = COSName.getPDFName("SA");
066: private static final COSName CA = COSName.getPDFName("CA");
067: private static final COSName CA_NS = COSName.getPDFName("ca");
068: private static final COSName AIS = COSName.getPDFName("AIS");
069: private static final COSName TK = COSName.getPDFName("TK");
070:
071: /**
072: * Rendering intent constants, see PDF Reference 1.5 Section 4.5.4 Rendering Intents.
073: */
074: public static final String RENDERING_INTENT_ABSOLUTE_COLORIMETRIC = "AbsoluteColorimetric";
075: /**
076: * Rendering intent constants, see PDF Reference 1.5 Section 4.5.4 Rendering Intents.
077: */
078: public static final String RENDERING_INTENT_RELATIVE_COLORIMETRIC = "RelativeColorimetric";
079: /**
080: * Rendering intent constants, see PDF Reference 1.5 Section 4.5.4 Rendering Intents.
081: */
082: public static final String RENDERING_INTENT_SATURATION = "Saturation";
083: /**
084: * Rendering intent constants, see PDF Reference 1.5 Section 4.5.4 Rendering Intents.
085: */
086: public static final String RENDERING_INTENT_PERCEPTUAL = "Perceptual";
087:
088: private COSDictionary graphicsState;
089:
090: /**
091: * Default constructor, creates blank graphics state.
092: */
093: public PDExtendedGraphicsState() {
094: graphicsState = new COSDictionary();
095: graphicsState.setItem(COSName.TYPE, COSName
096: .getPDFName("ExtGState"));
097: }
098:
099: /**
100: * Create a graphics state from an existing dictionary.
101: *
102: * @param dictionary The existing graphics state.
103: */
104: public PDExtendedGraphicsState(COSDictionary dictionary) {
105: graphicsState = dictionary;
106: }
107:
108: /**
109: * This will implement the gs operator.
110: *
111: * @param gs The state to copy this dictionaries values into.
112: *
113: * @throws IOException If there is an error copying font information.
114: */
115: public void copyIntoGraphicsState(PDGraphicsState gs)
116: throws IOException {
117: Iterator keys = graphicsState.keyList().iterator();
118: while (keys.hasNext()) {
119: COSName key = (COSName) keys.next();
120: if (key.equals(LW)) {
121: gs.setLineWidth(getLineWidth().doubleValue());
122: } else if (key.equals(LC)) {
123: gs.setLineCap(getLineCapStyle());
124: } else if (key.equals(LJ)) {
125: gs.setLineJoin(getLineJoinStyle());
126: } else if (key.equals(ML)) {
127: gs.setMiterLimit(getMiterLimit().doubleValue());
128: } else if (key.equals(D)) {
129: gs.setLineDashPattern(getLineDashPattern());
130: } else if (key.equals(RI)) {
131: gs.setRenderingIntent(getRenderingIntent());
132: } else if (key.equals(OPM)) {
133: gs.setOverprintMode(getOverprintMode().doubleValue());
134: } else if (key.equals(FONT)) {
135: PDFontSetting setting = getFontSetting();
136: gs.getTextState().setFont(setting.getFont());
137: gs.getTextState().setFontSize(setting.getFontSize());
138: } else if (key.equals(FL)) {
139: gs.setFlatness(getFlatnessTolerance().floatValue());
140: } else if (key.equals(SM)) {
141: gs.setSmoothness(getSmoothnessTolerance().floatValue());
142: } else if (key.equals(SA)) {
143: gs.setStrokeAdjustment(getAutomaticStrokeAdjustment());
144: } else if (key.equals(CA)) {
145: gs.setAlphaConstants(getStrokingAlpaConstant()
146: .floatValue());
147: }/**
148: else if( key.equals( CA_NS ) )
149: {
150: }**/
151: else if (key.equals(AIS)) {
152: gs.setAlphaSource(getAlphaSourceFlag());
153: } else if (key.equals(TK)) {
154: gs.getTextState()
155: .setKnockoutFlag(getTextKnockoutFlag());
156: }
157: }
158: }
159:
160: /**
161: * This will get the underlying dictionary that this class acts on.
162: *
163: * @return The underlying dictionary for this class.
164: */
165: public COSDictionary getCOSDictionary() {
166: return graphicsState;
167: }
168:
169: /**
170: * Convert this standard java object to a COS object.
171: *
172: * @return The cos object that matches this Java object.
173: */
174: public COSBase getCOSObject() {
175: return graphicsState;
176: }
177:
178: /**
179: * This will get the line width. This will return null if there is no line width
180: *
181: * @return null or the LW value of the dictionary.
182: */
183: public Float getLineWidth() {
184: return getFloatItem(LW);
185: }
186:
187: /**
188: * This will set the line width.
189: *
190: * @param width The line width for the object.
191: */
192: public void setLineWidth(Float width) {
193: setFloatItem(LW, width);
194: }
195:
196: /**
197: * This will get the line cap style.
198: *
199: * @return null or the LC value of the dictionary.
200: */
201: public int getLineCapStyle() {
202: return graphicsState.getInt(LC);
203: }
204:
205: /**
206: * This will set the line cap style for the graphics state.
207: *
208: * @param style The new line cap style to set.
209: */
210: public void setLineCapStyle(int style) {
211: graphicsState.setInt(LC, style);
212: }
213:
214: /**
215: * This will get the line join style.
216: *
217: * @return null or the LJ value in the dictionary.
218: */
219: public int getLineJoinStyle() {
220: return graphicsState.getInt(LJ);
221: }
222:
223: /**
224: * This will set the line join style.
225: *
226: * @param style The new line join style.
227: */
228: public void setLineJoinStyle(int style) {
229: graphicsState.setInt(LJ, style);
230: }
231:
232: /**
233: * This will get the miter limit.
234: *
235: * @return null or the ML value in the dictionary.
236: */
237: public Float getMiterLimit() {
238: return getFloatItem(ML);
239: }
240:
241: /**
242: * This will set the miter limit for the graphics state.
243: *
244: * @param miterLimit The new miter limit value
245: */
246: public void setMiterLimit(Float miterLimit) {
247: setFloatItem(ML, miterLimit);
248: }
249:
250: /**
251: * This will get the dash pattern.
252: *
253: * @return null or the D value in the dictionary.
254: */
255: public PDLineDashPattern getLineDashPattern() {
256: PDLineDashPattern retval = null;
257: COSArray dp = (COSArray) graphicsState.getDictionaryObject(D);
258: if (dp != null) {
259: retval = new PDLineDashPattern(dp);
260: }
261: return retval;
262: }
263:
264: /**
265: * This will set the dash pattern for the graphics state.
266: *
267: * @param dashPattern The dash pattern
268: */
269: public void setLineDashPattern(PDLineDashPattern dashPattern) {
270: graphicsState.setItem(D, dashPattern.getCOSObject());
271: }
272:
273: /**
274: * This will get the rendering intent.
275: *
276: * @return null or the RI value in the dictionary.
277: */
278: public String getRenderingIntent() {
279: return graphicsState.getNameAsString("RI");
280: }
281:
282: /**
283: * This will set the rendering intent for the graphics state.
284: *
285: * @param ri The new rendering intent
286: */
287: public void setRenderingIntent(String ri) {
288: graphicsState.setName("RI", ri);
289: }
290:
291: /**
292: * This will get the overprint control.
293: *
294: * @return The overprint control or null if one has not been set.
295: */
296: public boolean getStrokingOverprintControl() {
297: return graphicsState.getBoolean(OP, false);
298: }
299:
300: /**
301: * This will get the overprint control(OP).
302: *
303: * @param op The overprint control.
304: */
305: public void setStrokingOverprintControl(boolean op) {
306: graphicsState.setBoolean(OP, op);
307: }
308:
309: /**
310: * This will get the overprint control for non stroking operations. If this
311: * value is null then the regular overprint control value will be returned.
312: *
313: * @return The overprint control or null if one has not been set.
314: */
315: public boolean getNonStrokingOverprintControl() {
316: return graphicsState.getBoolean(OP_NS,
317: getStrokingOverprintControl());
318: }
319:
320: /**
321: * This will get the overprint control(OP).
322: *
323: * @param op The overprint control.
324: */
325: public void setNonStrokingOverprintControl(boolean op) {
326: graphicsState.setBoolean(OP_NS, op);
327: }
328:
329: /**
330: * This will get the overprint control mode.
331: *
332: * @return The overprint control mode or null if one has not been set.
333: */
334: public Float getOverprintMode() {
335: return getFloatItem(OPM);
336: }
337:
338: /**
339: * This will get the overprint mode(OPM).
340: *
341: * @param overprintMode The overprint mode
342: */
343: public void setOverprintMode(Float overprintMode) {
344: setFloatItem(OPM, overprintMode);
345: }
346:
347: /**
348: * This will get the font setting of the graphics state.
349: *
350: * @return The font setting.
351: */
352: public PDFontSetting getFontSetting() {
353: PDFontSetting setting = null;
354: COSArray font = (COSArray) graphicsState
355: .getDictionaryObject(FONT);
356: if (font != null) {
357: setting = new PDFontSetting(font);
358: }
359: return setting;
360: }
361:
362: /**
363: * This will set the font setting for this graphics state.
364: *
365: * @param fs The new font setting.
366: */
367: public void setFontSetting(PDFontSetting fs) {
368: graphicsState.setItem(FONT, fs);
369: }
370:
371: /**
372: * This will get the flatness tolerance.
373: *
374: * @return The flatness tolerance or null if one has not been set.
375: */
376: public Float getFlatnessTolerance() {
377: return getFloatItem(FL);
378: }
379:
380: /**
381: * This will get the flatness tolerance.
382: *
383: * @param flatness The new flatness tolerance
384: */
385: public void setFlatnessTolerance(Float flatness) {
386: setFloatItem(FL, flatness);
387: }
388:
389: /**
390: * This will get the smothness tolerance.
391: *
392: * @return The smothness tolerance or null if one has not been set.
393: */
394: public Float getSmoothnessTolerance() {
395: return getFloatItem(SM);
396: }
397:
398: /**
399: * This will get the smoothness tolerance.
400: *
401: * @param smoothness The new smoothness tolerance
402: */
403: public void setSmoothnessTolerance(Float smoothness) {
404: setFloatItem(SM, smoothness);
405: }
406:
407: /**
408: * This will get the automatic stroke adjustment flag.
409: *
410: * @return The automatic stroke adjustment flag or null if one has not been set.
411: */
412: public boolean getAutomaticStrokeAdjustment() {
413: return graphicsState.getBoolean(SA, false);
414: }
415:
416: /**
417: * This will get the automatic stroke adjustment flag.
418: *
419: * @param sa The new automatic stroke adjustment flag.
420: */
421: public void setAutomaticStrokeAdjustment(boolean sa) {
422: graphicsState.setBoolean(SA, sa);
423: }
424:
425: /**
426: * This will get the stroking alpha constant.
427: *
428: * @return The stroking alpha constant or null if one has not been set.
429: */
430: public Float getStrokingAlpaConstant() {
431: return getFloatItem(CA);
432: }
433:
434: /**
435: * This will get the stroking alpha constant.
436: *
437: * @param alpha The new stroking alpha constant.
438: */
439: public void setStrokingAlphaConstant(Float alpha) {
440: setFloatItem(CA, alpha);
441: }
442:
443: /**
444: * This will get the non stroking alpha constant.
445: *
446: * @return The non stroking alpha constant or null if one has not been set.
447: */
448: public Float getNonStrokingAlpaConstant() {
449: return getFloatItem(CA_NS);
450: }
451:
452: /**
453: * This will get the non stroking alpha constant.
454: *
455: * @param alpha The new non stroking alpha constant.
456: */
457: public void setNonStrokingAlphaConstant(Float alpha) {
458: setFloatItem(CA_NS, alpha);
459: }
460:
461: /**
462: * This will get the alpha source flag.
463: *
464: * @return The alpha source flag.
465: */
466: public boolean getAlphaSourceFlag() {
467: return graphicsState.getBoolean(AIS, false);
468: }
469:
470: /**
471: * This will get the alpha source flag.
472: *
473: * @param alpha The alpha source flag.
474: */
475: public void setAlphaSourceFlag(boolean alpha) {
476: graphicsState.setBoolean(AIS, alpha);
477: }
478:
479: /**
480: * This will get the text knockout flag.
481: *
482: * @return The text knockout flag.
483: */
484: public boolean getTextKnockoutFlag() {
485: return graphicsState.getBoolean(TK, true);
486: }
487:
488: /**
489: * This will get the text knockout flag.
490: *
491: * @param tk The text knockout flag.
492: */
493: public void setTextKnockoutFlag(boolean tk) {
494: graphicsState.setBoolean(TK, tk);
495: }
496:
497: /**
498: * This will get a float item from the dictionary.
499: *
500: * @param key The key to the item.
501: *
502: * @return The value for that item.
503: */
504: private Float getFloatItem(COSName key) {
505: Float retval = null;
506: COSNumber value = (COSNumber) graphicsState
507: .getDictionaryObject(key);
508: if (value != null) {
509: retval = new Float(value.floatValue());
510: }
511: return retval;
512: }
513:
514: /**
515: * This will set a float object.
516: *
517: * @param key The key to the data that we are setting.
518: * @param value The value that we are setting.
519: */
520: private void setFloatItem(COSName key, Float value) {
521: if (value == null) {
522: graphicsState.removeItem(key);
523: } else {
524: graphicsState
525: .setItem(key, new COSFloat(value.floatValue()));
526: }
527: }
528: }
|