1 /* 2 * Copyright (c) 1999, 2008, Oracle and/or its affiliates. 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * 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.java2d.ScreenUpdateManager; 42 import sun.java2d.SunGraphics2D; 43 import sun.java2d.SurfaceData; 44 import sun.java2d.SurfaceDataProxy; 45 import sun.java2d.pipe.Region; 46 import sun.java2d.pipe.PixelToShapeConverter; 47 import sun.java2d.loops.GraphicsPrimitive; 48 import sun.java2d.loops.SurfaceType; 49 import sun.java2d.loops.CompositeType; 50 import sun.java2d.loops.RenderLoops; 51 import sun.java2d.loops.XORComposite; 52 53 public class GDIWindowSurfaceData extends SurfaceData { 54 private WComponentPeer peer; 55 private Win32GraphicsConfig graphicsConfig; 56 private RenderLoops solidloops; 57 58 // GDI onscreen surface type 59 public static final String 60 DESC_GDI = "GDI"; 61 62 // Generic GDI surface type - used for registering all loops 63 public static final SurfaceType AnyGdi = 64 SurfaceType.IntRgb.deriveSubType(DESC_GDI); 65 66 public static final SurfaceType IntRgbGdi = 67 SurfaceType.IntRgb.deriveSubType(DESC_GDI); 68 69 public static final SurfaceType Ushort565RgbGdi = 70 SurfaceType.Ushort565Rgb.deriveSubType(DESC_GDI); 71 72 public static final SurfaceType Ushort555RgbGdi = 73 SurfaceType.Ushort555Rgb.deriveSubType(DESC_GDI); 74 75 public static final SurfaceType ThreeByteBgrGdi = 76 SurfaceType.ThreeByteBgr.deriveSubType(DESC_GDI); 77 78 private static native void initIDs(Class xorComp); 79 80 static { 81 initIDs(XORComposite.class); 82 if (WindowsFlags.isGdiBlitEnabled()) { 83 // Register our gdi Blit loops 84 GDIBlitLoops.register(); 85 } 86 } 87 88 public static SurfaceType getSurfaceType(ColorModel cm) { 89 switch (cm.getPixelSize()) { 90 case 32: 91 case 24: 92 if (cm instanceof DirectColorModel) { 93 if (((DirectColorModel)cm).getRedMask() == 0xff0000) { 94 return IntRgbGdi; 95 } else { 96 return SurfaceType.IntRgbx; 97 } 98 } else { 99 return ThreeByteBgrGdi; 100 } 101 case 15: 102 return Ushort555RgbGdi; 103 case 16: 104 if ((cm instanceof DirectColorModel) && 105 (((DirectColorModel)cm).getBlueMask() == 0x3e)) 106 { 107 return SurfaceType.Ushort555Rgbx; 108 } else { 109 return Ushort565RgbGdi; 110 } 111 case 8: 112 if (cm.getColorSpace().getType() == ColorSpace.TYPE_GRAY && 113 cm instanceof ComponentColorModel) { 114 return SurfaceType.ByteGray; 115 } else if (cm instanceof IndexColorModel && 116 isOpaqueGray((IndexColorModel)cm)) { 117 return SurfaceType.Index8Gray; 118 } else { 119 return SurfaceType.ByteIndexedOpaque; 120 } 121 default: 122 throw new sun.java2d.InvalidPipeException("Unsupported bit " + 123 "depth: " + 124 cm.getPixelSize()); 125 } 126 } 127 128 public static GDIWindowSurfaceData createData(WComponentPeer peer) { 129 SurfaceType sType = getSurfaceType(peer.getDeviceColorModel()); 130 return new GDIWindowSurfaceData(peer, sType); 131 } 132 133 @Override 134 public SurfaceDataProxy makeProxyFor(SurfaceData srcData) { 135 return SurfaceDataProxy.UNCACHED; 136 } 137 138 public Raster getRaster(int x, int y, int w, int h) { 139 throw new InternalError("not implemented yet"); 140 } 141 142 protected static GDIRenderer gdiPipe; 143 protected static PixelToShapeConverter gdiTxPipe; 144 145 static { 146 gdiPipe = new GDIRenderer(); 147 if (GraphicsPrimitive.tracingEnabled()) { 148 gdiPipe = gdiPipe.traceWrap(); 149 } 150 gdiTxPipe = new PixelToShapeConverter(gdiPipe); 151 152 } 153 154 public void validatePipe(SunGraphics2D sg2d) { 155 if (sg2d.antialiasHint != SunHints.INTVAL_ANTIALIAS_ON && 156 sg2d.paintState <= sg2d.PAINT_ALPHACOLOR && 157 (sg2d.compositeState <= sg2d.COMP_ISCOPY || 158 sg2d.compositeState == sg2d.COMP_XOR)) 159 { 160 if (sg2d.clipState == sg2d.CLIP_SHAPE) { 161 // Do this to init textpipe correctly; we will override the 162 // other non-text pipes below 163 // REMIND: we should clean this up eventually instead of 164 // having this work duplicated. 165 super.validatePipe(sg2d); 166 } else { 167 switch (sg2d.textAntialiasHint) { 168 169 case SunHints.INTVAL_TEXT_ANTIALIAS_DEFAULT: 170 /* equate DEFAULT to OFF which it is for us */ 171 case SunHints.INTVAL_TEXT_ANTIALIAS_OFF: 172 sg2d.textpipe = solidTextRenderer; 173 break; 174 175 case SunHints.INTVAL_TEXT_ANTIALIAS_ON: 176 sg2d.textpipe = aaTextRenderer; 177 break; 178 179 default: 180 switch (sg2d.getFontInfo().aaHint) { 181 182 case SunHints.INTVAL_TEXT_ANTIALIAS_LCD_HRGB: 183 case SunHints.INTVAL_TEXT_ANTIALIAS_LCD_VRGB: 184 sg2d.textpipe = lcdTextRenderer; 185 break; 186 187 case SunHints.INTVAL_TEXT_ANTIALIAS_ON: 188 sg2d.textpipe = aaTextRenderer; 189 break; 190 191 default: 192 sg2d.textpipe = solidTextRenderer; 193 } 194 } 195 } 196 sg2d.imagepipe = imagepipe; 197 if (sg2d.transformState >= sg2d.TRANSFORM_TRANSLATESCALE) { 198 sg2d.drawpipe = gdiTxPipe; 199 sg2d.fillpipe = gdiTxPipe; 200 } else if (sg2d.strokeState != sg2d.STROKE_THIN){ 201 sg2d.drawpipe = gdiTxPipe; 202 sg2d.fillpipe = gdiPipe; 203 } else { 204 sg2d.drawpipe = gdiPipe; 205 sg2d.fillpipe = gdiPipe; 206 } 207 sg2d.shapepipe = gdiPipe; 208 // This is needed for AA text. 209 // Note that even a SolidTextRenderer can dispatch AA text 210 // if a GlyphVector overrides the AA setting. 211 // We use getRenderLoops() rather than setting solidloops 212 // directly so that we get the appropriate loops in XOR mode. 213 if (sg2d.loops == null) { 214 // assert(some pipe will always be a LoopBasedPipe) 215 sg2d.loops = getRenderLoops(sg2d); 216 } 217 } else { 218 super.validatePipe(sg2d); 219 } 220 } 221 222 public RenderLoops getRenderLoops(SunGraphics2D sg2d) { 223 if (sg2d.paintState <= sg2d.PAINT_ALPHACOLOR && 224 sg2d.compositeState <= sg2d.COMP_ISCOPY) 225 { 226 return solidloops; 227 } 228 return super.getRenderLoops(sg2d); 229 } 230 231 public GraphicsConfiguration getDeviceConfiguration() { 232 return graphicsConfig; 233 } 234 235 /** 236 * Initializes the native Ops pointer. 237 */ 238 private native void initOps(WComponentPeer peer, int depth, int redMask, 239 int greenMask, int blueMask, int screen); 240 241 private GDIWindowSurfaceData(WComponentPeer peer, SurfaceType sType) { 242 super(sType, peer.getDeviceColorModel()); 243 ColorModel cm = peer.getDeviceColorModel(); 244 this.peer = peer; 245 int rMask = 0, gMask = 0, bMask = 0; 246 int depth; 247 switch (cm.getPixelSize()) { 248 case 32: 249 case 24: 250 if (cm instanceof DirectColorModel) { 251 depth = 32; 252 } else { 253 depth = 24; 254 } 255 break; 256 default: 257 depth = cm.getPixelSize(); 258 } 259 if (cm instanceof DirectColorModel) { 260 DirectColorModel dcm = (DirectColorModel)cm; 261 rMask = dcm.getRedMask(); 262 gMask = dcm.getGreenMask(); 263 bMask = dcm.getBlueMask(); 264 } 265 this.graphicsConfig = 266 (Win32GraphicsConfig) peer.getGraphicsConfiguration(); 267 this.solidloops = graphicsConfig.getSolidLoops(sType); 268 269 Win32GraphicsDevice gd = 270 (Win32GraphicsDevice)graphicsConfig.getDevice(); 271 initOps(peer, depth, rMask, gMask, bMask, gd.getScreen()); 272 setBlitProxyKey(graphicsConfig.getProxyKey()); 273 } 274 275 /** 276 * {@inheritDoc} 277 * 278 * Overridden to use ScreenUpdateManager to obtain the replacement surface. 279 * 280 * @see sun.java2d.ScreenUpdateManager#getReplacementScreenSurface 281 */ 282 @Override 283 public SurfaceData getReplacement() { 284 ScreenUpdateManager mgr = ScreenUpdateManager.getInstance(); 285 return mgr.getReplacementScreenSurface(peer, this); 286 } 287 288 public Rectangle getBounds() { 289 Rectangle r = peer.getBounds(); 290 r.x = r.y = 0; 291 return r; 292 } 293 294 public boolean copyArea(SunGraphics2D sg2d, 295 int x, int y, int w, int h, int dx, int dy) 296 { 297 CompositeType comptype = sg2d.imageComp; 298 if (sg2d.transformState < sg2d.TRANSFORM_TRANSLATESCALE && 299 sg2d.clipState != sg2d.CLIP_SHAPE && 300 (CompositeType.SrcOverNoEa.equals(comptype) || 301 CompositeType.SrcNoEa.equals(comptype))) 302 { 303 x += sg2d.transX; 304 y += sg2d.transY; 305 int dstx1 = x + dx; 306 int dsty1 = y + dy; 307 int dstx2 = dstx1 + w; 308 int dsty2 = dsty1 + h; 309 Region clip = sg2d.getCompClip(); 310 if (dstx1 < clip.getLoX()) dstx1 = clip.getLoX(); 311 if (dsty1 < clip.getLoY()) dsty1 = clip.getLoY(); 312 if (dstx2 > clip.getHiX()) dstx2 = clip.getHiX(); 313 if (dsty2 > clip.getHiY()) dsty2 = clip.getHiY(); 314 if (dstx1 < dstx2 && dsty1 < dsty2) { 315 gdiPipe.devCopyArea(this, dstx1 - dx, dsty1 - dy, 316 dx, dy, 317 dstx2 - dstx1, dsty2 - dsty1); 318 } 319 return true; 320 } 321 return false; 322 } 323 324 private native void invalidateSD(); 325 @Override 326 public void invalidate() { 327 if (isValid()) { 328 invalidateSD(); 329 super.invalidate(); 330 //peer.invalidateBackBuffer(); 331 } 332 } 333 334 /** 335 * Returns destination Component associated with this SurfaceData. 336 */ 337 @Override 338 public Object getDestination() { 339 return peer.getTarget(); 340 } 341 342 public WComponentPeer getPeer() { 343 return peer; 344 } 345 }