1 /* 2 * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Sun designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Sun in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 22 * CA 95054 USA or visit www.sun.com if you need additional information or 23 * have any questions. 24 */ 25 26 package sun.java2d.windows; 27 28 import java.awt.Rectangle; 29 import java.awt.GraphicsConfiguration; 30 import java.awt.color.ColorSpace; 31 import java.awt.image.ColorModel; 32 import java.awt.image.ComponentColorModel; 33 import java.awt.image.DirectColorModel; 34 import java.awt.image.IndexColorModel; 35 import java.awt.image.Raster; 36 37 import sun.awt.SunHints; 38 import sun.awt.Win32GraphicsConfig; 39 import sun.awt.Win32GraphicsDevice; 40 import sun.awt.windows.WComponentPeer; 41 import sun.awt.windows.WFileDialogPeer; 42 import sun.awt.windows.WPrintDialogPeer; 43 import sun.java2d.ScreenUpdateManager; 44 import sun.java2d.SunGraphics2D; 45 import sun.java2d.SurfaceData; 46 import sun.java2d.SurfaceDataProxy; 47 import sun.java2d.pipe.Region; 48 import sun.java2d.pipe.PixelToShapeConverter; 49 import sun.java2d.loops.GraphicsPrimitive; 50 import sun.java2d.loops.SurfaceType; 51 import sun.java2d.loops.CompositeType; 52 import sun.java2d.loops.RenderLoops; 53 import sun.java2d.loops.XORComposite; 54 55 public class GDIWindowSurfaceData extends SurfaceData { 56 private WComponentPeer peer; 57 private Win32GraphicsConfig graphicsConfig; 58 private RenderLoops solidloops; 59 60 // GDI onscreen surface type 61 public static final String 62 DESC_GDI = "GDI"; 63 64 // Generic GDI surface type - used for registering all loops 65 public static final SurfaceType AnyGdi = 66 SurfaceType.IntRgb.deriveSubType(DESC_GDI); 67 68 public static final SurfaceType IntRgbGdi = 69 SurfaceType.IntRgb.deriveSubType(DESC_GDI); 70 71 public static final SurfaceType Ushort565RgbGdi = 72 SurfaceType.Ushort565Rgb.deriveSubType(DESC_GDI); 73 74 public static final SurfaceType Ushort555RgbGdi = 75 SurfaceType.Ushort555Rgb.deriveSubType(DESC_GDI); 76 77 public static final SurfaceType ThreeByteBgrGdi = 78 SurfaceType.ThreeByteBgr.deriveSubType(DESC_GDI); 79 80 private static native void initIDs(Class xorComp); 81 82 static { 83 initIDs(XORComposite.class); 84 if (WindowsFlags.isGdiBlitEnabled()) { 85 // Register our gdi Blit loops 86 GDIBlitLoops.register(); 87 } 88 } 89 90 public static SurfaceType getSurfaceType(ColorModel cm) { 91 switch (cm.getPixelSize()) { 92 case 32: 93 case 24: 94 if (cm instanceof DirectColorModel) { 95 if (((DirectColorModel)cm).getRedMask() == 0xff0000) { 96 return IntRgbGdi; 97 } else { 98 return SurfaceType.IntRgbx; 99 } 100 } else { 101 return ThreeByteBgrGdi; 102 } 103 case 15: 104 return Ushort555RgbGdi; 105 case 16: 106 if ((cm instanceof DirectColorModel) && 107 (((DirectColorModel)cm).getBlueMask() == 0x3e)) 108 { 109 return SurfaceType.Ushort555Rgbx; 110 } else { 111 return Ushort565RgbGdi; 112 } 113 case 8: 114 if (cm.getColorSpace().getType() == ColorSpace.TYPE_GRAY && 115 cm instanceof ComponentColorModel) { 116 return SurfaceType.ByteGray; 117 } else if (cm instanceof IndexColorModel && 118 isOpaqueGray((IndexColorModel)cm)) { 119 return SurfaceType.Index8Gray; 120 } else { 121 return SurfaceType.ByteIndexedOpaque; 122 } 123 default: 124 throw new sun.java2d.InvalidPipeException("Unsupported bit " + 125 "depth: " + 126 cm.getPixelSize()); 127 } 128 } 129 130 public static GDIWindowSurfaceData createData(WComponentPeer peer) { 131 SurfaceType sType = getSurfaceType(peer.getDeviceColorModel()); 132 return new GDIWindowSurfaceData(peer, sType); 133 } 134 135 @Override 136 public SurfaceDataProxy makeProxyFor(SurfaceData srcData) { 137 return SurfaceDataProxy.UNCACHED; 138 } 139 140 public Raster getRaster(int x, int y, int w, int h) { 141 throw new InternalError("not implemented yet"); 142 } 143 144 protected static GDIRenderer gdiPipe; 145 protected static PixelToShapeConverter gdiTxPipe; 146 147 static { 148 gdiPipe = new GDIRenderer(); 149 if (GraphicsPrimitive.tracingEnabled()) { 150 gdiPipe = gdiPipe.traceWrap(); 151 } 152 gdiTxPipe = new PixelToShapeConverter(gdiPipe); 153 154 } 155 156 public void validatePipe(SunGraphics2D sg2d) { 157 if (sg2d.antialiasHint != SunHints.INTVAL_ANTIALIAS_ON && 158 sg2d.paintState <= sg2d.PAINT_ALPHACOLOR && 159 (sg2d.compositeState <= sg2d.COMP_ISCOPY || 160 sg2d.compositeState == sg2d.COMP_XOR)) 161 { 162 if (sg2d.clipState == sg2d.CLIP_SHAPE) { 163 // Do this to init textpipe correctly; we will override the 164 // other non-text pipes below 165 // REMIND: we should clean this up eventually instead of 166 // having this work duplicated. 167 super.validatePipe(sg2d); 168 } else { 169 switch (sg2d.textAntialiasHint) { 170 171 case SunHints.INTVAL_TEXT_ANTIALIAS_DEFAULT: 172 /* equate DEFAULT to OFF which it is for us */ 173 case SunHints.INTVAL_TEXT_ANTIALIAS_OFF: 174 sg2d.textpipe = solidTextRenderer; 175 break; 176 177 case SunHints.INTVAL_TEXT_ANTIALIAS_ON: 178 sg2d.textpipe = aaTextRenderer; 179 break; 180 181 default: 182 switch (sg2d.getFontInfo().aaHint) { 183 184 case SunHints.INTVAL_TEXT_ANTIALIAS_LCD_HRGB: 185 case SunHints.INTVAL_TEXT_ANTIALIAS_LCD_VRGB: 186 sg2d.textpipe = lcdTextRenderer; 187 break; 188 189 case SunHints.INTVAL_TEXT_ANTIALIAS_ON: 190 sg2d.textpipe = aaTextRenderer; 191 break; 192 193 default: 194 sg2d.textpipe = solidTextRenderer; 195 } 196 } 197 } 198 sg2d.imagepipe = imagepipe; 199 if (sg2d.transformState >= sg2d.TRANSFORM_TRANSLATESCALE) { 200 sg2d.drawpipe = gdiTxPipe; 201 sg2d.fillpipe = gdiTxPipe; 202 } else if (sg2d.strokeState != sg2d.STROKE_THIN){ 203 sg2d.drawpipe = gdiTxPipe; 204 sg2d.fillpipe = gdiPipe; 205 } else { 206 sg2d.drawpipe = gdiPipe; 207 sg2d.fillpipe = gdiPipe; 208 } 209 sg2d.shapepipe = gdiPipe; 210 // This is needed for AA text. 211 // Note that even a SolidTextRenderer can dispatch AA text 212 // if a GlyphVector overrides the AA setting. 213 // We use getRenderLoops() rather than setting solidloops 214 // directly so that we get the appropriate loops in XOR mode. 215 sg2d.setLoops(getRenderLoops(sg2d)); 216 } else { 217 super.validatePipe(sg2d); 218 } 219 } 220 221 public RenderLoops getRenderLoops(SunGraphics2D sg2d) { 222 if (sg2d.paintState <= sg2d.PAINT_ALPHACOLOR && 223 sg2d.compositeState <= sg2d.COMP_ISCOPY) 224 { 225 return solidloops; 226 } 227 return super.getRenderLoops(sg2d); 228 } 229 230 public GraphicsConfiguration getDeviceConfiguration() { 231 return graphicsConfig; 232 } 233 234 /** 235 * Initializes the native Ops pointer. 236 */ 237 private native void initOps(WComponentPeer peer, int depth, int redMask, 238 int greenMask, int blueMask, int screen); 239 240 private GDIWindowSurfaceData(WComponentPeer peer, SurfaceType sType) { 241 super(sType, peer.getDeviceColorModel()); 242 ColorModel cm = peer.getDeviceColorModel(); 243 this.peer = peer; 244 int rMask = 0, gMask = 0, bMask = 0; 245 int depth; 246 switch (cm.getPixelSize()) { 247 case 32: 248 case 24: 249 if (cm instanceof DirectColorModel) { 250 depth = 32; 251 } else { 252 depth = 24; 253 } 254 break; 255 default: 256 depth = cm.getPixelSize(); 257 } 258 if (cm instanceof DirectColorModel) { 259 DirectColorModel dcm = (DirectColorModel)cm; 260 rMask = dcm.getRedMask(); 261 gMask = dcm.getGreenMask(); 262 bMask = dcm.getBlueMask(); 263 } 264 this.graphicsConfig = 265 (Win32GraphicsConfig) peer.getGraphicsConfiguration(); 266 this.solidloops = graphicsConfig.getSolidLoops(sType); 267 if (peer instanceof WFileDialogPeer || 268 peer instanceof WPrintDialogPeer ) 269 { 270 // REMIND: Awful hack. The right fix for this problem 271 // would be for these type of Peers to not even use a 272 // GDIWindowSurfaceData object since they never do any 273 // rendering. Or they could actually implement the 274 // functionality needed in initOps. But this seems 275 // to work for now. See bug 4391928 for more info. 276 return; 277 } 278 Win32GraphicsDevice gd = 279 (Win32GraphicsDevice)graphicsConfig.getDevice(); 280 initOps(peer, depth, rMask, gMask, bMask, gd.getScreen()); 281 setBlitProxyKey(graphicsConfig.getProxyKey()); 282 } 283 284 /** 285 * {@inheritDoc} 286 * 287 * Overridden to use ScreenUpdateManager to obtain the replacement surface. 288 * 289 * @see sun.java2d.ScreenUpdateManager#getReplacementScreenSurface 290 */ 291 @Override 292 public SurfaceData getReplacement() { 293 ScreenUpdateManager mgr = ScreenUpdateManager.getInstance(); 294 return mgr.getReplacementScreenSurface(peer, this); 295 } 296 297 public Rectangle getBounds() { 298 Rectangle r = peer.getBounds(); 299 r.x = r.y = 0; 300 return r; 301 } 302 303 public boolean copyArea(SunGraphics2D sg2d, 304 int x, int y, int w, int h, int dx, int dy) 305 { 306 CompositeType comptype = sg2d.imageComp; 307 if (sg2d.transformState < sg2d.TRANSFORM_TRANSLATESCALE && 308 sg2d.clipState != sg2d.CLIP_SHAPE && 309 (CompositeType.SrcOverNoEa.equals(comptype) || 310 CompositeType.SrcNoEa.equals(comptype))) 311 { 312 x += sg2d.transX; 313 y += sg2d.transY; 314 int dstx1 = x + dx; 315 int dsty1 = y + dy; 316 int dstx2 = dstx1 + w; 317 int dsty2 = dsty1 + h; 318 Region clip = sg2d.getCompClip(); 319 if (dstx1 < clip.getLoX()) dstx1 = clip.getLoX(); 320 if (dsty1 < clip.getLoY()) dsty1 = clip.getLoY(); 321 if (dstx2 > clip.getHiX()) dstx2 = clip.getHiX(); 322 if (dsty2 > clip.getHiY()) dsty2 = clip.getHiY(); 323 if (dstx1 < dstx2 && dsty1 < dsty2) { 324 gdiPipe.devCopyArea(this, dstx1 - dx, dsty1 - dy, 325 dx, dy, 326 dstx2 - dstx1, dsty2 - dsty1); 327 } 328 return true; 329 } 330 return false; 331 } 332 333 private native void invalidateSD(); 334 @Override 335 public void invalidate() { 336 if (isValid()) { 337 invalidateSD(); 338 super.invalidate(); 339 //peer.invalidateBackBuffer(); 340 } 341 } 342 343 /** 344 * Returns destination Component associated with this SurfaceData. 345 */ 346 @Override 347 public Object getDestination() { 348 return peer.getTarget(); 349 } 350 351 public WComponentPeer getPeer() { 352 return peer; 353 } 354 }