001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: /**
018: * @author Ilya S. Okomin
019: * @version $Revision$
020: */package org.apache.harmony.awt.gl.linux;
021:
022: import java.awt.Color;
023: import java.awt.Graphics2D;
024: import java.awt.font.GlyphVector;
025: import java.awt.geom.AffineTransform;
026: import java.awt.geom.Point2D;
027: import java.awt.RenderingHints;
028:
029: import org.apache.harmony.awt.gl.CommonGraphics2D;
030: import org.apache.harmony.awt.gl.TextRenderer;
031: import org.apache.harmony.awt.gl.font.CommonGlyphVector;
032: import org.apache.harmony.awt.gl.font.CompositeFont;
033: import org.apache.harmony.awt.gl.font.FontManager;
034: import org.apache.harmony.awt.gl.font.FontPeerImpl;
035: import org.apache.harmony.awt.gl.font.Glyph;
036: import org.apache.harmony.awt.gl.font.LinuxFont;
037: import org.apache.harmony.awt.gl.font.LinuxNativeFont;
038:
039: import org.apache.harmony.awt.nativebridge.linux.X11;
040:
041: /**
042: *
043: * Linux text renderer, works using XFT text rendering
044: */
045: public class DrawableTextRenderer extends TextRenderer {
046:
047: /** Singleton DrawableTextRenderer instance */
048: public static final DrawableTextRenderer inst = new DrawableTextRenderer();
049:
050: // X11 instance
051: static final X11 x11 = X11.getInstance();
052:
053: boolean isAntialiasingHintSet(Graphics2D g) {
054: Object value = g
055: .getRenderingHint(RenderingHints.KEY_ANTIALIASING);
056: return (value == RenderingHints.VALUE_ANTIALIAS_ON);
057: }
058:
059: public void drawString(Graphics2D ga, String str, float x, float y) {
060: CommonGraphics2D g = (CommonGraphics2D) ga;
061: AffineTransform trans = g.getTransform();
062: double xOffset = x + trans.getTranslateX();
063: double yOffset = y + trans.getTranslateY();
064:
065: FontPeerImpl fnt = (FontPeerImpl) g.getFont().getPeer();
066:
067: if (fnt.getClass() == CompositeFont.class) {
068: drawCompositeString(g, str, xOffset, yOffset);
069: } else {
070: drawNormalString(g, str, xOffset, yOffset);
071: }
072:
073: }
074:
075: /**
076: * Returns XColor structure corresponding to the desired Color.
077: * @param color specified Color
078: */
079: static X11.XColor getXColor(Color color) {
080: X11.XColor xcolor = x11.createXColor(false);
081:
082: xcolor.set_green((short) (color.getGreen() << 8));
083: xcolor.set_blue((short) (color.getBlue() << 8));
084: xcolor.set_red((short) (color.getRed() << 8));
085:
086: return xcolor;
087: }
088:
089: /**
090: * Method to draw string with graphics that has physical font
091: * at desired coordinates.
092: *
093: * @param g CommonGraphics2D to draw onto
094: * @param str String to draw
095: * @param x starting X coordinate to draw at
096: * @param y starting Y coordinate to draw at
097: */
098: public void drawNormalString(CommonGraphics2D g, String str,
099: double x, double y) {
100: XGraphics2D xg2d = (XGraphics2D) g;
101:
102: long display = xg2d.display;
103: int screen = xg2d.xConfig.dev.screen;
104: long colormap = x11.XDefaultColormap(display, screen);
105:
106: LinuxFont peer = (LinuxFont) g.getFont().getPeer();
107:
108: X11.XColor xcolor = getXColor(g.getColor());
109: long xcolorPtr = xcolor.lock();
110:
111: /*
112: * Work around for escape-subsequences.
113: * We don't draw anything instead of \n,\r,\t
114: *
115: * */
116: char[] outChars = new char[str.length()];
117: char[] inChars = str.toCharArray();
118: int j = 0;
119: for (int i = 0; i < inChars.length; i++) {
120: if (peer.getFontType() == FontManager.FONT_TYPE_T1) {
121: if (!peer.isGlyphExists(inChars[i])) {
122: continue;
123: }
124: }
125:
126: switch (inChars[i]) {
127: case '\n':
128: case '\r':
129: case '\t':
130: break;
131: default:
132: outChars[j] = inChars[i];
133: j++;
134: }
135: }
136: if (inChars.length != 0) {
137: LinuxNativeFont.drawStringNative(xg2d.xftDraw, display,
138: colormap, peer
139: .getFontHandle(isAntialiasingHintSet(g)),
140: (int) Math.round(x), (int) Math.round(y), outChars,
141: j, xcolorPtr);
142: }
143: xcolor.unlock();
144:
145: }
146:
147: /**
148: * Method to draw string with graphics that has composite font
149: * at desired coordinates.
150: *
151: * @param g CommonGraphics2D to draw onto
152: * @param str String to draw
153: * @param x starting X coordinate to draw at
154: * @param y starting Y coordinate to draw at
155: */
156: public void drawCompositeString(CommonGraphics2D g, String str,
157: double x, double y) {
158: XGraphics2D xg2d = (XGraphics2D) g;
159:
160: long display = xg2d.display;
161: int screen = xg2d.xConfig.dev.screen;
162: long colormap = x11.XDefaultColormap(display, screen);
163:
164: X11.XColor xcolor = getXColor(g.getColor());
165: long xcolorPtr = xcolor.lock();
166:
167: CompositeFont wcf = (CompositeFont) (g.getFont().getPeer());
168: long font = 0;
169: int xOffset = (int) Math.round(x); // X offset to draw
170: int yOffset = (int) Math.round(y); // Y offset to draw
171: int offs = 0; // width of substring with the same font header
172: String sChars = new String();
173: char chars[];
174: for (int i = 0; i < str.length(); i++) {
175: char c = str.charAt(i);
176: Glyph gl = wcf.getGlyph(c);
177: if (font == 0) {
178: font = gl.getPFont();
179: }
180: int glWidth = Math.round(gl.getGlyphPointMetrics()
181: .getAdvance());
182: if (glWidth == 0) {
183: continue;
184: }
185: long glPFont = gl.getPFont();
186: if (font != glPFont) {
187: chars = sChars.toCharArray();
188: LinuxNativeFont.drawStringNative(xg2d.xftDraw, display,
189: colormap, font, xOffset, yOffset, chars, sChars
190: .length(), xcolorPtr);
191:
192: xOffset += offs;
193: offs = 0;
194: sChars = String.valueOf(gl.getChar());
195: font = glPFont;
196: } else {
197: sChars += String.valueOf(gl.getChar());
198: }
199: offs += glWidth;
200: }
201: chars = sChars.toCharArray();
202: if (chars.length != 0) {
203: LinuxNativeFont.drawStringNative(xg2d.xftDraw, display,
204: colormap, font, xOffset, yOffset, chars, sChars
205: .length(), xcolorPtr);
206: }
207: xcolor.unlock();
208:
209: }
210:
211: public void drawGlyphVector(Graphics2D ga, GlyphVector gv, float x,
212: float y) {
213: CommonGraphics2D g = (CommonGraphics2D) ga;
214: AffineTransform trans = g.getTransform();
215: float xOffset = x + (float) trans.getTranslateX();
216: float yOffset = y + (float) trans.getTranslateY();
217:
218: FontPeerImpl fnt = (FontPeerImpl) gv.getFont().getPeer();
219: if (fnt.getClass() == CompositeFont.class) {
220: drawCompositeGlyphVector(g, gv, xOffset, yOffset);
221: } else {
222: drawNormalGlyphVector(g, gv, xOffset, yOffset);
223: }
224:
225: }
226:
227: /**
228: * Method to draw GlyphVector created from physical font onto a
229: * specified graphics at desired coordinates.
230: *
231: * @param g CommonGraphics2D to draw onto
232: * @param glyphVector GlyphVector to draw
233: * @param x starting X coordinate to draw at
234: * @param y starting Y coordinate to draw at
235: */
236: public void drawNormalGlyphVector(CommonGraphics2D g,
237: GlyphVector glyphVector, float x, float y) {
238:
239: XGraphics2D xg2d = (XGraphics2D) g;
240:
241: long display = xg2d.display;
242: int screen = xg2d.xConfig.dev.screen;
243: long colormap = x11.XDefaultColormap(display, screen);
244:
245: LinuxFont peer = (LinuxFont) glyphVector.getFont().getPeer();
246:
247: X11.XColor xcolor = getXColor(g.getColor());
248: long xcolorPtr = xcolor.lock();
249:
250: for (int i = 0; i < glyphVector.getNumGlyphs(); i++) {
251:
252: Glyph gl = ((CommonGlyphVector) glyphVector).vector[i];
253: if (gl.getPointWidth() == 0) {
254: continue;
255: }
256:
257: Point2D pos = glyphVector.getGlyphPosition(i);
258:
259: int xBaseLine = (int) Math.round(x + pos.getX());
260: int yBaseLine = (int) Math.round(y + pos.getY());
261: char chars[] = { gl.getChar() };
262:
263: LinuxNativeFont.drawStringNative(xg2d.xftDraw, display,
264: colormap, peer
265: .getFontHandle(isAntialiasingHintSet(g)),
266: xBaseLine, yBaseLine, chars, 1, xcolorPtr);
267: }
268: xcolor.unlock();
269:
270: }
271:
272: /**
273: * Method to draw GlyphVector created from composite font onto a
274: * specified graphics at desired coordinates.
275: *
276: * @param g CommonGraphics2D to draw onto
277: * @param glyphVector GlyphVector to draw
278: * @param x starting X coordinate to draw at
279: * @param y starting Y coordinate to draw at
280: */
281: public void drawCompositeGlyphVector(CommonGraphics2D g,
282: GlyphVector glyphVector, float x, float y) {
283:
284: XGraphics2D xg2d = (XGraphics2D) g;
285: long display = xg2d.display;
286: int screen = xg2d.xConfig.dev.screen;
287: long colormap = x11.XDefaultColormap(display, screen);
288:
289: X11.XColor xcolor = getXColor(g.getColor());
290: long xcolorPtr = xcolor.lock();
291:
292: for (int i = 0; i < glyphVector.getNumGlyphs(); i++) {
293:
294: Glyph gl = ((CommonGlyphVector) glyphVector).vector[i];
295: if (gl.getPointWidth() == 0) {
296: continue;
297: }
298:
299: Point2D pos = glyphVector.getGlyphPosition(i);
300:
301: int xBaseLine = (int) Math.round(x + pos.getX());
302: int yBaseLine = (int) Math.round(y + pos.getY());
303: char chars[] = { gl.getChar() };
304:
305: LinuxNativeFont.drawStringNative(xg2d.xftDraw, display,
306: colormap, gl.getPFont(), xBaseLine, yBaseLine,
307: chars, 1, xcolorPtr);
308: }
309: xcolor.unlock();
310:
311: }
312: }
|