blob: deaf9c60e0db45d57ca569ca382a68b2eb7aafec [file] [log] [blame]
/*
* Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.java2d.windows;
import java.awt.Rectangle;
import java.awt.GraphicsConfiguration;
import java.awt.color.ColorSpace;
import java.awt.image.ColorModel;
import java.awt.image.ComponentColorModel;
import java.awt.image.DirectColorModel;
import java.awt.image.IndexColorModel;
import java.awt.image.Raster;
import sun.awt.SunHints;
import sun.awt.Win32GraphicsConfig;
import sun.awt.Win32GraphicsDevice;
import sun.awt.windows.WComponentPeer;
import sun.java2d.ScreenUpdateManager;
import sun.java2d.SunGraphics2D;
import sun.java2d.SurfaceData;
import sun.java2d.SurfaceDataProxy;
import sun.java2d.pipe.Region;
import sun.java2d.pipe.PixelToShapeConverter;
import sun.java2d.loops.GraphicsPrimitive;
import sun.java2d.loops.SurfaceType;
import sun.java2d.loops.CompositeType;
import sun.java2d.loops.RenderLoops;
import sun.java2d.loops.XORComposite;
public class GDIWindowSurfaceData extends SurfaceData {
private WComponentPeer peer;
private Win32GraphicsConfig graphicsConfig;
private RenderLoops solidloops;
// GDI onscreen surface type
public static final String
DESC_GDI = "GDI";
// Generic GDI surface type - used for registering all loops
public static final SurfaceType AnyGdi =
SurfaceType.IntRgb.deriveSubType(DESC_GDI);
public static final SurfaceType IntRgbGdi =
SurfaceType.IntRgb.deriveSubType(DESC_GDI);
public static final SurfaceType Ushort565RgbGdi =
SurfaceType.Ushort565Rgb.deriveSubType(DESC_GDI);
public static final SurfaceType Ushort555RgbGdi =
SurfaceType.Ushort555Rgb.deriveSubType(DESC_GDI);
public static final SurfaceType ThreeByteBgrGdi =
SurfaceType.ThreeByteBgr.deriveSubType(DESC_GDI);
private static native void initIDs(Class xorComp);
static {
initIDs(XORComposite.class);
if (WindowsFlags.isGdiBlitEnabled()) {
// Register our gdi Blit loops
GDIBlitLoops.register();
}
}
public static SurfaceType getSurfaceType(ColorModel cm) {
switch (cm.getPixelSize()) {
case 32:
case 24:
if (cm instanceof DirectColorModel) {
if (((DirectColorModel)cm).getRedMask() == 0xff0000) {
return IntRgbGdi;
} else {
return SurfaceType.IntRgbx;
}
} else {
return ThreeByteBgrGdi;
}
case 15:
return Ushort555RgbGdi;
case 16:
if ((cm instanceof DirectColorModel) &&
(((DirectColorModel)cm).getBlueMask() == 0x3e))
{
return SurfaceType.Ushort555Rgbx;
} else {
return Ushort565RgbGdi;
}
case 8:
if (cm.getColorSpace().getType() == ColorSpace.TYPE_GRAY &&
cm instanceof ComponentColorModel) {
return SurfaceType.ByteGray;
} else if (cm instanceof IndexColorModel &&
isOpaqueGray((IndexColorModel)cm)) {
return SurfaceType.Index8Gray;
} else {
return SurfaceType.ByteIndexedOpaque;
}
default:
throw new sun.java2d.InvalidPipeException("Unsupported bit " +
"depth: " +
cm.getPixelSize());
}
}
public static GDIWindowSurfaceData createData(WComponentPeer peer) {
SurfaceType sType = getSurfaceType(peer.getDeviceColorModel());
return new GDIWindowSurfaceData(peer, sType);
}
@Override
public SurfaceDataProxy makeProxyFor(SurfaceData srcData) {
return SurfaceDataProxy.UNCACHED;
}
public Raster getRaster(int x, int y, int w, int h) {
throw new InternalError("not implemented yet");
}
protected static GDIRenderer gdiPipe;
protected static PixelToShapeConverter gdiTxPipe;
static {
gdiPipe = new GDIRenderer();
if (GraphicsPrimitive.tracingEnabled()) {
gdiPipe = gdiPipe.traceWrap();
}
gdiTxPipe = new PixelToShapeConverter(gdiPipe);
}
public void validatePipe(SunGraphics2D sg2d) {
if (sg2d.antialiasHint != SunHints.INTVAL_ANTIALIAS_ON &&
sg2d.paintState <= sg2d.PAINT_ALPHACOLOR &&
(sg2d.compositeState <= sg2d.COMP_ISCOPY ||
sg2d.compositeState == sg2d.COMP_XOR))
{
if (sg2d.clipState == sg2d.CLIP_SHAPE) {
// Do this to init textpipe correctly; we will override the
// other non-text pipes below
// REMIND: we should clean this up eventually instead of
// having this work duplicated.
super.validatePipe(sg2d);
} else {
switch (sg2d.textAntialiasHint) {
case SunHints.INTVAL_TEXT_ANTIALIAS_DEFAULT:
/* equate DEFAULT to OFF which it is for us */
case SunHints.INTVAL_TEXT_ANTIALIAS_OFF:
sg2d.textpipe = solidTextRenderer;
break;
case SunHints.INTVAL_TEXT_ANTIALIAS_ON:
sg2d.textpipe = aaTextRenderer;
break;
default:
switch (sg2d.getFontInfo().aaHint) {
case SunHints.INTVAL_TEXT_ANTIALIAS_LCD_HRGB:
case SunHints.INTVAL_TEXT_ANTIALIAS_LCD_VRGB:
sg2d.textpipe = lcdTextRenderer;
break;
case SunHints.INTVAL_TEXT_ANTIALIAS_ON:
sg2d.textpipe = aaTextRenderer;
break;
default:
sg2d.textpipe = solidTextRenderer;
}
}
}
sg2d.imagepipe = imagepipe;
if (sg2d.transformState >= sg2d.TRANSFORM_TRANSLATESCALE) {
sg2d.drawpipe = gdiTxPipe;
sg2d.fillpipe = gdiTxPipe;
} else if (sg2d.strokeState != sg2d.STROKE_THIN){
sg2d.drawpipe = gdiTxPipe;
sg2d.fillpipe = gdiPipe;
} else {
sg2d.drawpipe = gdiPipe;
sg2d.fillpipe = gdiPipe;
}
sg2d.shapepipe = gdiPipe;
// This is needed for AA text.
// Note that even a SolidTextRenderer can dispatch AA text
// if a GlyphVector overrides the AA setting.
// We use getRenderLoops() rather than setting solidloops
// directly so that we get the appropriate loops in XOR mode.
if (sg2d.loops == null) {
// assert(some pipe will always be a LoopBasedPipe)
sg2d.loops = getRenderLoops(sg2d);
}
} else {
super.validatePipe(sg2d);
}
}
public RenderLoops getRenderLoops(SunGraphics2D sg2d) {
if (sg2d.paintState <= sg2d.PAINT_ALPHACOLOR &&
sg2d.compositeState <= sg2d.COMP_ISCOPY)
{
return solidloops;
}
return super.getRenderLoops(sg2d);
}
public GraphicsConfiguration getDeviceConfiguration() {
return graphicsConfig;
}
/**
* Initializes the native Ops pointer.
*/
private native void initOps(WComponentPeer peer, int depth, int redMask,
int greenMask, int blueMask, int screen);
private GDIWindowSurfaceData(WComponentPeer peer, SurfaceType sType) {
super(sType, peer.getDeviceColorModel());
ColorModel cm = peer.getDeviceColorModel();
this.peer = peer;
int rMask = 0, gMask = 0, bMask = 0;
int depth;
switch (cm.getPixelSize()) {
case 32:
case 24:
if (cm instanceof DirectColorModel) {
depth = 32;
} else {
depth = 24;
}
break;
default:
depth = cm.getPixelSize();
}
if (cm instanceof DirectColorModel) {
DirectColorModel dcm = (DirectColorModel)cm;
rMask = dcm.getRedMask();
gMask = dcm.getGreenMask();
bMask = dcm.getBlueMask();
}
this.graphicsConfig =
(Win32GraphicsConfig) peer.getGraphicsConfiguration();
this.solidloops = graphicsConfig.getSolidLoops(sType);
Win32GraphicsDevice gd =
(Win32GraphicsDevice)graphicsConfig.getDevice();
initOps(peer, depth, rMask, gMask, bMask, gd.getScreen());
setBlitProxyKey(graphicsConfig.getProxyKey());
}
/**
* {@inheritDoc}
*
* Overridden to use ScreenUpdateManager to obtain the replacement surface.
*
* @see sun.java2d.ScreenUpdateManager#getReplacementScreenSurface
*/
@Override
public SurfaceData getReplacement() {
ScreenUpdateManager mgr = ScreenUpdateManager.getInstance();
return mgr.getReplacementScreenSurface(peer, this);
}
public Rectangle getBounds() {
Rectangle r = peer.getBounds();
r.x = r.y = 0;
return r;
}
public boolean copyArea(SunGraphics2D sg2d,
int x, int y, int w, int h, int dx, int dy)
{
CompositeType comptype = sg2d.imageComp;
if (sg2d.transformState < sg2d.TRANSFORM_TRANSLATESCALE &&
sg2d.clipState != sg2d.CLIP_SHAPE &&
(CompositeType.SrcOverNoEa.equals(comptype) ||
CompositeType.SrcNoEa.equals(comptype)))
{
x += sg2d.transX;
y += sg2d.transY;
int dstx1 = x + dx;
int dsty1 = y + dy;
int dstx2 = dstx1 + w;
int dsty2 = dsty1 + h;
Region clip = sg2d.getCompClip();
if (dstx1 < clip.getLoX()) dstx1 = clip.getLoX();
if (dsty1 < clip.getLoY()) dsty1 = clip.getLoY();
if (dstx2 > clip.getHiX()) dstx2 = clip.getHiX();
if (dsty2 > clip.getHiY()) dsty2 = clip.getHiY();
if (dstx1 < dstx2 && dsty1 < dsty2) {
gdiPipe.devCopyArea(this, dstx1 - dx, dsty1 - dy,
dx, dy,
dstx2 - dstx1, dsty2 - dsty1);
}
return true;
}
return false;
}
private native void invalidateSD();
@Override
public void invalidate() {
if (isValid()) {
invalidateSD();
super.invalidate();
//peer.invalidateBackBuffer();
}
}
/**
* Returns destination Component associated with this SurfaceData.
*/
@Override
public Object getDestination() {
return peer.getTarget();
}
public WComponentPeer getPeer() {
return peer;
}
}