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.windows;
021:
022: import java.awt.Graphics2D;
023: import java.awt.font.GlyphVector;
024: import java.awt.geom.AffineTransform;
025: import java.awt.geom.Point2D;
026:
027: import org.apache.harmony.awt.gl.TextRenderer;
028: import org.apache.harmony.awt.gl.font.CommonGlyphVector;
029: import org.apache.harmony.awt.gl.font.CompositeFont;
030: import org.apache.harmony.awt.gl.font.FontPeerImpl;
031: import org.apache.harmony.awt.gl.font.Glyph;
032: import org.apache.harmony.awt.gl.font.NativeFont;
033: import org.apache.harmony.awt.gl.font.WindowsFont;
034:
035: import org.apache.harmony.awt.nativebridge.windows.WindowsDefs;
036: import org.apache.harmony.awt.nativebridge.windows.Win32;
037:
038: /**
039: *
040: * TextRenderer that works by means of GDI calls.
041: */
042:
043: public class GDITextRenderer extends TextRenderer {
044:
045: // GDI Pen object handle
046: long curPen;
047:
048: // curPen's color
049: int curPenColor;
050:
051: // GDI clipped region
052: long hOldGDIRgn = 0;
053:
054: // Win32 instance
055: private final Win32 win32 = Win32.getInstance();
056:
057: /** GDITextRenderer singleton instance */
058: public static final GDITextRenderer inst = new GDITextRenderer();
059:
060: private GDITextRenderer() {
061: }
062:
063: // Convert from aarrggbb to 00bbggrr
064: private int getGDIColor(int argbPix) {
065: return ((argbPix & 0x00FF0000) >> 16) | (argbPix & 0x0000FF00)
066: | ((argbPix & 0x000000FF) << 16);
067: }
068:
069: @SuppressWarnings("deprecation")
070: @Override
071: public void drawGlyphVector(Graphics2D g, GlyphVector gv, float x,
072: float y) {
073: FontPeerImpl fnt = (FontPeerImpl) gv.getFont().getPeer();
074: if (fnt.getClass() == CompositeFont.class) {
075: drawCompositeGlyphVector(g, gv, x, y);
076: } else {
077: drawNormalGlyphVector(g, gv, x, y);
078: }
079: }
080:
081: /**
082: * Method to draw GlyphVector created from physical font onto a
083: * specified graphics at desired coordinates.
084: *
085: * @param g Graphics to draw onto
086: * @param gv GlyphVector to draw
087: * @param x starting X coordinate to draw at
088: * @param y starting Y coordinate to draw at
089: */
090: @SuppressWarnings("deprecation")
091: public void drawNormalGlyphVector(Graphics2D g, GlyphVector gv,
092: float x, float y) {
093: AffineTransform trans = ((WinGDIGraphics2D) g).getTransform();
094: long hdc = ((WinGDIGraphics2D) g).getDC();
095:
096: x += trans.getTranslateX();
097: y += trans.getTranslateY();
098:
099: win32.SetTextColor(hdc, getGDIColor(g.getColor().getRGB()));
100: win32.SetBkMode(hdc, WindowsDefs.TRANSPARENT);
101:
102: WindowsFont wf = (WindowsFont) gv.getFont().getPeer();
103:
104: int ascent = wf.getAscent();
105: long font = wf.getFontHandle();
106: long oldFont = win32.SelectObject(hdc, font);
107:
108: for (int i = 0; i < gv.getNumGlyphs(); i++) {
109: Glyph gl = ((CommonGlyphVector) gv).vector[i];
110: char chr = gl.getChar();
111:
112: if (gl.getPointWidth() == 0) {
113: continue;
114: }
115:
116: String sChar = String.valueOf(chr);
117:
118: Point2D pos = gv.getGlyphPosition(i);
119: win32
120: .TextOutW(hdc, (int) Math.round(x + pos.getX()),
121: (int) Math.round(y + pos.getY() - ascent),
122: sChar, 1);
123: }
124:
125: win32.SelectObject(hdc, oldFont);
126: }
127:
128: /**
129: * Method to draw GlyphVector created from composite font onto a
130: * specified graphics at desired coordinates.
131: *
132: * @param g Graphics to draw onto
133: * @param gv GlyphVector to draw
134: * @param x starting X coordinate to draw at
135: * @param y starting Y coordinate to draw at
136: */
137: @SuppressWarnings("deprecation")
138: public void drawCompositeGlyphVector(Graphics2D g, GlyphVector gv,
139: float x, float y) {
140: AffineTransform trans = ((WinGDIGraphics2D) g).getTransform();
141: long hdc = ((WinGDIGraphics2D) g).getDC();
142:
143: x += (int) Math.round(trans.getTranslateX());
144: y += (int) Math.round(trans.getTranslateY());
145:
146: win32.SetTextColor(hdc, getGDIColor(g.getColor().getRGB()));
147: win32.SetBkMode(hdc, WindowsDefs.TRANSPARENT);
148:
149: CompositeFont cf = (CompositeFont) gv.getFont().getPeer();
150:
151: int ascent = cf.getAscent();
152:
153: long font = 0;
154:
155: for (int i = 0; i < gv.getNumGlyphs(); i++) {
156: Glyph gl = ((CommonGlyphVector) gv).vector[i];
157: char chr = gl.getChar();
158:
159: if (gl.getPointWidth() == 0) {
160: continue;
161: }
162:
163: String sChar = String.valueOf(chr);
164:
165: long glPFont = gl.getPFont();
166: if (font != glPFont) {
167: font = glPFont;
168: win32.SelectObject(hdc, font);
169: }
170:
171: Point2D pos = gv.getGlyphPosition(i);
172: win32
173: .TextOutW(hdc, (int) Math.round(x + pos.getX()),
174: (int) Math.round(y + pos.getY() - ascent),
175: sChar, 1);
176: }
177: }
178:
179: @SuppressWarnings("deprecation")
180: @Override
181: public void drawString(Graphics2D g, String str, float x, float y) {
182: FontPeerImpl fnt = (FontPeerImpl) g.getFont().getPeer();
183: if (fnt.getClass() == CompositeFont.class) {
184: drawCompositeString(g, str, Math.round(x), Math.round(y));
185: } else {
186: drawNormalString(g, str, Math.round(x), Math.round(y));
187: }
188: }
189:
190: /**
191: * Method to draw string with graphics that has physical font
192: * at desired coordinates.
193: *
194: * @param g Graphics to draw onto
195: * @param str String to draw
196: * @param x starting X coordinate to draw at
197: * @param y starting Y coordinate to draw at
198: */
199: @SuppressWarnings("deprecation")
200: public void drawNormalString(Graphics2D g, String str, int x, int y) {
201: AffineTransform trans = ((WinGDIGraphics2D) g).getTransform();
202:
203: x += (int) Math.round(trans.getTranslateX());
204: y += (int) Math.round(trans.getTranslateY());
205:
206: WindowsFont wf = (WindowsFont) (g.getFont().getPeer());
207: long font = wf.getFontHandle();
208:
209: long gi = ((WinGDIGraphics2D) g).getGraphicsInfo();
210: long hdc = ((WinGDIGraphics2D) g).getDC();
211:
212: win32.SelectObject(hdc, font);
213:
214: win32.SetTextColor(hdc, getGDIColor(g.getColor().getRGB()));
215: win32.SetBkMode(hdc, WindowsDefs.TRANSPARENT);
216:
217: /*
218: * Work around for escape-subsequences. If e.g. we draw
219: * string "\n\uFFFF" - instead of default glyph for \uFFFF
220: * GDI draws small vertical rectangle. For this reason we draw
221: * chars one by one to avoid this situation.
222: *
223: * GDI draws all glyphs starting from 0. First 32 glyphs are taken from
224: * another font, hence we have to check if the glyph exists in chosen
225: * font and if success draw it, otherwise we draw default glyph,
226: * except esc-subsequence chars.
227: * */
228: char[] chars = new char[str.length()];
229: int j = 0;
230: for (int i = 0; i < str.length(); i++) {
231: char c = str.charAt(i);
232: Glyph gl = wf.getGlyph(c);
233:
234: // We compare Advances because Width
235: // of a char can be 0 (e.g. "Space" char)
236: if (gl.getGlyphMetrics().getAdvance() != 0) {
237: chars[j] = gl.getChar();
238: j++;
239: }
240: }
241: String out = new String(chars, 0, j);
242:
243: win32.TextOutW(hdc, x, y - wf.getAscent(), out, j);
244:
245: }
246:
247: /**
248: * Method to draw string with graphics that has composite font
249: * at desired coordinates.
250: *
251: * @param g Graphics to draw onto
252: * @param str String to draw
253: * @param x starting X coordinate to draw at
254: * @param y starting Y coordinate to draw at
255: */
256: @SuppressWarnings("deprecation")
257: public void drawCompositeString(Graphics2D g, String str, int x,
258: int y) {
259:
260: int len = str.length();
261:
262: if (len == 0) {
263: return;
264: }
265:
266: AffineTransform trans = ((WinGDIGraphics2D) g).getTransform();
267:
268: long gi = ((WinGDIGraphics2D) g).getGraphicsInfo();
269: long hdc = ((WinGDIGraphics2D) g).getDC();
270:
271: x += (int) Math.round(trans.getTranslateX());
272: y += (int) Math.round(trans.getTranslateY());
273:
274: win32.SetTextColor(hdc, getGDIColor(g.getColor().getRGB()));
275: win32.SetBkMode(hdc, WindowsDefs.TRANSPARENT);
276:
277: CompositeFont wcf = (CompositeFont) (g.getFont().getPeer());
278: int charFontIndex = wcf.getCharFontIndex(str.charAt(0), 0);
279: int fontIndex = charFontIndex;
280:
281: WindowsFont physFont = (WindowsFont) wcf.fPhysicalFonts[charFontIndex];
282: long font = physFont.getFontHandle();
283:
284: win32.SelectObject(hdc, font);
285:
286: int ascent = physFont.getAscent(); // Font ascent
287: int offs = 0; // width of substring with the same font header
288: int yOffset = y - ascent; // Y offset to draw (y - font.ascent)
289: int xOffset = x; // X offset to draw
290: int start = 0;
291: int count = 0;
292:
293: for (int i = 0; i < len; i++) {
294: char c = str.charAt(i);
295: Glyph gl = wcf.getGlyph(c);
296:
297: int glWidth = Math.round(gl.getGlyphPointMetrics()
298: .getAdvance());
299: if (glWidth == 0) {
300: continue;
301: }
302:
303: fontIndex = wcf.getCharFontIndex(c, 0);
304:
305: if (fontIndex != charFontIndex) {
306: charFontIndex = fontIndex;
307: win32.TextOutW(hdc, xOffset, yOffset, str.substring(
308: start, start + count), count);
309:
310: xOffset += offs;
311: offs = 0;
312: count = 1;
313: start = i;
314:
315: physFont = (WindowsFont) wcf.fPhysicalFonts[charFontIndex];
316: font = physFont.getFontHandle();
317: win32.SelectObject(hdc, font);
318: yOffset = y - physFont.getAscent();
319: } else {
320: count++;
321: }
322:
323: offs += glWidth;
324: }
325:
326: win32.TextOutW(hdc, xOffset, yOffset, str.substring(start,
327: start + count), count);
328: }
329:
330: }
|