} } private void doCopyArea(int x, int y, int w, int h, int dx, int dy) { if (w <= 0 || h <= 0) { return; } SurfaceData theData = surfaceData; if (theData.copyArea(this, x, y, w, h, dx, dy)) { return; } if (transformState >= TRANSFORM_TRANSLATESCALE) { throw new InternalError("transformed copyArea not implemented yet"); } // REMIND: This method does not deal with missing data from the // source object (i.e. it does not send exposure events...) Region clip = getCompClip(); Composite comp = composite; if (lastCAcomp != comp) { SurfaceType dsttype = theData.getSurfaceType(); CompositeType comptype = imageComp; if (CompositeType.SrcOverNoEa.equals(comptype) && theData.getTransparency() == Transparency.OPAQUE) { comptype = CompositeType.SrcNoEa; } lastCAblit = Blit.locate(dsttype, comptype, dsttype); lastCAcomp = comp; } x += transX; y += transY; Blit ob = lastCAblit; if (dy == 0 && dx > 0 && dx < w) { while (w > 0) { int partW = Math.min(w, dx); w -= partW; int sx = x + w; ob.Blit(theData, theData, comp, clip, sx, y, sx+dx, y+dy, partW, h); } return; } if (dy > 0 && dy < h && dx > -w && dx < w) { while (h > 0) { int partH = Math.min(h, dy); h -= partH; int sy = y + h; ob.Blit(theData, theData, comp, clip, x, sy, x+dx, sy+dy, w, partH); } return; } ob.Blit(theData, theData, comp, clip, x, y, x+dx, y+dy, w, h); } /* public void XcopyArea(int x, int y, int w, int h, int dx, int dy) { Rectangle rect = new Rectangle(x, y, w, h); rect = transformBounds(rect, transform); Point2D point = new Point2D.Float(dx, dy); Point2D root = new Point2D.Float(0, 0); point = transform.transform(point, point); root = transform.transform(root, root); int fdx = (int)(point.getX()-root.getX()); int fdy = (int)(point.getY()-root.getY()); Rectangle r = getCompBounds().intersection(rect.getBounds()); if (r.isEmpty()) { return; } // Begin Rasterizer for Clip Shape boolean skipClip = true; byte[] clipAlpha = null; if (clipState == CLIP_SHAPE) { int box[] = new int[4]; clipRegion.getBounds(box); Rectangle devR = new Rectangle(box[0], box[1], box[2] - box[0], box[3] - box[1]); if (!devR.isEmpty()) { OutputManager mgr = getOutputManager(); RegionIterator ri = clipRegion.getIterator(); while (ri.nextYRange(box)) { int spany = box[1]; int spanh = box[3] - spany; while (ri.nextXBand(box)) { int spanx = box[0]; int spanw = box[2] - spanx; mgr.copyArea(this, null, spanw, 0, spanx, spany, spanw, spanh, fdx, fdy, null); } } } return; } // End Rasterizer for Clip Shape getOutputManager().copyArea(this, null, r.width, 0, r.x, r.y, r.width, r.height, fdx, fdy, null); } */ public void drawLine(int x1, int y1, int x2, int y2) { try { drawpipe.drawLine(this, x1, y1, x2, y2); } catch (InvalidPipeException e) { revalidateAll(); try { drawpipe.drawLine(this, x1, y1, x2, y2); } catch (InvalidPipeException e2) { // Still catching the exception; we are not yet ready to // validate the surfaceData correctly. Fail for now and // try again next time around. } } finally { surfaceData.markDirty(); } } public void drawRoundRect(int x, int y, int w, int h, int arcW, int arcH) { try { drawpipe.drawRoundRect(this, x, y, w, h, arcW, arcH); } catch (InvalidPipeException e) { revalidateAll(); try { drawpipe.drawRoundRect(this, x, y, w, h, arcW, arcH); } catch (InvalidPipeException e2) { // Still catching the exception; we are not yet ready to // validate the surfaceData correctly. Fail for now and // try again next time around. } } finally { surfaceData.markDirty(); } } public void fillRoundRect(int x, int y, int w, int h, int arcW, int arcH) { try { fillpipe.fillRoundRect(this, x, y, w, h, arcW, arcH); } catch (InvalidPipeException e) { revalidateAll(); try { fillpipe.fillRoundRect(this, x, y, w, h, arcW, arcH); } catch (InvalidPipeException e2) { // Still catching the exception; we are not yet ready to // validate the surfaceData correctly. Fail for now and // try again next time around. } } finally { surfaceData.markDirty(); } } public void drawOval(int x, int y, int w, int h) { try { drawpipe.drawOval(this, x, y, w, h); } catch (InvalidPipeException e) { revalidateAll(); try { drawpipe.drawOval(this, x, y, w, h); } catch (InvalidPipeException e2) { // Still catching the exception; we are not yet ready to // validate the surfaceData correctly. Fail for now and // try again next time around. } } finally { surfaceData.markDirty(); } } public void fillOval(int x, int y, int w, int h) { try { fillpipe.fillOval(this, x, y, w, h); } catch (InvalidPipeException e) { revalidateAll(); try { fillpipe.fillOval(this, x, y, w, h); } catch (InvalidPipeException e2) { // Still catching the exception; we are not yet ready to // validate the surfaceData correctly. Fail for now and // try again next time around. } } finally { surfaceData.markDirty(); } } public void drawArc(int x, int y, int w, int h, int startAngl, int arcAngl) { try { drawpipe.drawArc(this, x, y, w, h, startAngl, arcAngl); } catch (InvalidPipeException e) { revalidateAll(); try { drawpipe.drawArc(this, x, y, w, h, startAngl, arcAngl); } catch (InvalidPipeException e2) { // Still catching the exception; we are not yet ready to // validate the surfaceData correctly. Fail for now and // try again next time around. } } finally { surfaceData.markDirty(); } } public void fillArc(int x, int y, int w, int h, int startAngl, int arcAngl) { try { fillpipe.fillArc(this, x, y, w, h, startAngl, arcAngl); } catch (InvalidPipeException e) { revalidateAll(); try { fillpipe.fillArc(this, x, y, w, h, startAngl, arcAngl); } catch (InvalidPipeException e2) { // Still catching the exception; we are not yet ready to // validate the surfaceData correctly. Fail for now and // try again next time around. } } finally { surfaceData.markDirty(); } } public void drawPolyline(int xPoints[], int yPoints[], int nPoints) { try { drawpipe.drawPolyline(this, xPoints, yPoints, nPoints); } catch (InvalidPipeException e) { revalidateAll(); try { drawpipe.drawPolyline(this, xPoints, yPoints, nPoints); } catch (InvalidPipeException e2) { // Still catching the exception; we are not yet ready to // validate the surfaceData correctly. Fail for now and // try again next time around. } } finally { surfaceData.markDirty(); } } public void drawPolygon(int xPoints[], int yPoints[], int nPoints) { try { drawpipe.drawPolygon(this, xPoints, yPoints, nPoints); } catch (InvalidPipeException e) { revalidateAll(); try { drawpipe.drawPolygon(this, xPoints, yPoints, nPoints); } catch (InvalidPipeException e2) { // Still catching the exception; we are not yet ready to // validate the surfaceData correctly. Fail for now and // try again next time around. } } finally { surfaceData.markDirty(); } } public void fillPolygon(int xPoints[], int yPoints[], int nPoints) { try { fillpipe.fillPolygon(this, xPoints, yPoints, nPoints); } catch (InvalidPipeException e) { revalidateAll(); try { fillpipe.fillPolygon(this, xPoints, yPoints, nPoints); } catch (InvalidPipeException e2) { // Still catching the exception; we are not yet ready to // validate the surfaceData correctly. Fail for now and // try again next time around. } } finally { surfaceData.markDirty(); } } public void drawRect (int x, int y, int w, int h) { try { drawpipe.drawRect(this, x, y, w, h); } catch (InvalidPipeException e) { revalidateAll(); try { drawpipe.drawRect(this, x, y, w, h); } catch (InvalidPipeException e2) { // Still catching the exception; we are not yet ready to // validate the surfaceData correctly. Fail for now and // try again next time around. } } finally { surfaceData.markDirty(); } } public void fillRect (int x, int y, int w, int h) { try { fillpipe.fillRect(this, x, y, w, h); } catch (InvalidPipeException e) { revalidateAll(); try { fillpipe.fillRect(this, x, y, w, h); } catch (InvalidPipeException e2) { // Still catching the exception; we are not yet ready to // validate the surfaceData correctly. Fail for now and // try again next time around. } } finally { surfaceData.markDirty(); } } private void revalidateAll() { try { // REMIND: This locking needs to be done around the // caller of this method so that the pipe stays valid // long enough to call the new primitive. // REMIND: No locking yet in screen SurfaceData objects! // surfaceData.lock(); surfaceData = surfaceData.getReplacement(); if (surfaceData == null) { surfaceData = NullSurfaceData.theInstance; } // this will recalculate the composite clip setDevClip(surfaceData.getBounds()); if (paintState <= PAINT_ALPHACOLOR) { validateColor(); } if (composite instanceof XORComposite) { Color c = ((XORComposite) composite).getXorColor(); setComposite(new XORComposite(c, surfaceData)); } validatePipe(); } finally { // REMIND: No locking yet in screen SurfaceData objects! // surfaceData.unlock(); } } public void clearRect(int x, int y, int w, int h) { // REMIND: has some "interesting" consequences if threads are // not synchronized Composite c = composite; Paint p = paint; setComposite(AlphaComposite.Src); setColor(getBackground()); validatePipe(); fillRect(x, y, w, h); setPaint(p); setComposite(c); } /** * Strokes the outline of a Path using the settings of the current * graphics state. The rendering attributes applied include the * clip, transform, paint or color, composite and stroke attributes. * @param p The path to be drawn. * @see #setStroke * @see #setPaint * @see java.awt.Graphics#setColor * @see #transform * @see #setTransform * @see #clip * @see #setClip * @see #setComposite */ public void draw(Shape s) { try { shapepipe.draw(this, s); } catch (InvalidPipeException e) { revalidateAll(); try { shapepipe.draw(this, s); } catch (InvalidPipeException e2) { // Still catching the exception; we are not yet ready to // validate the surfaceData correctly. Fail for now and // try again next time around. } } finally { surfaceData.markDirty(); } } /** * Fills the interior of a Path using the settings of the current * graphics state. The rendering attributes applied include the * clip, transform, paint or color, and composite. * @see #setPaint * @see java.awt.Graphics#setColor * @see #transform * @see #setTransform * @see #setComposite * @see #clip * @see #setClip */ public void fill(Shape s) { try { shapepipe.fill(this, s); } catch (InvalidPipeException e) { revalidateAll(); try { shapepipe.fill(this, s); } catch (InvalidPipeException e2) { // Still catching the exception; we are not yet ready to // validate the surfaceData correctly. Fail for now and // try again next time around. } } finally { surfaceData.markDirty(); } } /** * Returns true if the given AffineTransform is an integer * translation. */ private static boolean isIntegerTranslation(AffineTransform xform) { if (xform.isIdentity()) { return true; } if (xform.getType() == AffineTransform.TYPE_TRANSLATION) { double tx = xform.getTranslateX(); double ty = xform.getTranslateY(); return (tx == (int)tx && ty == (int)ty); } return false; } /** * Returns the index of the tile corresponding to the supplied position * given the tile grid offset and size along the same axis. */ private static int getTileIndex(int p, int tileGridOffset, int tileSize) { p -= tileGridOffset; if (p < 0) { p += 1 - tileSize; // force round to -infinity (ceiling) } return p/tileSize; } /** * Returns a rectangle in image coordinates that may be required * in order to draw the given image into the given clipping region * through a pair of AffineTransforms. In addition, horizontal and * vertical padding factors for antialising and interpolation may * be used. */ private static Rectangle getImageRegion(RenderedImage img, Region compClip, AffineTransform transform, AffineTransform xform, int padX, int padY) { Rectangle imageRect = new Rectangle(img.getMinX(), img.getMinY(), img.getWidth(), img.getHeight()); Rectangle result = null; try { double p[] = new double[8]; p[0] = p[2] = compClip.getLoX(); p[4] = p[6] = compClip.getHiX(); p[1] = p[5] = compClip.getLoY(); p[3] = p[7] = compClip.getHiY(); // Inverse transform the output bounding rect transform.inverseTransform(p, 0, p, 0, 4); xform.inverseTransform(p, 0, p, 0, 4); // Determine a bounding box for the inverse transformed region double x0,x1,y0,y1; x0 = x1 = p[0]; y0 = y1 = p[1]; for (int i = 2; i < 8; ) { double pt = p[i++]; if (pt < x0) { x0 = pt; } else if (pt > x1) { x1 = pt; } pt = p[i++]; if (pt < y0) { y0 = pt; } else if (pt > y1) { y1 = pt;Lines 2001–2500 of 3310. Previous lines Load more
} } private void doCopyArea(int x, int y, int w, int h, int dx, int dy) { if (w <= 0 || h <= 0) { return; } SurfaceData theData = surfaceData; if (theData.copyArea(this, x, y, w, h, dx, dy)) { return; } if (transformState >= TRANSFORM_TRANSLATESCALE) { throw new InternalError("transformed copyArea not implemented yet"); } // REMIND: This method does not deal with missing data from the // source object (i.e. it does not send exposure events...) Region clip = getCompClip(); Composite comp = composite; if (lastCAcomp != comp) { SurfaceType dsttype = theData.getSurfaceType(); CompositeType comptype = imageComp; if (CompositeType.SrcOverNoEa.equals(comptype) && theData.getTransparency() == Transparency.OPAQUE) { comptype = CompositeType.SrcNoEa; } lastCAblit = Blit.locate(dsttype, comptype, dsttype); lastCAcomp = comp; } x += transX; y += transY; Blit ob = lastCAblit; if (dy == 0 && dx > 0 && dx < w) { while (w > 0) { int partW = Math.min(w, dx); w -= partW; int sx = x + w; ob.Blit(theData, theData, comp, clip, sx, y, sx+dx, y+dy, partW, h); } return; } if (dy > 0 && dy < h && dx > -w && dx < w) { while (h > 0) { int partH = Math.min(h, dy); h -= partH; int sy = y + h; ob.Blit(theData, theData, comp, clip, x, sy, x+dx, sy+dy, w, partH); } return; } ob.Blit(theData, theData, comp, clip, x, y, x+dx, y+dy, w, h); } /* public void XcopyArea(int x, int y, int w, int h, int dx, int dy) { Rectangle rect = new Rectangle(x, y, w, h); rect = transformBounds(rect, transform); Point2D point = new Point2D.Float(dx, dy); Point2D root = new Point2D.Float(0, 0); point = transform.transform(point, point); root = transform.transform(root, root); int fdx = (int)(point.getX()-root.getX()); int fdy = (int)(point.getY()-root.getY()); Rectangle r = getCompBounds().intersection(rect.getBounds()); if (r.isEmpty()) { return; } // Begin Rasterizer for Clip Shape boolean skipClip = true; byte[] clipAlpha = null; if (clipState == CLIP_SHAPE) { int box[] = new int[4]; clipRegion.getBounds(box); Rectangle devR = new Rectangle(box[0], box[1], box[2] - box[0], box[3] - box[1]); if (!devR.isEmpty()) { OutputManager mgr = getOutputManager(); RegionIterator ri = clipRegion.getIterator(); while (ri.nextYRange(box)) { int spany = box[1]; int spanh = box[3] - spany; while (ri.nextXBand(box)) { int spanx = box[0]; int spanw = box[2] - spanx; mgr.copyArea(this, null, spanw, 0, spanx, spany, spanw, spanh, fdx, fdy, null); } } } return; } // End Rasterizer for Clip Shape getOutputManager().copyArea(this, null, r.width, 0, r.x, r.y, r.width, r.height, fdx, fdy, null); } */ public void drawLine(int x1, int y1, int x2, int y2) { try { drawpipe.drawLine(this, x1, y1, x2, y2); } catch (InvalidPipeException e) { revalidateAll(); try { drawpipe.drawLine(this, x1, y1, x2, y2); } catch (InvalidPipeException e2) { // Still catching the exception; we are not yet ready to // validate the surfaceData correctly. Fail for now and // try again next time around. } } finally { surfaceData.markDirty(); } } public void drawRoundRect(int x, int y, int w, int h, int arcW, int arcH) { try { drawpipe.drawRoundRect(this, x, y, w, h, arcW, arcH); } catch (InvalidPipeException e) { revalidateAll(); try { drawpipe.drawRoundRect(this, x, y, w, h, arcW, arcH); } catch (InvalidPipeException e2) { // Still catching the exception; we are not yet ready to // validate the surfaceData correctly. Fail for now and // try again next time around. } } finally { surfaceData.markDirty(); } } public void fillRoundRect(int x, int y, int w, int h, int arcW, int arcH) { try { fillpipe.fillRoundRect(this, x, y, w, h, arcW, arcH); } catch (InvalidPipeException e) { revalidateAll(); try { fillpipe.fillRoundRect(this, x, y, w, h, arcW, arcH); } catch (InvalidPipeException e2) { // Still catching the exception; we are not yet ready to // validate the surfaceData correctly. Fail for now and // try again next time around. } } finally { surfaceData.markDirty(); } } public void drawOval(int x, int y, int w, int h) { try { drawpipe.drawOval(this, x, y, w, h); } catch (InvalidPipeException e) { revalidateAll(); try { drawpipe.drawOval(this, x, y, w, h); } catch (InvalidPipeException e2) { // Still catching the exception; we are not yet ready to // validate the surfaceData correctly. Fail for now and // try again next time around. } } finally { surfaceData.markDirty(); } } public void fillOval(int x, int y, int w, int h) { try { fillpipe.fillOval(this, x, y, w, h); } catch (InvalidPipeException e) { revalidateAll(); try { fillpipe.fillOval(this, x, y, w, h); } catch (InvalidPipeException e2) { // Still catching the exception; we are not yet ready to // validate the surfaceData correctly. Fail for now and // try again next time around. } } finally { surfaceData.markDirty(); } } public void drawArc(int x, int y, int w, int h, int startAngl, int arcAngl) { try { drawpipe.drawArc(this, x, y, w, h, startAngl, arcAngl); } catch (InvalidPipeException e) { revalidateAll(); try { drawpipe.drawArc(this, x, y, w, h, startAngl, arcAngl); } catch (InvalidPipeException e2) { // Still catching the exception; we are not yet ready to // validate the surfaceData correctly. Fail for now and // try again next time around. } } finally { surfaceData.markDirty(); } } public void fillArc(int x, int y, int w, int h, int startAngl, int arcAngl) { try { fillpipe.fillArc(this, x, y, w, h, startAngl, arcAngl); } catch (InvalidPipeException e) { revalidateAll(); try { fillpipe.fillArc(this, x, y, w, h, startAngl, arcAngl); } catch (InvalidPipeException e2) { // Still catching the exception; we are not yet ready to // validate the surfaceData correctly. Fail for now and // try again next time around. } } finally { surfaceData.markDirty(); } } public void drawPolyline(int xPoints[], int yPoints[], int nPoints) { try { drawpipe.drawPolyline(this, xPoints, yPoints, nPoints); } catch (InvalidPipeException e) { revalidateAll(); try { drawpipe.drawPolyline(this, xPoints, yPoints, nPoints); } catch (InvalidPipeException e2) { // Still catching the exception; we are not yet ready to // validate the surfaceData correctly. Fail for now and // try again next time around. } } finally { surfaceData.markDirty(); } } public void drawPolygon(int xPoints[], int yPoints[], int nPoints) { try { drawpipe.drawPolygon(this, xPoints, yPoints, nPoints); } catch (InvalidPipeException e) { revalidateAll(); try { drawpipe.drawPolygon(this, xPoints, yPoints, nPoints); } catch (InvalidPipeException e2) { // Still catching the exception; we are not yet ready to // validate the surfaceData correctly. Fail for now and // try again next time around. } } finally { surfaceData.markDirty(); } } public void fillPolygon(int xPoints[], int yPoints[], int nPoints) { try { fillpipe.fillPolygon(this, xPoints, yPoints, nPoints); } catch (InvalidPipeException e) { revalidateAll(); try { fillpipe.fillPolygon(this, xPoints, yPoints, nPoints); } catch (InvalidPipeException e2) { // Still catching the exception; we are not yet ready to // validate the surfaceData correctly. Fail for now and // try again next time around. } } finally { surfaceData.markDirty(); } } public void drawRect (int x, int y, int w, int h) { try { drawpipe.drawRect(this, x, y, w, h); } catch (InvalidPipeException e) { revalidateAll(); try { drawpipe.drawRect(this, x, y, w, h); } catch (InvalidPipeException e2) { // Still catching the exception; we are not yet ready to // validate the surfaceData correctly. Fail for now and // try again next time around. } } finally { surfaceData.markDirty(); } } public void fillRect (int x, int y, int w, int h) { try { fillpipe.fillRect(this, x, y, w, h); } catch (InvalidPipeException e) { revalidateAll(); try { fillpipe.fillRect(this, x, y, w, h); } catch (InvalidPipeException e2) { // Still catching the exception; we are not yet ready to // validate the surfaceData correctly. Fail for now and // try again next time around. } } finally { surfaceData.markDirty(); } } private void revalidateAll() { try { // REMIND: This locking needs to be done around the // caller of this method so that the pipe stays valid // long enough to call the new primitive. // REMIND: No locking yet in screen SurfaceData objects! // surfaceData.lock(); surfaceData = surfaceData.getReplacement(); if (surfaceData == null) { surfaceData = NullSurfaceData.theInstance; } // this will recalculate the composite clip setDevClip(surfaceData.getBounds()); if (paintState <= PAINT_ALPHACOLOR) { validateColor(); } if (composite instanceof XORComposite) { Color c = ((XORComposite) composite).getXorColor(); setComposite(new XORComposite(c, surfaceData)); } validatePipe(); } finally { // REMIND: No locking yet in screen SurfaceData objects! // surfaceData.unlock(); } } public void clearRect(int x, int y, int w, int h) { // REMIND: has some "interesting" consequences if threads are // not synchronized Composite c = composite; Paint p = paint; setComposite(AlphaComposite.Src); setColor(getBackground()); validatePipe(); fillRect(x, y, w, h); setPaint(p); setComposite(c); } /** * Strokes the outline of a Path using the settings of the current * graphics state. The rendering attributes applied include the * clip, transform, paint or color, composite and stroke attributes. * @param p The path to be drawn. * @see #setStroke * @see #setPaint * @see java.awt.Graphics#setColor * @see #transform * @see #setTransform * @see #clip * @see #setClip * @see #setComposite */ public void draw(Shape s) { try { shapepipe.draw(this, s); } catch (InvalidPipeException e) { revalidateAll(); try { shapepipe.draw(this, s); } catch (InvalidPipeException e2) { // Still catching the exception; we are not yet ready to // validate the surfaceData correctly. Fail for now and // try again next time around. } } finally { surfaceData.markDirty(); } } /** * Fills the interior of a Path using the settings of the current * graphics state. The rendering attributes applied include the * clip, transform, paint or color, and composite. * @see #setPaint * @see java.awt.Graphics#setColor * @see #transform * @see #setTransform * @see #setComposite * @see #clip * @see #setClip */ public void fill(Shape s) { try { shapepipe.fill(this, s); } catch (InvalidPipeException e) { revalidateAll(); try { shapepipe.fill(this, s); } catch (InvalidPipeException e2) { // Still catching the exception; we are not yet ready to // validate the surfaceData correctly. Fail for now and // try again next time around. } } finally { surfaceData.markDirty(); } } /** * Returns true if the given AffineTransform is an integer * translation. */ private static boolean isIntegerTranslation(AffineTransform xform) { if (xform.isIdentity()) { return true; } if (xform.getType() == AffineTransform.TYPE_TRANSLATION) { double tx = xform.getTranslateX(); double ty = xform.getTranslateY(); return (tx == (int)tx && ty == (int)ty); } return false; } /** * Returns the index of the tile corresponding to the supplied position * given the tile grid offset and size along the same axis. */ private static int getTileIndex(int p, int tileGridOffset, int tileSize) { p -= tileGridOffset; if (p < 0) { p += 1 - tileSize; // force round to -infinity (ceiling) } return p/tileSize; } /** * Returns a rectangle in image coordinates that may be required * in order to draw the given image into the given clipping region * through a pair of AffineTransforms. In addition, horizontal and * vertical padding factors for antialising and interpolation may * be used. */ private static Rectangle getImageRegion(RenderedImage img, Region compClip, AffineTransform transform, AffineTransform xform, int padX, int padY) { Rectangle imageRect = new Rectangle(img.getMinX(), img.getMinY(), img.getWidth(), img.getHeight()); Rectangle result = null; try { double p[] = new double[8]; p[0] = p[2] = compClip.getLoX(); p[4] = p[6] = compClip.getHiX(); p[1] = p[5] = compClip.getLoY(); p[3] = p[7] = compClip.getHiY(); // Inverse transform the output bounding rect transform.inverseTransform(p, 0, p, 0, 4); xform.inverseTransform(p, 0, p, 0, 4); // Determine a bounding box for the inverse transformed region double x0,x1,y0,y1; x0 = x1 = p[0]; y0 = y1 = p[1]; for (int i = 2; i < 8; ) { double pt = p[i++]; if (pt < x0) { x0 = pt; } else if (pt > x1) { x1 = pt; } pt = p[i++]; if (pt < y0) { y0 = pt; } else if (pt > y1) { y1 = pt;