208 * required 209 * : 210 * - 211 * / 212 * ? 213 * ? 214 */ 215 x11sdDst.maskBuffer.compositeBlit(x11sdSrc, x11sdDst, (int) sx1, (int) sy1, (int) dx1, (int) dy1, (int) (dx2 - dx1), (int) (dy2 - dy1)); 216 } finally { 217 SunToolkit.awtUnlock(); 218 } 219 } 220 } 221 222 /** 223 * Called also if scale+transform is set 224 * 225 * @author Clemens Eisserer 226 */ 227 class XRPMTransformedBlit extends TransformBlit { 228 229 public XRPMTransformedBlit(SurfaceType srcType, SurfaceType dstType) { 230 super(srcType, CompositeType.AnyAlpha, dstType); 231 } 232 233 /* 234 * Calculates the composite-rectangle required for transformed blits. This 235 * method is functionally equal to: Shape shp = 236 * xform.createTransformedShape(rect); Rectangle bounds = shp.getBounds(); 237 * but performs significantly better. 238 */ 239 public Rectangle getCompositeBounds(AffineTransform tr, int dstx, int dsty, int width, int height) { 240 double[] compBounds = new double[8]; 241 compBounds[0] = dstx; 242 compBounds[1] = dsty; 243 compBounds[2] = dstx + width; 244 compBounds[3] = dsty; 245 compBounds[4] = dstx + width; 246 compBounds[5] = dsty + height; 247 compBounds[6] = dstx; 248 compBounds[7] = dsty + height; 249 250 tr.transform(compBounds, 0, compBounds, 0, 4); 251 252 double minX = Math.min(compBounds[0], Math.min(compBounds[2], Math.min(compBounds[4], compBounds[6]))); 253 double minY = Math.min(compBounds[1], Math.min(compBounds[3], Math.min(compBounds[5], compBounds[7]))); 254 double maxX = Math.max(compBounds[0], Math.max(compBounds[2], Math.max(compBounds[4], compBounds[6]))); 255 double maxY = Math.max(compBounds[1], Math.max(compBounds[3], Math.max(compBounds[5], compBounds[7]))); 256 257 minX = Math.floor(minX); 258 minY = Math.floor(minY); 259 maxX = Math.ceil(maxX); 260 maxY = Math.ceil(maxY); 261 262 return new Rectangle((int) minX, (int) minY, (int) (maxX - minX), (int) (maxY - minY)); 263 } 264 265 public void Transform(SurfaceData src, SurfaceData dst, Composite comp, Region clip, AffineTransform xform, int hint, int srcx, int srcy, 266 int dstx, int dsty, int width, int height) { 267 try { 268 SunToolkit.awtLock(); 269 270 int filter = XRUtils.ATransOpToXRQuality(hint); 271 272 XRSurfaceData x11sdDst = (XRSurfaceData) dst; 273 x11sdDst.validateAsDestination(null, clip); 274 XRSurfaceData x11sdSrc = (XRSurfaceData) src; 275 x11sdDst.maskBuffer.validateCompositeState(comp, null, null, null); 276 277 Rectangle bounds = getCompositeBounds(xform, dstx, dsty, width, height); 278 279 AffineTransform trx = AffineTransform.getTranslateInstance((-bounds.x), (-bounds.y)); 280 trx.concatenate(xform); 281 AffineTransform maskTX = (AffineTransform) trx.clone(); 282 283 trx.translate(-srcx, -srcy); 284 285 try { 286 trx.invert(); 287 } catch (NoninvertibleTransformException ex) { 288 trx.setToIdentity(); 289 System.err.println("Reseted to identity!"); 290 } 291 292 boolean omitMask = isMaskOmittable(trx, comp, filter); 293 294 if (!omitMask) { 295 XRMaskImage mask = x11sdSrc.maskBuffer.getMaskImage(); 296 297 x11sdSrc.validateAsSource(trx, XRUtils.RepeatPad, filter); 298 int maskPicture = mask.prepareBlitMask(x11sdDst, maskTX, width, height); 299 x11sdDst.maskBuffer.con.renderComposite(XRCompositeManager.getInstance(x11sdSrc).getCompRule(), x11sdSrc.picture, maskPicture, x11sdDst.picture, 300 0, 0, 0, 0, bounds.x, bounds.y, bounds.width, bounds.height); 301 } else { 302 int repeat = filter == XRUtils.FAST ? XRUtils.RepeatNone : XRUtils.RepeatPad; 303 304 x11sdSrc.validateAsSource(trx, repeat, filter); 305 x11sdDst.maskBuffer.compositeBlit(x11sdSrc, x11sdDst, 0, 0, bounds.x, bounds.y, bounds.width, bounds.height); 306 } 307 } finally { 308 SunToolkit.awtUnlock(); 309 } 310 } 311 312 /* TODO: Is mask ever omitable??? ... should be for 90 degree rotation and no shear, but we always need to use RepeatPad */ 313 protected static boolean isMaskOmittable(AffineTransform trx, Composite comp, int filter) { 314 return (filter == XRUtils.FAST || trx.getTranslateX() == (int) trx.getTranslateX() /* 315 * If 316 * translate 317 * is 318 * integer 319 * only 320 */ 321 && trx.getTranslateY() == (int) trx.getTranslateY() && (trx.getShearX() == 0 && trx.getShearY() == 0 // Only 322 // 90 degree 323 // rotation 324 || trx.getShearX() == -trx.getShearY())) && ((AlphaComposite) comp).getAlpha() == 1.0f; // No 325 // ExtraAlpha!=1 326 } 327 } 328 329 class XrSwToPMBlit extends Blit { 330 Blit pmToSurfaceBlit; 331 332 XrSwToPMBlit(SurfaceType srcType, SurfaceType dstType) { 333 super(srcType, CompositeType.AnyAlpha, dstType); 334 pmToSurfaceBlit = new XRPMBlit(dstType, dstType); 335 } 336 337 public void Blit(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx, int sy, int dx, int dy, int w, int h) { 338 /* 339 * If the blit is write-only (putimge), no need for a temporary VI. 340 */ 341 if (CompositeType.SrcOverNoEa.equals(comp) && (src.getTransparency() == Transparency.OPAQUE)) { 342 Blit opaqueSwToSurfaceBlit = Blit.getFromCache(src.getSurfaceType(), CompositeType.SrcNoEa, dst.getSurfaceType()); 343 opaqueSwToSurfaceBlit.Blit(src, dst, comp, clip, sx, sy, dx, dy, w, h); 344 } else { 345 try { | 208 * required 209 * : 210 * - 211 * / 212 * ? 213 * ? 214 */ 215 x11sdDst.maskBuffer.compositeBlit(x11sdSrc, x11sdDst, (int) sx1, (int) sy1, (int) dx1, (int) dy1, (int) (dx2 - dx1), (int) (dy2 - dy1)); 216 } finally { 217 SunToolkit.awtUnlock(); 218 } 219 } 220 } 221 222 /** 223 * Called also if scale+transform is set 224 * 225 * @author Clemens Eisserer 226 */ 227 class XRPMTransformedBlit extends TransformBlit { 228 final Rectangle compositeBounds = new Rectangle(); 229 final double[] srcCoords = new double[8]; 230 final double[] dstCoords = new double[8]; 231 232 public XRPMTransformedBlit(SurfaceType srcType, SurfaceType dstType) { 233 super(srcType, CompositeType.AnyAlpha, dstType); 234 } 235 236 /* 237 * Calculates the composite-rectangle required for transformed blits. This 238 * method is functionally equal to: Shape shp = 239 * xform.createTransformedShape(rect); Rectangle bounds = shp.getBounds(); 240 * but performs significantly better. 241 * Returns true if the destination shape is parallel to x/y axis 242 */ 243 protected boolean adjustCompositeBounds(AffineTransform tr, int dstx, int dsty, int width, int height) { 244 srcCoords[0] = dstx; 245 srcCoords[1] = dsty; 246 srcCoords[2] = dstx + width; 247 srcCoords[3] = dsty; 248 srcCoords[4] = dstx + width; 249 srcCoords[5] = dsty + height; 250 srcCoords[6] = dstx; 251 srcCoords[7] = dsty + height; 252 253 tr.transform(srcCoords, 0, dstCoords, 0, 4); 254 255 double minX = Math.min(dstCoords[0], Math.min(dstCoords[2], Math.min(dstCoords[4], dstCoords[6]))); 256 double minY = Math.min(dstCoords[1], Math.min(dstCoords[3], Math.min(dstCoords[5], dstCoords[7]))); 257 double maxX = Math.max(dstCoords[0], Math.max(dstCoords[2], Math.max(dstCoords[4], dstCoords[6]))); 258 double maxY = Math.max(dstCoords[1], Math.max(dstCoords[3], Math.max(dstCoords[5], dstCoords[7]))); 259 260 minX = Math.round(minX); 261 minY = Math.round(minY); 262 maxX = Math.round(maxX); 263 maxY = Math.round(maxY); 264 265 compositeBounds.x = (int) minX; 266 compositeBounds.y = (int) minY; 267 compositeBounds.width = (int) (maxX - minX); 268 compositeBounds.height = (int) (maxY - minY); 269 270 boolean is0or180 = (dstCoords[1] == dstCoords[3]) && (dstCoords[2] == dstCoords[4]); 271 boolean is90or270 = (dstCoords[0] == dstCoords[2]) && (dstCoords[3] == dstCoords[5]); 272 273 return is0or180 || is90or270; 274 } 275 276 public void Transform(SurfaceData src, SurfaceData dst, Composite comp, Region clip, AffineTransform xform, 277 int hint, int srcx, int srcy, int dstx, int dsty, int width, int height) { 278 try { 279 SunToolkit.awtLock(); 280 281 XRSurfaceData x11sdDst = (XRSurfaceData) dst; 282 XRSurfaceData x11sdSrc = (XRSurfaceData) src; 283 284 int filter = XRUtils.ATransOpToXRQuality(hint); 285 boolean isAxisAligned = adjustCompositeBounds(xform, dstx, dsty, width, height); 286 287 x11sdDst.validateAsDestination(null, clip); 288 x11sdDst.maskBuffer.validateCompositeState(comp, null, null, null); 289 290 AffineTransform trx = AffineTransform.getTranslateInstance(-compositeBounds.x, -compositeBounds.y); 291 trx.concatenate(xform); 292 AffineTransform maskTX = (AffineTransform) trx.clone(); 293 trx.translate(-srcx, -srcy); 294 295 try { 296 trx.invert(); 297 } catch (NoninvertibleTransformException ex) { 298 trx.setToIdentity(); 299 } 300 301 boolean omitMask = (filter == XRUtils.FAST) 302 || (isAxisAligned && ((AlphaComposite) comp).getAlpha() == 1.0f); 303 304 if (!omitMask) { 305 XRMaskImage mask = x11sdSrc.maskBuffer.getMaskImage(); 306 307 x11sdSrc.validateAsSource(trx, XRUtils.RepeatPad, filter); 308 int maskPicture = mask.prepareBlitMask(x11sdDst, maskTX, width, height); 309 x11sdDst.maskBuffer.con.renderComposite(XRCompositeManager.getInstance(x11sdSrc).getCompRule(), x11sdSrc.picture, maskPicture, x11sdDst.picture, 310 0, 0, 0, 0, compositeBounds.x, compositeBounds.y, compositeBounds.width, compositeBounds.height); 311 } else { 312 int repeat = filter == XRUtils.FAST ? XRUtils.RepeatNone : XRUtils.RepeatPad; 313 314 x11sdSrc.validateAsSource(trx, repeat, filter); 315 x11sdDst.maskBuffer.compositeBlit(x11sdSrc, x11sdDst, 0, 0, compositeBounds.x, compositeBounds.y, compositeBounds.width, compositeBounds.height); 316 } 317 } finally { 318 SunToolkit.awtUnlock(); 319 } 320 } 321 } 322 323 class XrSwToPMBlit extends Blit { 324 Blit pmToSurfaceBlit; 325 326 XrSwToPMBlit(SurfaceType srcType, SurfaceType dstType) { 327 super(srcType, CompositeType.AnyAlpha, dstType); 328 pmToSurfaceBlit = new XRPMBlit(dstType, dstType); 329 } 330 331 public void Blit(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx, int sy, int dx, int dy, int w, int h) { 332 /* 333 * If the blit is write-only (putimge), no need for a temporary VI. 334 */ 335 if (CompositeType.SrcOverNoEa.equals(comp) && (src.getTransparency() == Transparency.OPAQUE)) { 336 Blit opaqueSwToSurfaceBlit = Blit.getFromCache(src.getSurfaceType(), CompositeType.SrcNoEa, dst.getSurfaceType()); 337 opaqueSwToSurfaceBlit.Blit(src, dst, comp, clip, sx, sy, dx, dy, w, h); 338 } else { 339 try { |