1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17/**
18 * @author Ilya S. Okomin
19 * @version $Revision$
20 */
21
22package java.awt.font;
23
24import java.awt.BasicStroke;
25import java.awt.Graphics2D;
26import java.awt.Shape;
27import java.awt.Stroke;
28import java.awt.geom.AffineTransform;
29import java.awt.geom.Rectangle2D;
30
31import org.apache.harmony.misc.HashCode;
32
33/**
34 * The ShapeGraphicAttribute class provides an opportunity to insert shapes to a
35 * text.
36 *
37 * @since Android 1.0
38 */
39public final class ShapeGraphicAttribute extends GraphicAttribute {
40
41    // shape to render
42    /**
43     * The shape.
44     */
45    private Shape fShape;
46
47    // flag, if the shape should be stroked (true) or filled (false)
48    /**
49     * The stroke.
50     */
51    private boolean fStroke;
52
53    // bounds of the shape
54    /**
55     * The bounds.
56     */
57    private Rectangle2D fBounds;
58
59    // X coordinate of the origin point
60    /**
61     * The origin x.
62     */
63    private float fOriginX;
64
65    // Y coordinate of the origin point
66    /**
67     * The origin y.
68     */
69    private float fOriginY;
70
71    // width of the shape
72    /**
73     * The shape width.
74     */
75    private float fShapeWidth;
76
77    // height of the shape
78    /**
79     * The shape height.
80     */
81    private float fShapeHeight;
82
83    /**
84     * The Constant STROKE indicates whether the Shape is stroked or not.
85     */
86    public static final boolean STROKE = true;
87
88    /**
89     * The Constant FILL indicates whether the Shape is filled or not.
90     */
91    public static final boolean FILL = false;
92
93    /**
94     * Instantiates a new ShapeGraphicAttribute object for the specified Shape.
95     *
96     * @param shape
97     *            the shape to be rendered by this ShapeGraphicAttribute.
98     * @param alignment
99     *            the alignment of this ShapeGraphicAttribute.
100     * @param stroke
101     *            true if the Shape is stroked, false if the Shape is filled.
102     */
103    public ShapeGraphicAttribute(Shape shape, int alignment, boolean stroke) {
104        super(alignment);
105
106        this.fShape = shape;
107        this.fStroke = stroke;
108
109        this.fBounds = fShape.getBounds2D();
110
111        this.fOriginX = (float)fBounds.getMinX();
112        this.fOriginY = (float)fBounds.getMinY();
113
114        this.fShapeWidth = (float)fBounds.getWidth();
115        this.fShapeHeight = (float)fBounds.getHeight();
116    }
117
118    /**
119     * Returns a hash code of this ShapeGraphicAttribute object.
120     *
121     * @return a hash code of this ShapeGraphicAttribute object.
122     */
123    @Override
124    public int hashCode() {
125        HashCode hash = new HashCode();
126
127        hash.append(fShape.hashCode());
128        hash.append(getAlignment());
129        return hash.hashCode();
130    }
131
132    /**
133     * Compares this ShapeGraphicAttribute object to the specified
134     * ShapeGraphicAttribute object.
135     *
136     * @param sga
137     *            the ShapeGraphicAttribute object to be compared.
138     * @return true, if this ShapeGraphicAttribute object is equal to the
139     *         specified ShapeGraphicAttribute object, false otherwise.
140     */
141    public boolean equals(ShapeGraphicAttribute sga) {
142        if (sga == null) {
143            return false;
144        }
145
146        if (sga == this) {
147            return true;
148        }
149
150        return (fStroke == sga.fStroke && getAlignment() == sga.getAlignment() && fShape
151                .equals(sga.fShape));
152
153    }
154
155    /**
156     * Compares this ShapeGraphicAttribute object to the specified Object.
157     *
158     * @param obj
159     *            the Object to be compared.
160     * @return true, if this ShapeGraphicAttribute object is equal to the
161     *         specified Object, false otherwise.
162     */
163    @Override
164    public boolean equals(Object obj) {
165        try {
166            return equals((ShapeGraphicAttribute)obj);
167        } catch (ClassCastException e) {
168            return false;
169        }
170    }
171
172    @Override
173    public void draw(Graphics2D g2, float x, float y) {
174        AffineTransform at = AffineTransform.getTranslateInstance(x, y);
175        if (fStroke == STROKE) {
176            Stroke oldStroke = g2.getStroke();
177            g2.setStroke(new BasicStroke());
178            g2.draw(at.createTransformedShape(fShape));
179            g2.setStroke(oldStroke);
180        } else {
181            g2.fill(at.createTransformedShape(fShape));
182        }
183
184    }
185
186    @Override
187    public float getAdvance() {
188        return Math.max(0, fShapeWidth + fOriginX);
189    }
190
191    @Override
192    public float getAscent() {
193        return Math.max(0, -fOriginY);
194    }
195
196    @Override
197    public Rectangle2D getBounds() {
198        return (Rectangle2D)fBounds.clone();
199    }
200
201    @Override
202    public float getDescent() {
203        return Math.max(0, fShapeHeight + fOriginY);
204    }
205
206}
207