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