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 
initIDs(Class xorComp)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
GDIBlitLoops.register()84             GDIBlitLoops.register();
85         }
86     }
87 
getSurfaceType(ColorModel cm)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 
createData(WComponentPeer peer)128     public static GDIWindowSurfaceData createData(WComponentPeer peer) {
129         SurfaceType sType = getSurfaceType(peer.getDeviceColorModel());
130         return new GDIWindowSurfaceData(peer, sType);
131     }
132 
133     @Override
makeProxyFor(SurfaceData srcData)134     public SurfaceDataProxy makeProxyFor(SurfaceData srcData) {
135         return SurfaceDataProxy.UNCACHED;
136     }
137 
getRaster(int x, int y, int w, int h)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 
validatePipe(SunGraphics2D sg2d)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 
getRenderLoops(SunGraphics2D sg2d)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 
getDeviceConfiguration()231     public GraphicsConfiguration getDeviceConfiguration() {
232         return graphicsConfig;
233     }
234 
235     /**
236      * Initializes the native Ops pointer.
237      */
initOps(WComponentPeer peer, int depth, int redMask, int greenMask, int blueMask, int screen)238     private native void initOps(WComponentPeer peer, int depth, int redMask,
239                                 int greenMask, int blueMask, int screen);
240 
GDIWindowSurfaceData(WComponentPeer peer, SurfaceType sType)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
getReplacement()283     public SurfaceData getReplacement() {
284         ScreenUpdateManager mgr = ScreenUpdateManager.getInstance();
285         return mgr.getReplacementScreenSurface(peer, this);
286     }
287 
getBounds()288     public Rectangle getBounds() {
289         Rectangle r = peer.getBounds();
290         r.x = r.y = 0;
291         return r;
292     }
293 
copyArea(SunGraphics2D sg2d, int x, int y, int w, int h, int dx, int dy)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 
invalidateSD()324     private native void invalidateSD();
325     @Override
invalidate()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
getDestination()338     public Object getDestination() {
339         return peer.getTarget();
340     }
341 
getPeer()342     public WComponentPeer getPeer() {
343         return peer;
344     }
345 }
346