1/*
2 * Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26/*
27 * (C) Copyright Taligent, Inc. 1996 - 1997, All Rights Reserved
28 * (C) Copyright IBM Corp. 1996 - 1998, All Rights Reserved
29 *
30 * The original version of this source code and documentation is
31 * copyrighted and owned by Taligent, Inc., a wholly-owned subsidiary
32 * of IBM. These materials are provided under terms of a License
33 * Agreement between Taligent and Sun. This technology is protected
34 * by multiple US and International patents.
35 *
36 * This notice and attribution to Taligent may not be removed.
37 * Taligent is a registered trademark of Taligent, Inc.
38 *
39 */
40
41package java.awt.font;
42
43import java.awt.Graphics2D;
44import java.awt.Font;
45import java.awt.Shape;
46import java.awt.geom.AffineTransform;
47import java.awt.geom.Rectangle2D;
48
49/**
50 * This class is used with the CHAR_REPLACEMENT attribute.
51 * <p>
52 * The {@code GraphicAttribute} class represents a graphic embedded
53 * in text. Clients subclass this class to implement their own char
54 * replacement graphics.  Clients wishing to embed shapes and images in
55 * text need not subclass this class.  Instead, clients can use the
56 * {@link ShapeGraphicAttribute} and {@link ImageGraphicAttribute}
57 * classes.
58 * <p>
59 * Subclasses must ensure that their objects are immutable once they
60 * are constructed.  Mutating a {@code GraphicAttribute} that
61 * is used in a {@link TextLayout} results in undefined behavior from the
62 * {@code TextLayout}.
63 */
64public abstract class GraphicAttribute {
65
66    private int fAlignment;
67
68    /**
69     * Aligns top of graphic to top of line.
70     */
71    public static final int TOP_ALIGNMENT = -1;
72
73    /**
74     * Aligns bottom of graphic to bottom of line.
75     */
76    public static final int BOTTOM_ALIGNMENT = -2;
77
78    /**
79     * Aligns origin of graphic to roman baseline of line.
80     */
81    public static final int ROMAN_BASELINE = Font.ROMAN_BASELINE;
82
83    /**
84     * Aligns origin of graphic to center baseline of line.
85     */
86    public static final int CENTER_BASELINE = Font.CENTER_BASELINE;
87
88    /**
89     * Aligns origin of graphic to hanging baseline of line.
90     */
91    public static final int HANGING_BASELINE = Font.HANGING_BASELINE;
92
93    /**
94     * Constructs a {@code GraphicAttribute}.
95     * Subclasses use this to define the alignment of the graphic.
96     * @param alignment an int representing one of the
97     * {@code GraphicAttribute} alignment fields
98     * @throws IllegalArgumentException if alignment is not one of the
99     * five defined values.
100     */
101    protected GraphicAttribute(int alignment) {
102        if (alignment < BOTTOM_ALIGNMENT || alignment > HANGING_BASELINE) {
103          throw new IllegalArgumentException("bad alignment");
104        }
105        fAlignment = alignment;
106    }
107
108    /**
109     * Returns the ascent of this {@code GraphicAttribute}.  A
110     * graphic can be rendered above its ascent.
111     * @return the ascent of this {@code GraphicAttribute}.
112     * @see #getBounds()
113     */
114    public abstract float getAscent();
115
116
117    /**
118     * Returns the descent of this {@code GraphicAttribute}.  A
119     * graphic can be rendered below its descent.
120     * @return the descent of this {@code GraphicAttribute}.
121     * @see #getBounds()
122     */
123    public abstract float getDescent();
124
125    /**
126     * Returns the advance of this {@code GraphicAttribute}.  The
127     * {@code GraphicAttribute} object's advance is the distance
128     * from the point at which the graphic is rendered and the point where
129     * the next character or graphic is rendered.  A graphic can be
130     * rendered beyond its advance
131     * @return the advance of this {@code GraphicAttribute}.
132     * @see #getBounds()
133     */
134    public abstract float getAdvance();
135
136    /**
137     * Returns a {@link Rectangle2D} that encloses all of the
138     * bits drawn by this {@code GraphicAttribute} relative to the
139     * rendering position.
140     * A graphic may be rendered beyond its origin, ascent, descent,
141     * or advance;  but if it is, this method's implementation must
142     * indicate where the graphic is rendered.
143     * Default bounds is the rectangle (0, -ascent, advance, ascent+descent).
144     * @return a {@code Rectangle2D} that encloses all of the bits
145     * rendered by this {@code GraphicAttribute}.
146     */
147    public Rectangle2D getBounds() {
148        float ascent = getAscent();
149        return new Rectangle2D.Float(0, -ascent,
150                                        getAdvance(), ascent+getDescent());
151    }
152
153    /**
154     * Return a {@link java.awt.Shape} that represents the region that
155     * this {@code GraphicAttribute} renders.  This is used when a
156     * {@link TextLayout} is requested to return the outline of the text.
157     * The (untransformed) shape must not extend outside the rectangular
158     * bounds returned by {@code getBounds}.
159     * The default implementation returns the rectangle returned by
160     * {@link #getBounds}, transformed by the provided {@link AffineTransform}
161     * if present.
162     * @param tx an optional {@link AffineTransform} to apply to the
163     *   outline of this {@code GraphicAttribute}. This can be null.
164     * @return a {@code Shape} representing this graphic attribute,
165     *   suitable for stroking or filling.
166     * @since 1.6
167     */
168    public Shape getOutline(AffineTransform tx) {
169        Shape b = getBounds();
170        if (tx != null) {
171            b = tx.createTransformedShape(b);
172        }
173        return b;
174    }
175
176    /**
177     * Renders this {@code GraphicAttribute} at the specified
178     * location.
179     * @param graphics the {@link Graphics2D} into which to render the
180     * graphic
181     * @param x the user-space X coordinate where the graphic is rendered
182     * @param y the user-space Y coordinate where the graphic is rendered
183     */
184    public abstract void draw(Graphics2D graphics, float x, float y);
185
186    /**
187     * Returns the alignment of this {@code GraphicAttribute}.
188     * Alignment can be to a particular baseline, or to the absolute top
189     * or bottom of a line.
190     * @return the alignment of this {@code GraphicAttribute}.
191     */
192    public final int getAlignment() {
193
194        return fAlignment;
195    }
196
197    /**
198     * Returns the justification information for this
199     * {@code GraphicAttribute}.  Subclasses
200     * can override this method to provide different justification
201     * information.
202     * @return a {@link GlyphJustificationInfo} object that contains the
203     * justification information for this {@code GraphicAttribute}.
204     */
205    public GlyphJustificationInfo getJustificationInfo() {
206
207        // should we cache this?
208        float advance = getAdvance();
209
210        return new GlyphJustificationInfo(
211                                     advance,   // weight
212                                     false,     // growAbsorb
213                                     2,         // growPriority
214                                     advance/3, // growLeftLimit
215                                     advance/3, // growRightLimit
216                                     false,     // shrinkAbsorb
217                                     1,         // shrinkPriority
218                                     0,         // shrinkLeftLimit
219                                     0);        // shrinkRightLimit
220    }
221}
222