GDIWindowSurfaceData.java revision 13220:a8e9ad77ac81
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
26package sun.java2d.windows;
27
28import java.awt.Rectangle;
29import java.awt.GraphicsConfiguration;
30import java.awt.color.ColorSpace;
31import java.awt.geom.AffineTransform;
32import java.awt.image.ColorModel;
33import java.awt.image.ComponentColorModel;
34import java.awt.image.DirectColorModel;
35import java.awt.image.IndexColorModel;
36import java.awt.image.Raster;
37
38import sun.awt.SunHints;
39import sun.awt.Win32GraphicsConfig;
40import sun.awt.Win32GraphicsDevice;
41import sun.awt.windows.WComponentPeer;
42import sun.java2d.ScreenUpdateManager;
43import sun.java2d.SunGraphics2D;
44import sun.java2d.SurfaceData;
45import sun.java2d.SurfaceDataProxy;
46import sun.java2d.pipe.Region;
47import sun.java2d.pipe.PixelToShapeConverter;
48import sun.java2d.loops.GraphicsPrimitive;
49import sun.java2d.loops.SurfaceType;
50import sun.java2d.loops.CompositeType;
51import sun.java2d.loops.RenderLoops;
52import sun.java2d.loops.XORComposite;
53
54public 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 = (int) Math.ceil(r.width * scaleX);
306        r.height = (int) Math.ceil(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.transformState < SunGraphics2D.TRANSFORM_TRANSLATESCALE &&
315            sg2d.clipState != SunGraphics2D.CLIP_SHAPE &&
316            (CompositeType.SrcOverNoEa.equals(comptype) ||
317             CompositeType.SrcNoEa.equals(comptype)))
318        {
319            x += sg2d.transX;
320            y += sg2d.transY;
321            int dstx1 = x + dx;
322            int dsty1 = y + dy;
323            int dstx2 = dstx1 + w;
324            int dsty2 = dsty1 + h;
325            Region clip = sg2d.getCompClip();
326            if (dstx1 < clip.getLoX()) dstx1 = clip.getLoX();
327            if (dsty1 < clip.getLoY()) dsty1 = clip.getLoY();
328            if (dstx2 > clip.getHiX()) dstx2 = clip.getHiX();
329            if (dsty2 > clip.getHiY()) dsty2 = clip.getHiY();
330            if (dstx1 < dstx2 && dsty1 < dsty2) {
331                gdiPipe.devCopyArea(this, dstx1 - dx, dsty1 - dy,
332                                    dx, dy,
333                                    dstx2 - dstx1, dsty2 - dsty1);
334            }
335            return true;
336        }
337        return false;
338    }
339
340    private native void invalidateSD();
341    @Override
342    public void invalidate() {
343        if (isValid()) {
344            invalidateSD();
345            super.invalidate();
346            //peer.invalidateBackBuffer();
347        }
348    }
349
350    /**
351     * Returns destination Component associated with this SurfaceData.
352     */
353    @Override
354    public Object getDestination() {
355        return peer.getTarget();
356    }
357
358    public WComponentPeer getPeer() {
359        return peer;
360    }
361}
362