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.render;
021:
022: import java.awt.*;
023: import java.awt.image.*;
024:
025: import java.awt.font.GlyphMetrics;
026: import java.awt.font.GlyphVector;
027: import java.awt.geom.AffineTransform;
028: import java.awt.geom.Point2D;
029:
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.FontPeerImpl;
033: import org.apache.harmony.awt.gl.font.Glyph;
034: import org.apache.harmony.awt.gl.image.BufferedImageGraphics2D;
035:
036: public class JavaTextRenderer extends TextRenderer {
037:
038: public static final JavaTextRenderer inst = new JavaTextRenderer();
039:
040: @Override
041: public void drawGlyphVector(Graphics2D g, GlyphVector glyphVector,
042: float x, float y) {
043:
044: AffineTransform at = g.getTransform();
045: Rectangle c = g.getClipBounds();
046: if (at != null) {
047: int atType = at.getType();
048: if (atType == AffineTransform.TYPE_TRANSLATION) {
049: c.translate((int) Math.round(at.getTranslateX()),
050: (int) Math.round(at.getTranslateY()));
051: }
052: }
053:
054: WritableRaster wr = ((BufferedImageGraphics2D) g)
055: .getWritableRaster();
056: ColorModel cm = ((BufferedImageGraphics2D) g).getColorModel();
057:
058: Rectangle rBounds = wr.getBounds();
059:
060: Object color = cm.getDataElements(g.getColor().getRGB(), null);
061:
062: drawClipGlyphVector(wr, color, glyphVector, (int) Math.round(x
063: + at.getTranslateX()), (int) Math.round(y
064: + at.getTranslateY()), Math.max(c.x, rBounds.x), Math
065: .max(c.y, rBounds.y), Math.min((int) Math.round(c
066: .getMaxX()), (int) Math.round(rBounds.getMaxX())), Math
067: .min((int) Math.round(c.getMaxY()), (int) Math
068: .round(rBounds.getMaxY())));
069:
070: }
071:
072: @SuppressWarnings("deprecation")
073: @Override
074: public void drawString(Graphics2D g, String str, float x, float y) {
075: AffineTransform at = g.getTransform();
076: Rectangle c = g.getClipBounds();
077: if (at != null) {
078: int atType = at.getType();
079: if (atType == AffineTransform.TYPE_TRANSLATION) {
080: c.translate((int) Math.round(at.getTranslateX()),
081: (int) Math.round(at.getTranslateY()));
082: }
083: }
084: WritableRaster wr = ((BufferedImageGraphics2D) g)
085: .getWritableRaster();
086: ColorModel cm = ((BufferedImageGraphics2D) g).getColorModel();
087: Rectangle rBounds = wr.getBounds();
088:
089: Object color = cm.getDataElements(g.getColor().getRGB(), null);
090:
091: drawClipString(wr, color, str, (FontPeerImpl) (g.getFont()
092: .getPeer()), (int) Math.round(x + at.getTranslateX()),
093: (int) Math.round(y + at.getTranslateY()), Math.max(c.x,
094: rBounds.x), Math.max(c.y, rBounds.y), Math.min(
095: (int) Math.round(c.getMaxX()), (int) Math
096: .round(rBounds.getMaxX())), Math.min(
097: (int) Math.round(c.getMaxY()), (int) Math
098: .round(rBounds.getMaxY())));
099:
100: }
101:
102: /**
103: *
104: * Draws string on specified raster at desired position.
105: *
106: * @param raster specified WritableRaster to draw at
107: * @param color color of the text
108: * @param glyphVector GlyphVector object to draw
109: * @param x start X position to draw
110: * @param y start Y position to draw
111: * @param cMinX minimum x of the raster area to draw
112: * @param cMinY minimum y of the raster area to draw
113: * @param cMaxX maximum x of the raster area to draw
114: * @param cMaxY maximum y of the raster area to draw
115: */
116: public void drawClipGlyphVector(WritableRaster raster,
117: Object color, GlyphVector glyphVector, int x, int y,
118: int cMinX, int cMinY, int cMaxX, int cMaxY) {
119: // TODO: implement complex clipping
120:
121: int xSrcSurf, ySrcSurf; // Start point in String rectangle
122: int xDstSurf, yDstSurf; // Start point in Surface rectangle
123: int clWidth, clHeight;
124:
125: for (int i = 0; i < glyphVector.getNumGlyphs(); i++) {
126: Glyph gl = ((CommonGlyphVector) glyphVector).vector[i];
127:
128: if (gl.getPointWidth() == 0) {
129: continue;
130: }
131:
132: byte[] data = gl.getBitmap();
133: if (data != null) {
134: Point2D pos = glyphVector.getGlyphPosition(i);
135:
136: xSrcSurf = 0;//gl.bmp_left;
137: ySrcSurf = 0;//gl.bmp_rows - gl.bmp_top;
138:
139: xDstSurf = x + (int) pos.getX()
140: + (int) gl.getGlyphPointMetrics().getLSB();// + gl.bmp_left;
141: yDstSurf = y - gl.bmp_top/*getPointHeight()*/
142: + (int) pos.getY();// - (gl.bmp_rows-gl.bmp_top);
143:
144: int textWidth = gl.bmp_width;
145: int textHeight = gl.getPointHeight();
146:
147: // if Regions don't intersect
148: if ((xDstSurf > cMaxX) || (yDstSurf > cMaxY)
149: || (xDstSurf + textWidth < cMinX)
150: || (yDstSurf + textHeight < cMinY)) {
151: // Nothing to do
152: } else {
153: if (xDstSurf >= cMinX) {
154: clWidth = Math.min(textWidth, cMaxX - xDstSurf);
155: } else {
156: xSrcSurf += cMinX - xDstSurf;
157: clWidth = Math.min(cMaxX - cMinX, textWidth
158: - (cMinX - xDstSurf));
159: xDstSurf = cMinX;
160: }
161: if (yDstSurf >= cMinY) {
162: clHeight = Math.min(textHeight, cMaxY
163: - yDstSurf);
164: } else {
165: ySrcSurf += cMinY - yDstSurf;
166: clHeight = Math.min(cMaxY - cMinY, textHeight
167: - (cMinY - yDstSurf));
168: yDstSurf = cMinY;
169: }
170: // Drawing on the Raster
171: for (int h = 0; h < clHeight; h++) {
172: for (int w = 0; w < clWidth; w++) {
173: byte currByte = data[(ySrcSurf + h)
174: * gl.bmp_pitch + (xSrcSurf + w) / 8];
175: boolean emptyByte = ((currByte & (1 << (7 - ((xSrcSurf + w) % 8)))) != 0);
176: if (emptyByte) {
177: raster.setDataElements(xDstSurf + w,
178: yDstSurf + h, color);
179: } else {
180: // Nothing to do
181: }
182: }
183: }
184: }
185: }
186: }
187: }
188:
189: /**
190: * Draws string on specified raster at desired position.
191: *
192: * @param raster specified WritableRaster to draw at
193: * @param color color of the text
194: * @param str text to draw
195: * @param font font peer to use for drawing text
196: * @param x start X position to draw
197: * @param y start Y position to draw
198: * @param cMinX minimum x of the raster area to draw
199: * @param cMinY minimum y of the raster area to draw
200: * @param cMaxX maximum x of the raster area to draw
201: * @param cMaxY maximum y of the raster area to draw
202: */
203: public void drawClipString(WritableRaster raster, Object color,
204: String str, FontPeerImpl font, int x, int y, int cMinX,
205: int cMinY, int cMaxX, int cMaxY) {
206: // TODO: implement complex clipping
207:
208: int xSrcSurf, ySrcSurf; // Start point in String rectangle
209: int xDstSurf, yDstSurf; // Start point in Surface rectangle
210: int clWidth, clHeight;
211:
212: char[] chars = str.toCharArray();
213:
214: int xBaseLine = x;
215: int yBaseLine = y;
216:
217: for (char element : chars) {
218: Glyph gl = font.getGlyph(element);
219: GlyphMetrics pointMetrics = gl.getGlyphPointMetrics();
220: if (gl.getWidth() == 0) {
221: xBaseLine += pointMetrics.getAdvanceX();
222: continue;
223: }
224:
225: byte[] data = gl.getBitmap();
226: if (data == null) {
227: xBaseLine += pointMetrics.getAdvanceX();
228: } else {
229:
230: xSrcSurf = 0;
231: ySrcSurf = 0;
232:
233: xDstSurf = Math.round(xBaseLine
234: + gl.getGlyphPointMetrics().getLSB());
235: yDstSurf = yBaseLine - gl.bmp_top;
236:
237: int textWidth = gl.bmp_width;
238: int textHeight = gl.getPointHeight();
239:
240: // if Regions don't intersect
241: if ((xDstSurf > cMaxX) || (yDstSurf > cMaxY)
242: || (xDstSurf + textWidth < cMinX)
243: || (yDstSurf + textHeight < cMinY)) {
244: // Nothing to do
245: } else {
246: if (xDstSurf >= cMinX) {
247: clWidth = Math.min(textWidth, cMaxX - xDstSurf);
248: } else {
249: xSrcSurf += cMinX - xDstSurf;
250: clWidth = Math.min(cMaxX - cMinX, textWidth
251: - (cMinX - xDstSurf));
252: xDstSurf = cMinX;
253: }
254: if (yDstSurf >= cMinY) {
255: clHeight = Math.min(textHeight, cMaxY
256: - yDstSurf);
257: } else {
258: ySrcSurf += cMinY - yDstSurf;
259: clHeight = Math.min(cMaxY - cMinY, textHeight
260: - (cMinY - yDstSurf));
261: yDstSurf = cMinY;
262: }
263:
264: // Drawing on the Raster
265: for (int h = 0; h < clHeight; h++) {
266: for (int w = 0; w < clWidth; w++) {
267: byte currByte = data[(ySrcSurf + h)
268: * gl.bmp_pitch + (xSrcSurf + w) / 8];
269: boolean emptyByte = ((currByte & (1 << (7 - ((xSrcSurf + w) % 8)))) != 0);
270: if (emptyByte) {
271: raster.setDataElements(xDstSurf + w,
272: yDstSurf + h, color);
273: } else {
274: // Nothing to do
275: }
276: }
277: }
278: }
279: xBaseLine += pointMetrics.getAdvanceX();
280: }
281: }
282: }
283:
284: }
|