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.Font;
023: import java.awt.Graphics2D;
024: import java.awt.font.GlyphVector;
025: import java.awt.geom.AffineTransform;
026: import java.awt.geom.Point2D;
027:
028: import org.apache.harmony.awt.gl.TextRenderer;
029: import org.apache.harmony.awt.gl.font.CommonGlyphVector;
030: import org.apache.harmony.awt.gl.font.CompositeFont;
031: import org.apache.harmony.awt.gl.font.FontPeerImpl;
032: import org.apache.harmony.awt.gl.font.Glyph;
033: import org.apache.harmony.awt.gl.font.NativeFont;
034: import org.apache.harmony.awt.gl.font.WindowsFont;
035: import org.apache.harmony.awt.internal.nls.Messages;
036:
037: /**
038: * @author Ilya S. Okomin
039: * @version $Revision$
040: *
041: * TextRenderer that works by means of GDI+ calls.
042: */
043:
044: public class GDIPTextRenderer extends TextRenderer {
045:
046: // GDI Pen object handle
047: long curPen;
048:
049: // curPen's color
050: int curPenColor;
051:
052: // Print debug output or not
053: protected static final boolean debugOutput = "1".equals(System.getProperty("g2d.debug")); //$NON-NLS-1$ //$NON-NLS-2$
054:
055: public static final GDIPTextRenderer inst = new GDIPTextRenderer();
056:
057: private GDIPTextRenderer() {
058: }
059:
060: @SuppressWarnings("deprecation")
061: @Override
062: public void drawGlyphVector(Graphics2D g, GlyphVector gv, float x,
063: float y) {
064: FontPeerImpl fnt = (FontPeerImpl) gv.getFont().getPeer();
065: if (fnt.getClass() == CompositeFont.class) {
066: gdipDrawCompositeGlyphVector(g, gv, x, y);
067: } else {
068: gdipDrawNormalGlyphVector(g, gv, x, y);
069: }
070: }
071:
072: /**
073: * Method to draw GlyphVector created from physical font onto a
074: * specified graphics at desired coordinates.
075: *
076: * @param g Graphics to draw onto
077: * @param gv GlyphVector to draw
078: * @param x starting X coordinate to draw at
079: * @param y starting Y coordinate to draw at
080: */
081: @SuppressWarnings("deprecation")
082: public void gdipDrawNormalGlyphVector(Graphics2D g, GlyphVector gv,
083: float x, float y) {
084: int len = gv.getNumGlyphs();
085: int status = 0;
086: long graphicsInfo = ((WinGDIPGraphics2D) g).getGraphicsInfo();
087: int flags = gv.getLayoutFlags();
088:
089: if ((flags & (GlyphVector.FLAG_HAS_POSITION_ADJUSTMENTS | GlyphVector.FLAG_HAS_TRANSFORMS)) == 0) {
090: gdipDrawNormalChars(g, gv.getFont(),
091: ((CommonGlyphVector) gv).charVector, len, x, y);
092: return;
093: }
094:
095: WindowsFont wf = (WindowsFont) gv.getFont().getPeer();
096: long font = wf.getFontHandle();
097: AffineTransform fontAT = gv.getFont().getTransform();
098:
099: double matrix[] = new double[6];
100: double fontMatrix[] = new double[6];
101: char chars[] = new char[len];
102: double positions[] = new double[len * 2];
103: int count = 0;
104:
105: AffineTransform at = new AffineTransform(fontAT);
106: at.getMatrix(fontMatrix);
107: at.preConcatenate(AffineTransform.getTranslateInstance(x, y));
108:
109: if (((gv.getLayoutFlags() & GlyphVector.FLAG_HAS_TRANSFORMS) != 0)) {
110:
111: for (int i = 0; i < gv.getNumGlyphs(); i++) {
112:
113: Glyph gl = ((CommonGlyphVector) gv).vector[i];
114:
115: if (gl.getPointWidth() == 0) {
116: continue;
117: }
118:
119: char chr = gl.getChar();
120:
121: AffineTransform glyphAT = gv.getGlyphTransform(i);
122: if ((glyphAT == null) || glyphAT.isIdentity()) {
123: chars[count] = chr;
124: int index = i * 2;
125: int ind = count * 2;
126: positions[ind] = ((CommonGlyphVector) gv).visualPositions[index];
127: positions[ind + 1] = ((CommonGlyphVector) gv).visualPositions[index + 1];
128: count++;
129: continue;
130: }
131:
132: if (glyphAT.getType() == AffineTransform.TYPE_TRANSLATION) {
133: chars[count] = chr;
134: int index = i * 2;
135: int ind = count * 2;
136: positions[ind] = ((CommonGlyphVector) gv).visualPositions[index]
137: + glyphAT.getTranslateX();
138: positions[ind + 1] = ((CommonGlyphVector) gv).visualPositions[index + 1]
139: + glyphAT.getTranslateY();
140: count++;
141: continue;
142: }
143:
144: at.transform(positions, 0, positions, 0, count);
145:
146: status = NativeFont.gdiPlusDrawDriverChars(
147: graphicsInfo, chars, count, font, positions,
148: NativeFont.DriverStringOptionsCmapLookup,
149: fontMatrix);
150: if (status != 0 && debugOutput) {
151: // awt.err.02=GDIPlus DrawDriverString error status = {0}
152: System.err.println(Messages.getString(
153: "awt.err.02", status)); //$NON-NLS-1$
154: }
155:
156: count = 0;
157:
158: AffineTransform at1 = new AffineTransform(glyphAT);
159:
160: at1.concatenate(fontAT);
161: at1.getMatrix(matrix);
162:
163: Point2D pos = gv.getGlyphPosition(i);
164:
165: status = NativeFont.gdiPlusDrawDriverChar(graphicsInfo,
166: chr, font, (float) (x + pos.getX()),
167: (float) (y + pos.getY()),
168: NativeFont.DriverStringOptionsCmapLookup,
169: matrix);
170: if (status != 0 && debugOutput) {
171: // awt.err.02=GDIPlus DrawDriverString error status = {0}
172: System.err.println(Messages.getString(
173: "awt.err.02", status)); //$NON-NLS-1$
174: }
175:
176: }
177: if (count != 0) {
178:
179: at.transform(positions, 0, positions, 0, count);
180:
181: status = NativeFont.gdiPlusDrawDriverChars(
182: graphicsInfo, chars, count, font, positions,
183: NativeFont.DriverStringOptionsCmapLookup,
184: fontMatrix);
185: if (status != 0 && debugOutput) {
186: // awt.err.02=GDIPlus DrawDriverString error status = {0}
187: System.err.println(Messages.getString(
188: "awt.err.02", status)); //$NON-NLS-1$
189: }
190:
191: }
192: } else {
193: for (int i = 0; i < len; i++) {
194: Glyph gl = ((CommonGlyphVector) gv).vector[i];
195:
196: if (gl.getPointWidth() == 0) {
197: continue;
198: }
199:
200: chars[count] = gl.getChar();
201: int index = i * 2;
202: int ind = count * 2;
203: positions[ind] = ((CommonGlyphVector) gv).visualPositions[index];
204: positions[ind + 1] = ((CommonGlyphVector) gv).visualPositions[index + 1];
205: count++;
206: }
207:
208: at.transform(positions, 0, positions, 0, count);
209:
210: status = NativeFont.gdiPlusDrawDriverChars(graphicsInfo,
211: chars, count, font, positions,
212: NativeFont.DriverStringOptionsCmapLookup,
213: fontMatrix);
214: }
215:
216: if (status != 0 && debugOutput) {
217: // awt.err.02=GDIPlus DrawDriverString error status = {0}
218: System.err
219: .println(Messages.getString("awt.err.02", status)); //$NON-NLS-1$
220: }
221: }
222:
223: /**
224: * Method to draw GlyphVector created from composite font onto a
225: * specified graphics at desired coordinates.
226: *
227: * @param g Graphics to draw onto
228: * @param gv GlyphVector to draw
229: * @param x starting X coordinate to draw at
230: * @param y starting Y coordinate to draw at
231: */
232: @SuppressWarnings("deprecation")
233: public void gdipDrawCompositeGlyphVector(Graphics2D g,
234: GlyphVector gv, float x, float y) {
235: int status = 0;
236:
237: long graphicsInfo = ((WinGDIPGraphics2D) g).getGraphicsInfo();
238: Font fnt = gv.getFont();
239: int len = gv.getNumGlyphs();
240: CompositeFont wcf = (CompositeFont) (fnt.getPeer());
241: int charFontIndex = wcf.getCharFontIndex(
242: ((CommonGlyphVector) gv).charVector[0], 0);
243: int fontIndex = charFontIndex;
244:
245: int size = len;
246: double positions[] = new double[size * 2];
247: char chars[] = new char[size];
248: int count = 0;
249: WindowsFont physFont = (WindowsFont) wcf.fPhysicalFonts[charFontIndex];
250:
251: long font = physFont.getFontHandle();
252:
253: AffineTransform fontAT = fnt.getTransform();
254:
255: double matrix[] = new double[6];
256: double fontMatrix[] = new double[6];
257:
258: AffineTransform at = new AffineTransform(fontAT);
259: at.getMatrix(fontMatrix);
260: at.preConcatenate(AffineTransform.getTranslateInstance(x, y));
261:
262: for (int i = 0; i < len; i++) {
263: Glyph gl = ((CommonGlyphVector) gv).vector[i];
264:
265: if (gl.getPointWidth() == 0) {
266: continue;
267: }
268:
269: char c = gl.getChar();
270: AffineTransform glyphAT = gv.getGlyphTransform(i);
271: Point2D pos = gv.getGlyphPosition(i);
272:
273: fontIndex = wcf.getCharFontIndex(c, 0);
274:
275: if ((glyphAT == null)
276: || glyphAT.isIdentity()
277: || glyphAT.getType() == AffineTransform.TYPE_TRANSLATION) {
278: if (fontIndex != charFontIndex) {
279: charFontIndex = fontIndex;
280:
281: at.transform(positions, 0, positions, 0, count);
282:
283: status = NativeFont.gdiPlusDrawDriverChars(
284: graphicsInfo, chars, count, font,
285: positions,
286: NativeFont.DriverStringOptionsCmapLookup,
287: fontMatrix);
288: if (status != 0 && debugOutput) {
289: // awt.err.03=gdipDrawCompositeGlyphVector: GDIPlus DrawDriverString error status = {0}
290: System.err.println(Messages.getString(
291: "awt.err.03", status)); //$NON-NLS-1$
292: }
293:
294: count = 0;
295: font = gl.getPFont();
296: physFont = (WindowsFont) wcf.fPhysicalFonts[charFontIndex];
297: } else {
298: chars[count] = c;
299: int ind = count * 2;
300: positions[ind] = pos.getX();
301: positions[ind + 1] = pos.getY();
302: count++;
303: }
304: continue;
305: }
306:
307: charFontIndex = fontIndex;
308: if (count > 0) {
309:
310: at.transform(positions, 0, positions, 0, count);
311:
312: status = NativeFont.gdiPlusDrawDriverChars(
313: graphicsInfo, chars, count, font, positions,
314: NativeFont.DriverStringOptionsCmapLookup,
315: fontMatrix);
316: if (status != 0 && debugOutput) {
317: // awt.err.04=gdipDrawCompositeGlyphVector: GDIPlus DrawDriverString error status = {0}
318: System.err.println(Messages.getString(
319: "awt.err.04", status)); //$NON-NLS-1$
320: }
321: count = 0;
322: }
323:
324: font = gl.getPFont();
325:
326: AffineTransform at1 = new AffineTransform(glyphAT);
327: at1.concatenate(fontAT);
328: at1.getMatrix(matrix);
329:
330: status = NativeFont.gdiPlusDrawDriverChar(graphicsInfo, c,
331: font, (float) (x + pos.getX()), (float) (y + pos
332: .getY()),
333: NativeFont.DriverStringOptionsCmapLookup, matrix);
334:
335: if (status != 0 && debugOutput) {
336: // awt.err.04=gdipDrawCompositeGlyphVector: GDIPlus DrawDriverString error status = {0}
337: System.err.println(Messages.getString(
338: "awt.err.04", status)); //$NON-NLS-1$
339: }
340:
341: }
342: if (count > 0) {
343:
344: at.transform(positions, 0, positions, 0, count);
345:
346: status = NativeFont.gdiPlusDrawDriverChars(graphicsInfo,
347: chars, count, font, positions,
348: NativeFont.DriverStringOptionsCmapLookup,
349: fontMatrix);
350: }
351:
352: }
353:
354: @SuppressWarnings("deprecation")
355: @Override
356: public void drawString(Graphics2D g, String str, float x, float y) {
357: int len = str.length();
358: if (len == 0) {
359: return;
360: }
361:
362: FontPeerImpl fnt = (FontPeerImpl) g.getFont().getPeer();
363: if (fnt.getClass() == CompositeFont.class) {
364: gdipDrawCompositeString(g, str, x, y);
365: } else {
366: gdipDrawNormalChars(g, g.getFont(), str.toCharArray(), len,
367: x, y);
368: }
369: }
370:
371: /**
372: * Method to draw string with graphics that has physical font
373: * at desired coordinates.
374: *
375: * @param g Graphics to draw onto
376: * @param str String to draw
377: * @param x starting X coordinate to draw at
378: * @param y starting Y coordinate to draw at
379: */
380: @SuppressWarnings("deprecation")
381: public void gdipDrawNormalString(Graphics2D g, String str, float x,
382: float y) {
383: long graphicsInfo = ((WinGDIPGraphics2D) g).getGraphicsInfo();
384:
385: WindowsFont wf = (WindowsFont) (g.getFont().getPeer());
386: long font = wf.getFontHandle();
387: int len = str.length();
388:
389: char[] chars = new char[len];
390: double positions[] = new double[len * 2];
391: double matrix[] = new double[6];
392: AffineTransform at = new AffineTransform(g.getFont()
393: .getTransform());
394: at.getMatrix(matrix);
395:
396: float xPos = 0;
397: float yPos = 0;
398:
399: int count = 0;
400: for (int i = 0; i < len; i++) {
401: char c = str.charAt(i);
402: Glyph gl = wf.getGlyph(c);
403:
404: // We compare Advances because Width
405: // of a char can be 0 (e.g. "Space" char)
406: float advance = gl.getGlyphPointMetrics().getAdvance();
407: if (advance != 0) {
408: chars[count] = gl.getChar();
409: positions[count * 2] = xPos;
410: positions[count * 2 + 1] = yPos;
411: xPos += advance;
412: count++;
413: }
414: }
415:
416: at.preConcatenate(AffineTransform.getTranslateInstance(x, y));
417: at.transform(positions, 0, positions, 0, count);
418:
419: int status = NativeFont.gdiPlusDrawDriverChars(graphicsInfo,
420: chars, count, font, positions,
421: NativeFont.DriverStringOptionsCmapLookup, matrix);
422:
423: if (status != 0 && debugOutput) {
424: // awt.err.02=GDIPlus DrawDriverString error status = {0}
425: System.err
426: .println(Messages.getString("awt.err.02", status)); //$NON-NLS-1$
427: }
428: }
429:
430: /**
431: * Method for fast drawing strings at the desired coordinates with Graphics
432: * or Font object has transforms.
433: *
434: * @param g Graphics to draw onto
435: * @param fnt Font class that is used to draw string
436: * @param str String to draw
437: * @param len length of the String parameter
438: * @param x starting X coordinate to draw at
439: * @param y starting Y coordinate to draw at
440: */
441: @SuppressWarnings("deprecation")
442: public void gdipDrawNormalChars(Graphics2D g, Font fnt, char str[],
443: int len, float x, float y) {
444: long graphicsInfo = ((WinGDIPGraphics2D) g).getGraphicsInfo();
445:
446: WindowsFont wf = (WindowsFont) (fnt.getPeer());
447: long font = wf.getFontHandle();
448:
449: char[] chars = new char[len];
450: double positions[] = new double[len * 2];
451: double matrix[] = new double[6];
452:
453: AffineTransform at = new AffineTransform(fnt.getTransform());
454: at.getMatrix(matrix);
455: at.preConcatenate(AffineTransform.getTranslateInstance(x, y));
456:
457: float xPos = 0;
458: float yPos = 0;
459:
460: int count = 0;
461: for (int i = 0; i < len; i++) {
462: char c = str[i];
463: Glyph gl = wf.getGlyph(c);
464:
465: // We compare advances because width
466: // of a char can be 0 (e.g. "Space" char)
467: float advance = gl.getGlyphPointMetrics().getAdvance();
468: if (advance != 0) {
469: chars[count] = gl.getChar();
470:
471: positions[count * 2] = xPos;
472: positions[count * 2 + 1] = yPos;
473:
474: xPos += advance;
475: count++;
476: }
477: }
478: at.transform(positions, 0, positions, 0, count);
479:
480: int status = NativeFont.gdiPlusDrawDriverChars(graphicsInfo,
481: chars, count, font, positions,
482: NativeFont.DriverStringOptionsCmapLookup, matrix);
483:
484: if (status != 0 && debugOutput) {
485: // awt.err.02=GDIPlus DrawDriverString error status = {0}
486: System.err
487: .println(Messages.getString("awt.err.02", status)); //$NON-NLS-1$
488: }
489:
490: }
491:
492: /**
493: * Method to draw string with graphics that has composite font
494: * at desired coordinates.
495: *
496: * @param g Graphics to draw onto
497: * @param str String to draw
498: * @param x starting X coordinate to draw at
499: * @param y starting Y coordinate to draw at
500: */
501: @SuppressWarnings("deprecation")
502: public void gdipDrawCompositeString(Graphics2D g, String str,
503: float x, float y) {
504: int len = str.length();
505:
506: long graphicsInfo = ((WinGDIPGraphics2D) g).getGraphicsInfo();
507:
508: double matrix[] = new double[6];
509: AffineTransform at = new AffineTransform(g.getFont()
510: .getTransform());
511: at.getMatrix(matrix);
512: at.preConcatenate(AffineTransform.getTranslateInstance(x, y));
513:
514: int size = len;
515: double positions[] = new double[size * 2];
516: char chars[] = new char[size];
517:
518: CompositeFont wcf = (CompositeFont) (g.getFont().getPeer());
519: int charFontIndex = wcf.getCharFontIndex(str.charAt(0), 0);
520: int fontIndex = charFontIndex;
521:
522: WindowsFont physFont = (WindowsFont) wcf.fPhysicalFonts[charFontIndex];
523:
524: long font = physFont.getFontHandle();
525: float yPos = 0; // Y position to draw (y - font.ascent)
526: float xPos = 0; // X position to draw
527: int count = 0;
528:
529: for (int i = 0; i < len; i++) {
530: Glyph gl = wcf.getGlyph(str.charAt(i));
531:
532: int advance = (int) (gl.getGlyphPointMetrics().getAdvance());
533: if (advance == 0) {
534: continue;
535: }
536: char c = gl.getChar();
537:
538: fontIndex = wcf.getCharFontIndex(c, 0);
539:
540: if (fontIndex != charFontIndex) {
541: charFontIndex = fontIndex;
542:
543: at.transform(positions, 0, positions, 0, count);
544:
545: int status = NativeFont.gdiPlusDrawDriverChars(
546: graphicsInfo, chars, count, font, positions,
547: NativeFont.DriverStringOptionsCmapLookup,
548: matrix);
549: if (status != 0 && debugOutput) {
550: // awt.err.02=GDIPlus DrawDriverString error status = {0}
551: System.err.println(Messages.getString(
552: "awt.err.02", status)); //$NON-NLS-1$
553: }
554:
555: count = 0;
556: font = gl.getPFont();
557: }
558: chars[count] = c;
559: positions[count * 2] = xPos;
560: positions[count * 2 + 1] = yPos;
561:
562: count++;
563: xPos += advance;
564: }
565:
566: at.transform(positions, 0, positions, 0, count);
567:
568: int status = NativeFont.gdiPlusDrawDriverChars(graphicsInfo,
569: chars, count, font, positions,
570: NativeFont.DriverStringOptionsCmapLookup, matrix);
571: if (status != 0 && debugOutput) {
572: // awt.err.02=GDIPlus DrawDriverString error status = {0}
573: System.err
574: .println(Messages.getString("awt.err.02", status)); //$NON-NLS-1$
575: }
576:
577: }
578:
579: }
|