161 162 XRSurfaceData x11sdDst = (XRSurfaceData) dst; 163 x11sdDst.validateAsDestination(null, clip); 164 XRSurfaceData x11sdSrc = (XRSurfaceData) src; 165 x11sdSrc.validateAsSource(null, XRUtils.RepeatNone, XRUtils.FAST); 166 167 x11sdDst.maskBuffer.validateCompositeState(comp, null, null, null); 168 169 x11sdDst.maskBuffer.compositeBlit(x11sdSrc, x11sdDst, sx, sy, dx, dy, w, h); 170 } finally { 171 SunToolkit.awtUnlock(); 172 } 173 } 174 } 175 176 class XRPMScaledBlit extends ScaledBlit { 177 public XRPMScaledBlit(SurfaceType srcType, SurfaceType dstType) { 178 super(srcType, CompositeType.AnyAlpha, dstType); 179 } 180 181 /* 182 * TODO: This breaks scales with non-integer coordinates!?!?! 183 */ 184 public void Scale(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx1, int sy1, int sx2, int sy2, double dx1, double dy1, 185 double dx2, double dy2) { 186 try { 187 SunToolkit.awtLock(); 188 189 XRSurfaceData x11sdDst = (XRSurfaceData) dst; 190 x11sdDst.validateAsDestination(null, clip); 191 XRSurfaceData x11sdSrc = (XRSurfaceData) src; 192 x11sdDst.maskBuffer.validateCompositeState(comp, null, null, null); 193 194 double xScale = (dx2 - dx1) / (sx2 - sx1); 195 double yScale = (dy2 - dy1) / (sy2 - sy1); 196 197 sx1 *= xScale; 198 sx2 *= xScale; 199 sy1 *= yScale; 200 sy2 *= yScale; 201 202 AffineTransform xForm = AffineTransform.getScaleInstance(1 / xScale, 1 / yScale); 203 204 x11sdSrc.validateAsSource(xForm, XRUtils.RepeatNone, XRUtils.FAST); /* 205 * TODO: 206 * padded 207 * blit 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 { 340 SunToolkit.awtLock(); 341 342 XRSurfaceData vImgSurface = XRPMBlitLoops.cacheToTmpSurface(src, (XRSurfaceData) dst, w, h, sx, sy); 343 pmToSurfaceBlit.Blit(vImgSurface, dst, comp, clip, 0, 0, dx, dy, w, h); 344 } finally { 345 SunToolkit.awtUnlock(); 346 } 347 } 348 } 349 } 350 351 class XrSwToPMScaledBlit extends ScaledBlit { 352 ScaledBlit pmToSurfaceBlit; 353 354 XrSwToPMScaledBlit(SurfaceType srcType, SurfaceType dstType) { | 161 162 XRSurfaceData x11sdDst = (XRSurfaceData) dst; 163 x11sdDst.validateAsDestination(null, clip); 164 XRSurfaceData x11sdSrc = (XRSurfaceData) src; 165 x11sdSrc.validateAsSource(null, XRUtils.RepeatNone, XRUtils.FAST); 166 167 x11sdDst.maskBuffer.validateCompositeState(comp, null, null, null); 168 169 x11sdDst.maskBuffer.compositeBlit(x11sdSrc, x11sdDst, sx, sy, dx, dy, w, h); 170 } finally { 171 SunToolkit.awtUnlock(); 172 } 173 } 174 } 175 176 class XRPMScaledBlit extends ScaledBlit { 177 public XRPMScaledBlit(SurfaceType srcType, SurfaceType dstType) { 178 super(srcType, CompositeType.AnyAlpha, dstType); 179 } 180 181 public void Scale(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx1, int sy1, int sx2, int sy2, double dx1, double dy1, 182 double dx2, double dy2) { 183 try { 184 SunToolkit.awtLock(); 185 186 XRSurfaceData x11sdDst = (XRSurfaceData) dst; 187 x11sdDst.validateAsDestination(null, clip); 188 XRSurfaceData x11sdSrc = (XRSurfaceData) src; 189 x11sdDst.maskBuffer.validateCompositeState(comp, null, null, null); 190 191 double xScale = (dx2 - dx1) / (sx2 - sx1); 192 double yScale = (dy2 - dy1) / (sy2 - sy1); 193 194 sx1 *= xScale; 195 sx2 *= xScale; 196 sy1 *= yScale; 197 sy2 *= yScale; 198 199 dx1 = Math.ceil(dx1 - 0.5); 200 dy1 = Math.ceil(dy1 - 0.5); 201 dx2 = Math.ceil(dx2 - 0.5); 202 dy2 = Math.ceil(dy2 - 0.5); 203 204 AffineTransform xForm = AffineTransform.getScaleInstance(1 / xScale, 1 / yScale); 205 206 x11sdSrc.validateAsSource(xForm, XRUtils.RepeatNone, XRUtils.FAST); 207 x11sdDst.maskBuffer.compositeBlit(x11sdSrc, x11sdDst, (int) sx1, (int) sy1, (int) dx1, (int) dy1, (int) (dx2 - dx1), (int) (dy2 - dy1)); 208 } finally { 209 SunToolkit.awtUnlock(); 210 } 211 } 212 } 213 214 /** 215 * Called also if scale+transform is set 216 * 217 * @author Clemens Eisserer 218 */ 219 class XRPMTransformedBlit extends TransformBlit { 220 final Rectangle compositeBounds = new Rectangle(); 221 final double[] srcCoords = new double[8]; 222 final double[] dstCoords = new double[8]; 223 224 public XRPMTransformedBlit(SurfaceType srcType, SurfaceType dstType) { 225 super(srcType, CompositeType.AnyAlpha, dstType); 226 } 227 228 /* 229 * Calculates the composition-rectangle required for transformed blits. 230 * For composite operations where the composition-rectangle defines 231 * the modified destination area, coordinates are rounded. 232 * Otherwise the composition window rectangle is sized large enough 233 * to not clip away any pixels. 234 */ 235 protected void adjustCompositeBounds(boolean isQuadrantRotated, AffineTransform tr, 236 int dstx, int dsty, int width, int height) { 237 srcCoords[0] = dstx; 238 srcCoords[1] = dsty; 239 srcCoords[2] = dstx + width; 240 srcCoords[3] = dsty + height; 241 242 double minX, minY, maxX, maxY; 243 if (isQuadrantRotated) { 244 tr.transform(srcCoords, 0, dstCoords, 0, 2); 245 246 minX = Math.min(dstCoords[0], dstCoords[2]); 247 minY = Math.min(dstCoords[1], dstCoords[3]); 248 maxX = Math.max(dstCoords[0], dstCoords[2]); 249 maxY = Math.max(dstCoords[1], dstCoords[3]); 250 251 minX = Math.ceil(minX - 0.5); 252 minY = Math.ceil(minY - 0.5); 253 maxX = Math.ceil(maxX - 0.5); 254 maxY = Math.ceil(maxY - 0.5); 255 } else { 256 srcCoords[4] = dstx; 257 srcCoords[5] = dsty + height; 258 srcCoords[6] = dstx + width; 259 srcCoords[7] = dsty; 260 261 tr.transform(srcCoords, 0, dstCoords, 0, 4); 262 263 minX = Math.min(dstCoords[0], Math.min(dstCoords[2], Math.min(dstCoords[4], dstCoords[6]))); 264 minY = Math.min(dstCoords[1], Math.min(dstCoords[3], Math.min(dstCoords[5], dstCoords[7]))); 265 maxX = Math.max(dstCoords[0], Math.max(dstCoords[2], Math.max(dstCoords[4], dstCoords[6]))); 266 maxY = Math.max(dstCoords[1], Math.max(dstCoords[3], Math.max(dstCoords[5], dstCoords[7]))); 267 268 minX = Math.floor(minX); 269 minY = Math.floor(minY); 270 maxX = Math.ceil(maxX); 271 maxY = Math.ceil(maxY); 272 } 273 274 compositeBounds.x = (int) minX; 275 compositeBounds.y = (int) minY; 276 compositeBounds.width = (int) (maxX - minX); 277 compositeBounds.height = (int) (maxY - minY); 278 } 279 280 public void Transform(SurfaceData src, SurfaceData dst, Composite comp, Region clip, AffineTransform xform, 281 int hint, int srcx, int srcy, int dstx, int dsty, int width, int height) { 282 try { 283 SunToolkit.awtLock(); 284 285 XRSurfaceData x11sdDst = (XRSurfaceData) dst; 286 XRSurfaceData x11sdSrc = (XRSurfaceData) src; 287 XRCompositeManager xrMgr = XRCompositeManager.getInstance(x11sdSrc); 288 289 float extraAlpha = ((AlphaComposite) comp).getAlpha(); 290 int filter = XRUtils.ATransOpToXRQuality(hint); 291 boolean isQuadrantRotated = XRUtils.isTransformQuadrantRotated(xform); 292 293 adjustCompositeBounds(isQuadrantRotated, xform, dstx, dsty, width, height); 294 295 x11sdDst.validateAsDestination(null, clip); 296 x11sdDst.maskBuffer.validateCompositeState(comp, null, null, null); 297 298 AffineTransform trx = AffineTransform.getTranslateInstance(-compositeBounds.x, -compositeBounds.y); 299 trx.concatenate(xform); 300 AffineTransform maskTX = (AffineTransform) trx.clone(); 301 trx.translate(-srcx, -srcy); 302 303 try { 304 trx.invert(); 305 } catch (NoninvertibleTransformException ex) { 306 trx.setToIdentity(); 307 } 308 309 if (filter != XRUtils.FAST && (!isQuadrantRotated || extraAlpha != 1.0f)) { 310 XRMaskImage mask = x11sdSrc.maskBuffer.getMaskImage(); 311 312 // For quadrant-transformed blits geometry is not stored inside the mask 313 // therefore we can use a repeating 1x1 mask for applying extra alpha. 314 int maskPicture = isQuadrantRotated ? xrMgr.getExtraAlphaMask() 315 : mask.prepareBlitMask(x11sdDst, maskTX, width, height); 316 317 x11sdSrc.validateAsSource(trx, XRUtils.RepeatPad, filter); 318 x11sdDst.maskBuffer.con.renderComposite(xrMgr.getCompRule(), x11sdSrc.picture, 319 maskPicture, x11sdDst.picture, 0, 0, 0, 0, compositeBounds.x, compositeBounds.y, 320 compositeBounds.width, compositeBounds.height); 321 } else { 322 int repeat = filter == XRUtils.FAST ? XRUtils.RepeatNone : XRUtils.RepeatPad; 323 324 x11sdSrc.validateAsSource(trx, repeat, filter); 325 326 // compositeBlit takes care of extra alpha 327 x11sdDst.maskBuffer.compositeBlit(x11sdSrc, x11sdDst, 0, 0, compositeBounds.x, 328 compositeBounds.y, compositeBounds.width, compositeBounds.height); 329 } 330 } finally { 331 SunToolkit.awtUnlock(); 332 } 333 } 334 } 335 336 class XrSwToPMBlit extends Blit { 337 Blit pmToSurfaceBlit; 338 339 XrSwToPMBlit(SurfaceType srcType, SurfaceType dstType) { 340 super(srcType, CompositeType.AnyAlpha, dstType); 341 pmToSurfaceBlit = new XRPMBlit(dstType, dstType); 342 } 343 344 public void Blit(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx, int sy, int dx, int dy, int w, int h) { 345 // If the blit is write-only (putimge), no need for a temporary VI. 346 if (CompositeType.SrcOverNoEa.equals(comp) && (src.getTransparency() == Transparency.OPAQUE)) { 347 Blit opaqueSwToSurfaceBlit = Blit.getFromCache(src.getSurfaceType(), CompositeType.SrcNoEa, dst.getSurfaceType()); 348 opaqueSwToSurfaceBlit.Blit(src, dst, comp, clip, sx, sy, dx, dy, w, h); 349 } else { 350 try { 351 SunToolkit.awtLock(); 352 353 XRSurfaceData vImgSurface = XRPMBlitLoops.cacheToTmpSurface(src, (XRSurfaceData) dst, w, h, sx, sy); 354 pmToSurfaceBlit.Blit(vImgSurface, dst, comp, clip, 0, 0, dx, dy, w, h); 355 } finally { 356 SunToolkit.awtUnlock(); 357 } 358 } 359 } 360 } 361 362 class XrSwToPMScaledBlit extends ScaledBlit { 363 ScaledBlit pmToSurfaceBlit; 364 365 XrSwToPMScaledBlit(SurfaceType srcType, SurfaceType dstType) { |