1/* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17/** 18 * @author Ilya S. Okomin 19 * @version $Revision$ 20 */ 21package org.apache.harmony.awt.gl.render; 22 23import java.awt.*; 24import java.awt.image.*; 25 26 27import java.awt.font.GlyphMetrics; 28import java.awt.font.GlyphVector; 29import java.awt.geom.AffineTransform; 30import java.awt.geom.Point2D; 31 32import org.apache.harmony.awt.gl.TextRenderer; 33import org.apache.harmony.awt.gl.font.CommonGlyphVector; 34import org.apache.harmony.awt.gl.font.FontPeerImpl; 35import org.apache.harmony.awt.gl.font.Glyph; 36import org.apache.harmony.awt.gl.image.BufferedImageGraphics2D; 37 38public class JavaTextRenderer extends TextRenderer { 39 40 public static final JavaTextRenderer inst = new JavaTextRenderer(); 41 42 @Override 43 public void drawGlyphVector(Graphics2D g, GlyphVector glyphVector, 44 float x, float y) { 45 46 AffineTransform at = g.getTransform(); 47 Rectangle c = g.getClipBounds(); 48 if (at != null){ 49 int atType = at.getType(); 50 if (atType == AffineTransform.TYPE_TRANSLATION) { 51 c.translate((int)Math.round(at.getTranslateX()), (int)Math.round(at.getTranslateY())); 52 } 53 } 54 55 WritableRaster wr = ((BufferedImageGraphics2D)g).getWritableRaster(); 56 ColorModel cm = ((BufferedImageGraphics2D)g).getColorModel(); 57 58 Rectangle rBounds = wr.getBounds(); 59 60 Object color = cm.getDataElements(g.getColor().getRGB(), null); 61 62 drawClipGlyphVector(wr, color, glyphVector, (int)Math.round(x + at.getTranslateX()), (int)Math.round(y + at.getTranslateY()), 63 Math.max(c.x,rBounds.x), 64 Math.max(c.y,rBounds.y), 65 Math.min((int)Math.round(c.getMaxX()), (int)Math.round(rBounds.getMaxX())), 66 Math.min((int)Math.round(c.getMaxY()), (int)Math.round(rBounds.getMaxY()))); 67 68 } 69 70 @SuppressWarnings("deprecation") 71 @Override 72 public void drawString(Graphics2D g, String str, float x, float y) { 73 AffineTransform at = g.getTransform(); 74 Rectangle c = g.getClipBounds(); 75 if (at != null){ 76 int atType = at.getType(); 77 if (atType == AffineTransform.TYPE_TRANSLATION) { 78 c.translate((int)Math.round(at.getTranslateX()), (int)Math.round(at.getTranslateY())); 79 } 80 } 81 WritableRaster wr = ((BufferedImageGraphics2D)g).getWritableRaster(); 82 ColorModel cm = ((BufferedImageGraphics2D)g).getColorModel(); 83 Rectangle rBounds = wr.getBounds(); 84 85 Object color = cm.getDataElements(g.getColor().getRGB(), null); 86 87 drawClipString(wr, color, str, (FontPeerImpl) (g.getFont().getPeer()), 88 (int)Math.round(x + at.getTranslateX()), (int)Math.round(y + at.getTranslateY()), 89 Math.max(c.x,rBounds.x), 90 Math.max(c.y,rBounds.y), 91 Math.min((int)Math.round(c.getMaxX()), (int)Math.round(rBounds.getMaxX())), 92 Math.min((int)Math.round(c.getMaxY()), (int)Math.round(rBounds.getMaxY()))); 93 94 } 95 96 /** 97 * 98 * Draws string on specified raster at desired position. 99 * 100 * @param raster specified WritableRaster to draw at 101 * @param color color of the text 102 * @param glyphVector GlyphVector object to draw 103 * @param x start X position to draw 104 * @param y start Y position to draw 105 * @param cMinX minimum x of the raster area to draw 106 * @param cMinY minimum y of the raster area to draw 107 * @param cMaxX maximum x of the raster area to draw 108 * @param cMaxY maximum y of the raster area to draw 109 */ 110 public void drawClipGlyphVector(WritableRaster raster, Object color, 111 GlyphVector glyphVector, int x, int y, 112 int cMinX, int cMinY, int cMaxX, int cMaxY) { 113 // TODO: implement complex clipping 114 115 int xSrcSurf, ySrcSurf; // Start point in String rectangle 116 int xDstSurf, yDstSurf; // Start point in Surface rectangle 117 int clWidth, clHeight; 118 119 for (int i = 0; i < glyphVector.getNumGlyphs(); i++) { 120 Glyph gl = ((CommonGlyphVector) glyphVector).vector[i]; 121 122 if (gl.getPointWidth() == 0) { 123 continue; 124 } 125 126 byte[] data = gl.getBitmap(); 127 if (data != null) { 128 Point2D pos = glyphVector.getGlyphPosition(i); 129 130 xSrcSurf = 0;//gl.bmp_left; 131 ySrcSurf = 0;//gl.bmp_rows - gl.bmp_top; 132 133 xDstSurf = x + (int)pos.getX() + (int) gl.getGlyphPointMetrics().getLSB();// + gl.bmp_left; 134 yDstSurf = y - gl.bmp_top/*getPointHeight()*/ + (int) pos.getY();// - (gl.bmp_rows-gl.bmp_top); 135 136 int textWidth = gl.bmp_width; 137 int textHeight = gl.getPointHeight(); 138 139 // if Regions don't intersect 140 if ((xDstSurf > cMaxX) || (yDstSurf > cMaxY) || (xDstSurf + textWidth < cMinX) 141 || (yDstSurf + textHeight < cMinY)) { 142 // Nothing to do 143 } else { 144 if (xDstSurf >= cMinX) { 145 clWidth = Math.min(textWidth, cMaxX - xDstSurf); 146 } else { 147 xSrcSurf += cMinX - xDstSurf; 148 clWidth = Math.min(cMaxX - cMinX, textWidth - (cMinX - xDstSurf)); 149 xDstSurf = cMinX; 150 } 151 if (yDstSurf >= cMinY) { 152 clHeight = Math.min(textHeight, cMaxY - yDstSurf); 153 } else { 154 ySrcSurf += cMinY - yDstSurf; 155 clHeight = Math.min(cMaxY - cMinY, textHeight - (cMinY - yDstSurf)); 156 yDstSurf = cMinY; 157 } 158 // Drawing on the Raster 159 for (int h=0; h<clHeight; h++){ 160 for (int w=0; w < clWidth ; w++) { 161 byte currByte = data[(ySrcSurf + h)*gl.bmp_pitch + (xSrcSurf+w)/8]; 162 boolean emptyByte = ((currByte & (1 << (7 - ((xSrcSurf+w) % 8)))) != 0); 163 if (emptyByte) { 164 raster.setDataElements(xDstSurf+w, yDstSurf+h, color); 165 } else { 166 // Nothing to do 167 } 168 } 169 } 170 } 171 } 172 } 173 } 174 175 /** 176 * Draws string on specified raster at desired position. 177 * 178 * @param raster specified WritableRaster to draw at 179 * @param color color of the text 180 * @param str text to draw 181 * @param font font peer to use for drawing text 182 * @param x start X position to draw 183 * @param y start Y position to draw 184 * @param cMinX minimum x of the raster area to draw 185 * @param cMinY minimum y of the raster area to draw 186 * @param cMaxX maximum x of the raster area to draw 187 * @param cMaxY maximum y of the raster area to draw 188 */ 189 public void drawClipString(WritableRaster raster, Object color, String str, 190 FontPeerImpl font, int x, int y, int cMinX, int cMinY, int cMaxX, 191 int cMaxY) { 192 // TODO: implement complex clipping 193 194 int xSrcSurf, ySrcSurf; // Start point in String rectangle 195 int xDstSurf, yDstSurf; // Start point in Surface rectangle 196 int clWidth, clHeight; 197 198 char[] chars = str.toCharArray(); 199 200 int xBaseLine = x; 201 int yBaseLine = y; 202 203 for (char element : chars) { 204 Glyph gl = font.getGlyph(element); 205 GlyphMetrics pointMetrics = gl.getGlyphPointMetrics(); 206 if (gl.getWidth() == 0) { 207 xBaseLine += pointMetrics.getAdvanceX(); 208 continue; 209 } 210 211 byte[] data = gl.getBitmap(); 212 if (data == null) { 213 xBaseLine += pointMetrics.getAdvanceX(); 214 } else { 215 216 xSrcSurf = 0; 217 ySrcSurf = 0; 218 219 xDstSurf = Math.round(xBaseLine + gl.getGlyphPointMetrics().getLSB()); 220 yDstSurf = yBaseLine - gl.bmp_top; 221 222 int textWidth = gl.bmp_width; 223 int textHeight = gl.getPointHeight(); 224 225 // if Regions don't intersect 226 if ((xDstSurf > cMaxX) || (yDstSurf > cMaxY) || (xDstSurf + textWidth < cMinX) 227 || (yDstSurf + textHeight < cMinY)) { 228 // Nothing to do 229 } else { 230 if (xDstSurf >= cMinX) { 231 clWidth = Math.min(textWidth, cMaxX - xDstSurf); 232 } else { 233 xSrcSurf += cMinX - xDstSurf; 234 clWidth = Math.min(cMaxX - cMinX, textWidth - (cMinX - xDstSurf)); 235 xDstSurf = cMinX; 236 } 237 if (yDstSurf >= cMinY) { 238 clHeight = Math.min(textHeight, cMaxY - yDstSurf); 239 } else { 240 ySrcSurf += cMinY - yDstSurf; 241 clHeight = Math.min(cMaxY - cMinY, textHeight - (cMinY - yDstSurf)); 242 yDstSurf = cMinY; 243 } 244 245 // Drawing on the Raster 246 for (int h=0; h<clHeight; h++){ 247 for (int w=0; w < clWidth ; w++) { 248 byte currByte = data[(ySrcSurf + h)*gl.bmp_pitch + (xSrcSurf+w)/8]; 249 boolean emptyByte = ((currByte & (1 << (7 - ((xSrcSurf+w) % 8)))) != 0); 250 if (emptyByte) { 251 raster.setDataElements(xDstSurf+w, yDstSurf+h, color); 252 } else { 253 // Nothing to do 254 } 255 } 256 } 257 } 258 xBaseLine += pointMetrics.getAdvanceX(); 259 } 260 } 261 } 262 263}