001/*
002 * $Id: MetaState.java 4784 2011-03-15 08:33:00Z blowagie $
003 *
004 * This file is part of the iText (R) project.
005 * Copyright (c) 1998-2011 1T3XT BVBA
006 * Authors: Bruno Lowagie, Paulo Soares, et al.
007 *
008 * This program is free software; you can redistribute it and/or modify
009 * it under the terms of the GNU Affero General Public License version 3
010 * as published by the Free Software Foundation with the addition of the
011 * following permission added to Section 15 as permitted in Section 7(a):
012 * FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY 1T3XT,
013 * 1T3XT DISCLAIMS THE WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
014 *
015 * This program is distributed in the hope that it will be useful, but
016 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
017 * or FITNESS FOR A PARTICULAR PURPOSE.
018 * See the GNU Affero General Public License for more details.
019 * You should have received a copy of the GNU Affero General Public License
020 * along with this program; if not, see http://www.gnu.org/licenses or write to
021 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
022 * Boston, MA, 02110-1301 USA, or download the license from the following URL:
023 * http://itextpdf.com/terms-of-use/
024 *
025 * The interactive user interfaces in modified source and object code versions
026 * of this program must display Appropriate Legal Notices, as required under
027 * Section 5 of the GNU Affero General Public License.
028 *
029 * In accordance with Section 7(b) of the GNU Affero General Public License,
030 * a covered work must retain the producer line in every PDF that is created
031 * or manipulated using iText.
032 *
033 * You can be released from the requirements of the license by purchasing
034 * a commercial license. Buying such a license is mandatory as soon as you
035 * develop commercial activities involving the iText software without
036 * disclosing the source code of your own applications.
037 * These activities include: offering paid services to customers as an ASP,
038 * serving PDFs on the fly in a web application, shipping iText with a closed
039 * source product.
040 *
041 * For more information, please contact iText Software Corp. at this
042 * address: sales@itextpdf.com
043 */
044package com.itextpdf.text.pdf.codec.wmf;
045
046import java.util.ArrayList;
047import java.util.Stack;
048
049import com.itextpdf.text.BaseColor;
050import com.itextpdf.text.pdf.PdfContentByte;
051
052public class MetaState {
053
054    public static final int TA_NOUPDATECP = 0;
055    public static final int TA_UPDATECP = 1;
056    public static final int TA_LEFT = 0;
057    public static final int TA_RIGHT = 2;
058    public static final int TA_CENTER = 6;
059    public static final int TA_TOP = 0;
060    public static final int TA_BOTTOM = 8;
061    public static final int TA_BASELINE = 24;
062
063    public static final int TRANSPARENT = 1;
064    public static final int OPAQUE = 2;
065
066    public static final int ALTERNATE = 1;
067    public static final int WINDING = 2;
068
069    public Stack<MetaState> savedStates;
070    public ArrayList<MetaObject> MetaObjects;
071    public Point currentPoint;
072    public MetaPen currentPen;
073    public MetaBrush currentBrush;
074    public MetaFont currentFont;
075    public BaseColor currentBackgroundColor = BaseColor.WHITE;
076    public BaseColor currentTextColor = BaseColor.BLACK;
077    public int backgroundMode = OPAQUE;
078    public int polyFillMode = ALTERNATE;
079    public int lineJoin = 1;
080    public int textAlign;
081    public int offsetWx;
082    public int offsetWy;
083    public int extentWx;
084    public int extentWy;
085    public float scalingX;
086    public float scalingY;
087
088
089    /** Creates new MetaState */
090    public MetaState() {
091        savedStates = new Stack<MetaState>();
092        MetaObjects = new ArrayList<MetaObject>();
093        currentPoint = new Point(0, 0);
094        currentPen = new MetaPen();
095        currentBrush = new MetaBrush();
096        currentFont = new MetaFont();
097    }
098
099    public MetaState(MetaState state) {
100        setMetaState(state);
101    }
102
103    public void setMetaState(MetaState state) {
104        savedStates = state.savedStates;
105        MetaObjects = state.MetaObjects;
106        currentPoint = state.currentPoint;
107        currentPen = state.currentPen;
108        currentBrush = state.currentBrush;
109        currentFont = state.currentFont;
110        currentBackgroundColor = state.currentBackgroundColor;
111        currentTextColor = state.currentTextColor;
112        backgroundMode = state.backgroundMode;
113        polyFillMode = state.polyFillMode;
114        textAlign = state.textAlign;
115        lineJoin = state.lineJoin;
116        offsetWx = state.offsetWx;
117        offsetWy = state.offsetWy;
118        extentWx = state.extentWx;
119        extentWy = state.extentWy;
120        scalingX = state.scalingX;
121        scalingY = state.scalingY;
122    }
123
124    public void addMetaObject(MetaObject object) {
125        for (int k = 0; k < MetaObjects.size(); ++k) {
126            if (MetaObjects.get(k) == null) {
127                MetaObjects.set(k, object);
128                return;
129            }
130        }
131        MetaObjects.add(object);
132    }
133
134    public void selectMetaObject(int index, PdfContentByte cb) {
135        MetaObject obj = MetaObjects.get(index);
136        if (obj == null)
137            return;
138        int style;
139        switch (obj.getType()) {
140            case MetaObject.META_BRUSH:
141                currentBrush = (MetaBrush)obj;
142                style = currentBrush.getStyle();
143                if (style == MetaBrush.BS_SOLID) {
144                    BaseColor color = currentBrush.getColor();
145                    cb.setColorFill(color);
146                }
147                else if (style == MetaBrush.BS_HATCHED) {
148                    BaseColor color = currentBackgroundColor;
149                    cb.setColorFill(color);
150                }
151                break;
152            case MetaObject.META_PEN:
153            {
154                currentPen = (MetaPen)obj;
155                style = currentPen.getStyle();
156                if (style != MetaPen.PS_NULL) {
157                    BaseColor color = currentPen.getColor();
158                    cb.setColorStroke(color);
159                    cb.setLineWidth(Math.abs(currentPen.getPenWidth() * scalingX / extentWx));
160                    switch (style) {
161                        case MetaPen.PS_DASH:
162                            cb.setLineDash(18, 6, 0);
163                            break;
164                        case MetaPen.PS_DASHDOT:
165                            cb.setLiteral("[9 6 3 6]0 d\n");
166                            break;
167                        case MetaPen.PS_DASHDOTDOT:
168                            cb.setLiteral("[9 3 3 3 3 3]0 d\n");
169                            break;
170                        case MetaPen.PS_DOT:
171                            cb.setLineDash(3, 0);
172                            break;
173                        default:
174                            cb.setLineDash(0);
175                            break;
176                    }
177                }
178                break;
179            }
180            case MetaObject.META_FONT:
181            {
182                currentFont = (MetaFont)obj;
183                break;
184            }
185        }
186    }
187
188    public void deleteMetaObject(int index) {
189        MetaObjects.set(index, null);
190    }
191
192    public void saveState(PdfContentByte cb) {
193        cb.saveState();
194        MetaState state = new MetaState(this);
195        savedStates.push(state);
196    }
197
198    public void restoreState(int index, PdfContentByte cb) {
199        int pops;
200        if (index < 0)
201            pops = Math.min(-index, savedStates.size());
202        else
203            pops = Math.max(savedStates.size() - index, 0);
204        if (pops == 0)
205            return;
206        MetaState state = null;
207        while (pops-- != 0) {
208            cb.restoreState();
209            state = savedStates.pop();
210        }
211        setMetaState(state);
212    }
213
214    public void cleanup(PdfContentByte cb) {
215        int k = savedStates.size();
216        while (k-- > 0)
217            cb.restoreState();
218    }
219
220    public float transformX(int x) {
221        return ((float)x - offsetWx) * scalingX / extentWx;
222    }
223
224    public float transformY(int y) {
225        return (1f - ((float)y - offsetWy) / extentWy) * scalingY;
226    }
227
228    public void setScalingX(float scalingX) {
229        this.scalingX = scalingX;
230    }
231
232    public void setScalingY(float scalingY) {
233        this.scalingY = scalingY;
234    }
235
236    public void setOffsetWx(int offsetWx) {
237        this.offsetWx = offsetWx;
238    }
239
240    public void setOffsetWy(int offsetWy) {
241        this.offsetWy = offsetWy;
242    }
243
244    public void setExtentWx(int extentWx) {
245        this.extentWx = extentWx;
246    }
247
248    public void setExtentWy(int extentWy) {
249        this.extentWy = extentWy;
250    }
251
252    public float transformAngle(float angle) {
253        float ta = scalingY < 0 ? -angle : angle;
254        return (float)(scalingX < 0 ? Math.PI - ta : ta);
255    }
256
257    public void setCurrentPoint(Point p) {
258        currentPoint = p;
259    }
260
261    public Point getCurrentPoint() {
262        return currentPoint;
263    }
264
265    public MetaBrush getCurrentBrush() {
266        return currentBrush;
267    }
268
269    public MetaPen getCurrentPen() {
270        return currentPen;
271    }
272
273    public MetaFont getCurrentFont() {
274        return currentFont;
275    }
276
277    /** Getter for property currentBackgroundColor.
278     * @return Value of property currentBackgroundColor.
279     */
280    public BaseColor getCurrentBackgroundColor() {
281        return currentBackgroundColor;
282    }
283
284    /** Setter for property currentBackgroundColor.
285     * @param currentBackgroundColor New value of property currentBackgroundColor.
286     */
287    public void setCurrentBackgroundColor(BaseColor currentBackgroundColor) {
288        this.currentBackgroundColor = currentBackgroundColor;
289    }
290
291    /** Getter for property currentTextColor.
292     * @return Value of property currentTextColor.
293     */
294    public BaseColor getCurrentTextColor() {
295        return currentTextColor;
296    }
297
298    /** Setter for property currentTextColor.
299     * @param currentTextColor New value of property currentTextColor.
300     */
301    public void setCurrentTextColor(BaseColor currentTextColor) {
302        this.currentTextColor = currentTextColor;
303    }
304
305    /** Getter for property backgroundMode.
306     * @return Value of property backgroundMode.
307     */
308    public int getBackgroundMode() {
309        return backgroundMode;
310    }
311
312    /** Setter for property backgroundMode.
313     * @param backgroundMode New value of property backgroundMode.
314     */
315    public void setBackgroundMode(int backgroundMode) {
316        this.backgroundMode = backgroundMode;
317    }
318
319    /** Getter for property textAlign.
320     * @return Value of property textAlign.
321     */
322    public int getTextAlign() {
323        return textAlign;
324    }
325
326    /** Setter for property textAlign.
327     * @param textAlign New value of property textAlign.
328     */
329    public void setTextAlign(int textAlign) {
330        this.textAlign = textAlign;
331    }
332
333    /** Getter for property polyFillMode.
334     * @return Value of property polyFillMode.
335     */
336    public int getPolyFillMode() {
337        return polyFillMode;
338    }
339
340    /** Setter for property polyFillMode.
341     * @param polyFillMode New value of property polyFillMode.
342     */
343    public void setPolyFillMode(int polyFillMode) {
344        this.polyFillMode = polyFillMode;
345    }
346
347    public void setLineJoinRectangle(PdfContentByte cb) {
348        if (lineJoin != 0) {
349            lineJoin = 0;
350            cb.setLineJoin(0);
351        }
352    }
353
354    public void setLineJoinPolygon(PdfContentByte cb) {
355        if (lineJoin == 0) {
356            lineJoin = 1;
357            cb.setLineJoin(1);
358        }
359    }
360
361    public boolean getLineNeutral() {
362        return lineJoin == 0;
363    }
364
365}