mirror of
https://github.com/openjdk/jdk.git
synced 2026-04-28 15:51:02 +00:00
355 lines
11 KiB
Java
355 lines
11 KiB
Java
/*
|
|
* Copyright (c) 2010, 2013, 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.xr;
|
|
|
|
import java.awt.*;
|
|
import java.awt.geom.*;
|
|
|
|
import java.security.AccessController;
|
|
import java.security.PrivilegedAction;
|
|
|
|
import sun.font.*;
|
|
import sun.java2d.*;
|
|
import sun.java2d.loops.*;
|
|
|
|
/**
|
|
* Manages per-application resources, e.g. the 1x1 pixmap used for solid color
|
|
* fill as well as per-application state e.g. the currently set source picture
|
|
* used for composition .
|
|
*
|
|
* @author Clemens Eisserer
|
|
*/
|
|
|
|
public class XRCompositeManager {
|
|
private static boolean enableGradCache = true;
|
|
private static XRCompositeManager instance;
|
|
|
|
private static final int SOLID = 0;
|
|
private static final int TEXTURE = 1;
|
|
private static final int GRADIENT = 2;
|
|
|
|
int srcType;
|
|
XRSolidSrcPict solidSrc32;
|
|
XRSurfaceData texture;
|
|
XRSurfaceData gradient;
|
|
int alphaMask = XRUtils.None;
|
|
|
|
XRColor solidColor = new XRColor();
|
|
float extraAlpha = 1.0f;
|
|
byte compRule = XRUtils.PictOpOver;
|
|
XRColor alphaColor = new XRColor();
|
|
|
|
XRSurfaceData solidSrcPict;
|
|
int alphaMaskPict;
|
|
int gradCachePixmap;
|
|
int gradCachePicture;
|
|
|
|
boolean xorEnabled = false;
|
|
int validatedPixel = 0;
|
|
Composite validatedComp;
|
|
Paint validatedPaint;
|
|
float validatedExtraAlpha = 1.0f;
|
|
|
|
XRBackend con;
|
|
MaskTileManager maskBuffer;
|
|
XRTextRenderer textRenderer;
|
|
XRMaskImage maskImage;
|
|
|
|
public static synchronized XRCompositeManager getInstance(
|
|
XRSurfaceData surface) {
|
|
if (instance == null) {
|
|
instance = new XRCompositeManager(surface);
|
|
}
|
|
return instance;
|
|
}
|
|
|
|
private XRCompositeManager(XRSurfaceData surface) {
|
|
con = new XRBackendNative();
|
|
|
|
String gradProp =
|
|
AccessController.doPrivileged(new PrivilegedAction<String>() {
|
|
public String run() {
|
|
return System.getProperty("sun.java2d.xrgradcache");
|
|
}
|
|
});
|
|
|
|
enableGradCache = gradProp == null ||
|
|
!(gradProp.equalsIgnoreCase("false") ||
|
|
gradProp.equalsIgnoreCase("f"));
|
|
|
|
XRPaints.register(this);
|
|
|
|
initResources(surface);
|
|
|
|
maskBuffer = new MaskTileManager(this, surface.getXid());
|
|
textRenderer = new XRTextRenderer(this);
|
|
maskImage = new XRMaskImage(this, surface.getXid());
|
|
}
|
|
|
|
public void initResources(XRSurfaceData surface) {
|
|
int parentXid = surface.getXid();
|
|
|
|
solidSrc32 = new XRSolidSrcPict(con, parentXid);
|
|
setForeground(0);
|
|
|
|
int extraAlphaMask = con.createPixmap(parentXid, 8, 1, 1);
|
|
alphaMaskPict = con.createPicture(extraAlphaMask,
|
|
XRUtils.PictStandardA8);
|
|
con.setPictureRepeat(alphaMaskPict, XRUtils.RepeatNormal);
|
|
con.renderRectangle(alphaMaskPict, XRUtils.PictOpClear,
|
|
XRColor.NO_ALPHA, 0, 0, 1, 1);
|
|
|
|
if (enableGradCache) {
|
|
gradCachePixmap = con.createPixmap(parentXid, 32,
|
|
MaskTileManager.MASK_SIZE, MaskTileManager.MASK_SIZE);
|
|
gradCachePicture = con.createPicture(gradCachePixmap,
|
|
XRUtils.PictStandardARGB32);
|
|
}
|
|
}
|
|
|
|
public void setForeground(int pixel) {
|
|
solidColor.setColorValues(pixel, true);
|
|
}
|
|
|
|
public void setGradientPaint(XRSurfaceData gradient) {
|
|
if (this.gradient != null) {
|
|
con.freePicture(this.gradient.picture);
|
|
}
|
|
this.gradient = gradient;
|
|
srcType = GRADIENT;
|
|
}
|
|
|
|
public void setTexturePaint(XRSurfaceData texture) {
|
|
this.texture = texture;
|
|
this.srcType = TEXTURE;
|
|
}
|
|
|
|
public void XRResetPaint() {
|
|
srcType = SOLID;
|
|
}
|
|
|
|
public void validateCompositeState(Composite comp, AffineTransform xform,
|
|
Paint paint, SunGraphics2D sg2d) {
|
|
boolean updatePaint = (paint != validatedPaint) || paint == null;
|
|
|
|
// validate composite
|
|
if ((comp != validatedComp)) {
|
|
if (comp != null) {
|
|
setComposite(comp);
|
|
} else {
|
|
comp = AlphaComposite.getInstance(AlphaComposite.SRC_OVER);
|
|
setComposite(comp);
|
|
}
|
|
// the paint state is dependent on the composite state, so make
|
|
// sure we update the color below
|
|
updatePaint = true;
|
|
validatedComp = comp;
|
|
}
|
|
|
|
if (sg2d != null && (validatedPixel != sg2d.pixel || updatePaint)) {
|
|
validatedPixel = sg2d.pixel;
|
|
setForeground(validatedPixel);
|
|
}
|
|
|
|
// validate paint
|
|
if (updatePaint) {
|
|
if (paint != null && sg2d != null
|
|
&& sg2d.paintState >= SunGraphics2D.PAINT_GRADIENT) {
|
|
XRPaints.setPaint(sg2d, paint);
|
|
} else {
|
|
XRResetPaint();
|
|
}
|
|
validatedPaint = paint;
|
|
}
|
|
|
|
if (srcType != SOLID) {
|
|
AffineTransform at = (AffineTransform) xform.clone();
|
|
try {
|
|
at.invert();
|
|
} catch (NoninvertibleTransformException e) {
|
|
at.setToIdentity();
|
|
}
|
|
getCurrentSource().validateAsSource(at, -1, XRUtils.ATransOpToXRQuality(sg2d.interpolationType));
|
|
}
|
|
}
|
|
|
|
private void setComposite(Composite comp) {
|
|
if (comp instanceof AlphaComposite) {
|
|
AlphaComposite aComp = (AlphaComposite) comp;
|
|
validatedExtraAlpha = aComp.getAlpha();
|
|
|
|
this.compRule = XRUtils.j2dAlphaCompToXR(aComp.getRule());
|
|
this.extraAlpha = validatedExtraAlpha;
|
|
|
|
if (extraAlpha == 1.0f) {
|
|
alphaMask = XRUtils.None;
|
|
alphaColor.alpha = XRColor.FULL_ALPHA.alpha;
|
|
} else {
|
|
alphaColor.alpha = XRColor
|
|
.byteToXRColorValue((int) (extraAlpha * 255));
|
|
alphaMask = alphaMaskPict;
|
|
con.renderRectangle(alphaMaskPict, XRUtils.PictOpSrc,
|
|
alphaColor, 0, 0, 1, 1);
|
|
}
|
|
|
|
xorEnabled = false;
|
|
} else if (comp instanceof XORComposite) {
|
|
/* XOR composite validation is handled in XRSurfaceData */
|
|
xorEnabled = true;
|
|
} else {
|
|
throw new InternalError(
|
|
"Composite accaleration not implemented for: "
|
|
+ comp.getClass().getName());
|
|
}
|
|
}
|
|
|
|
public boolean maskRequired() {
|
|
return (!xorEnabled)
|
|
&& ((srcType != SOLID)
|
|
|| (srcType == SOLID && (solidColor.alpha != 0xffff) || (extraAlpha != 1.0f)));
|
|
}
|
|
|
|
public void XRComposite(int src, int mask, int dst, int srcX, int srcY,
|
|
int maskX, int maskY, int dstX, int dstY, int width, int height) {
|
|
int cachedSrc = (src == XRUtils.None) ? getCurrentSource().picture : src;
|
|
int cachedX = srcX;
|
|
int cachedY = srcY;
|
|
|
|
if (enableGradCache && gradient != null
|
|
&& cachedSrc == gradient.picture) {
|
|
con.renderComposite(XRUtils.PictOpSrc, gradient.picture,
|
|
XRUtils.None, gradCachePicture, srcX, srcY, 0, 0, 0, 0,
|
|
width, height);
|
|
cachedX = 0;
|
|
cachedY = 0;
|
|
cachedSrc = gradCachePicture;
|
|
}
|
|
|
|
con.renderComposite(compRule, cachedSrc, mask, dst, cachedX, cachedY,
|
|
maskX, maskY, dstX, dstY, width, height);
|
|
}
|
|
|
|
public void XRRenderRectangles(XRSurfaceData dst, GrowableRectArray rects) {
|
|
if (xorEnabled) {
|
|
con.GCRectangles(dst.getXid(), dst.getGC(), rects);
|
|
} else {
|
|
if (rects.getSize() == 1) {
|
|
con.renderRectangle(dst.getPicture(), compRule, solidColor,
|
|
rects.getX(0), rects.getY(0), rects.getWidth(0), rects.getHeight(0));
|
|
} else {
|
|
con.renderRectangles(dst.getPicture(), compRule, solidColor, rects);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void XRCompositeRectangles(XRSurfaceData dst, GrowableRectArray rects) {
|
|
int srcPict = getCurrentSource().picture;
|
|
|
|
for(int i=0; i < rects.getSize(); i++) {
|
|
int x = rects.getX(i);
|
|
int y = rects.getY(i);
|
|
int width = rects.getWidth(i);
|
|
int height = rects.getHeight(i);
|
|
|
|
con.renderComposite(compRule, srcPict, XRUtils.None, dst.picture, x, y, 0, 0, x, y, width, height);
|
|
}
|
|
}
|
|
|
|
protected XRSurfaceData getCurrentSource() {
|
|
switch(srcType) {
|
|
case SOLID:
|
|
return solidSrc32.prepareSrcPict(validatedPixel);
|
|
case TEXTURE:
|
|
return texture;
|
|
case GRADIENT:
|
|
return gradient;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public void compositeBlit(XRSurfaceData src, XRSurfaceData dst, int sx,
|
|
int sy, int dx, int dy, int w, int h) {
|
|
con.renderComposite(compRule, src.picture, alphaMask, dst.picture, sx,
|
|
sy, 0, 0, dx, dy, w, h);
|
|
}
|
|
|
|
public void compositeText(XRSurfaceData dst, int sx, int sy, int glyphSet,
|
|
int maskFormat, GrowableEltArray elts) {
|
|
/*
|
|
* Try to emulate the SRC blend mode with SRC_OVER.
|
|
* We bail out during pipe validation for cases where this is not possible.
|
|
*/
|
|
byte textCompRule = (compRule != XRUtils.PictOpSrc) ? compRule : XRUtils.PictOpOver;
|
|
con.XRenderCompositeText(textCompRule, getCurrentSource().picture, dst.picture,
|
|
maskFormat, sx, sy, 0, 0, glyphSet, elts);
|
|
}
|
|
|
|
public XRColor getMaskColor() {
|
|
return !isTexturePaintActive() ? XRColor.FULL_ALPHA : getAlphaColor();
|
|
}
|
|
|
|
public int getExtraAlphaMask() {
|
|
return alphaMask;
|
|
}
|
|
|
|
public boolean isTexturePaintActive() {
|
|
return srcType == TEXTURE;
|
|
}
|
|
|
|
public boolean isSolidPaintActive() {
|
|
return srcType == SOLID;
|
|
}
|
|
|
|
public XRColor getAlphaColor() {
|
|
return alphaColor;
|
|
}
|
|
|
|
public XRBackend getBackend() {
|
|
return con;
|
|
}
|
|
|
|
public float getExtraAlpha() {
|
|
return validatedExtraAlpha;
|
|
}
|
|
|
|
public byte getCompRule() {
|
|
return compRule;
|
|
}
|
|
|
|
public XRTextRenderer getTextRenderer() {
|
|
return textRenderer;
|
|
}
|
|
|
|
public MaskTileManager getMaskBuffer() {
|
|
return maskBuffer;
|
|
}
|
|
|
|
public XRMaskImage getMaskImage() {
|
|
return maskImage;
|
|
}
|
|
}
|