Loading tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java +2 −1 Original line number Diff line number Diff line Loading @@ -499,13 +499,14 @@ public final class Canvas_Delegate { } Rectangle rect = canvasDelegate.getSnapshot().getClip().getBounds(); if (rect != null) { if (rect != null && rect.isEmpty() == false) { bounds.left = rect.x; bounds.top = rect.y; bounds.right = rect.x + rect.width; bounds.bottom = rect.y + rect.height; return true; } return false; } Loading tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java +27 −2 Original line number Diff line number Diff line Loading @@ -69,39 +69,64 @@ public class Region_Delegate { * * If the Op is not one that combines two shapes, then this return null * * @param shape1 the firt shape to combine * @param shape1 the firt shape to combine which can be null if there's no original clip. * @param shape2 the 2nd shape to combine * @param regionOp the operande for the combine * @return a new area or null. */ public static Area combineShapes(Shape shape1, Shape shape2, int regionOp) { if (regionOp == Region.Op.DIFFERENCE.nativeInt) { // if shape1 is null (empty), then the result is null. if (shape1 == null) { return null; } // result is always a new area. Area result = new Area(shape1); result.subtract(shape2 instanceof Area ? (Area) shape2 : new Area(shape2)); return result; } else if (regionOp == Region.Op.INTERSECT.nativeInt) { // if shape1 is null, then the result is simply shape2. if (shape1 == null) { return new Area(shape2); } // result is always a new area. Area result = new Area(shape1); result.intersect(shape2 instanceof Area ? (Area) shape2 : new Area(shape2)); return result; } else if (regionOp == Region.Op.UNION.nativeInt) { // if shape1 is null, then the result is simply shape2. if (shape1 == null) { return new Area(shape2); } // result is always a new area. Area result = new Area(shape1); result.add(shape2 instanceof Area ? (Area) shape2 : new Area(shape2)); return result; } else if (regionOp == Region.Op.XOR.nativeInt) { // if shape1 is null, then the result is simply shape2 if (shape1 == null) { return new Area(shape2); } // result is always a new area. Area result = new Area(shape1); result.exclusiveOr(shape2 instanceof Area ? (Area) shape2 : new Area(shape2)); return result; } else if (regionOp == Region.Op.REVERSE_DIFFERENCE.nativeInt) { // result is always a new area. Area result = new Area(shape2); if (shape1 != null) { result.subtract(shape1 instanceof Area ? (Area) shape1 : new Area(shape1)); } return result; } Loading tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java +58 −11 Original line number Diff line number Diff line Loading @@ -170,6 +170,29 @@ public class GcSnapshot { mBitmap.change(); } } /** * Sets the clip for the graphics2D object associated with the layer. * This should be used over the normal Graphics2D setClip method. * * @param clipShape the shape to use a the clip shape. */ void setClip(Shape clipShape) { // because setClip is only guaranteed to work with rectangle shape, // first reset the clip to max and then intersect the current (empty) // clip with the shap. mGraphics.setClip(null); mGraphics.clip(clipShape); } /** * Clips the layer with the given shape. This performs an intersect between the current * clip shape and the given shape. * @param shape the new clip shape. */ public void clip(Shape shape) { mGraphics.clip(shape); } } /** Loading Loading @@ -287,12 +310,13 @@ public class GcSnapshot { AffineTransform currentMtx = baseLayer.getGraphics().getTransform(); layerGraphics.setTransform(currentMtx); Shape currentClip = baseLayer.getGraphics().getClip(); layerGraphics.setClip(currentClip); // create a new layer for this new layer and add it to the list at the end. mLayers.add(mLocalLayer = new Layer(layerGraphics, layerImage, flags)); // set the clip on it. Shape currentClip = baseLayer.getGraphics().getClip(); mLocalLayer.setClip(currentClip); // if the drawing is not clipped to the local layer only, we save the current content // of all other layers. We are only interested in the part that will actually // be drawn, so we create as small bitmaps as we can. Loading Loading @@ -369,15 +393,24 @@ public class GcSnapshot { */ public void setBitmap(Bitmap_Delegate bitmap) { assert mLayers.size() == 0; // create a new Layer for the bitmap. This will be the base layer. Graphics2D graphics2D = bitmap.getImage().createGraphics(); mLayers.add(new Layer(graphics2D, bitmap)); Layer baseLayer = new Layer(graphics2D, bitmap); // add it to the list. mLayers.add(baseLayer); // if transform and clip where modified before, get the information and give it to the // layer. if (mTransform != null) { graphics2D.setTransform(mTransform); mTransform = null; } if (mClip != null) { graphics2D.setClip(mClip); baseLayer.setClip(mClip); mClip = null; } } Loading Loading @@ -447,7 +480,20 @@ public class GcSnapshot { } public boolean clip(Shape shape, int regionOp) { // Simple case of intersect with existing layers. // Because Graphics2D#setClip works a bit peculiarly, we optimize // the case of clipping by intersection, as it's supported natively. if (regionOp == Region.Op.INTERSECT.nativeInt && mLayers.size() > 0) { for (Layer layer : mLayers) { layer.clip(shape); } Shape currentClip = getClip(); return currentClip != null && currentClip.getBounds().isEmpty() == false; } Area area = null; if (regionOp == Region.Op.REPLACE.nativeInt) { area = new Area(shape); } else { Loading @@ -459,11 +505,12 @@ public class GcSnapshot { if (mLayers.size() > 0) { if (area != null) { for (Layer layer : mLayers) { layer.getGraphics().setClip(area); layer.setClip(area); } } return getClip().getBounds().isEmpty() == false; Shape currentClip = getClip(); return currentClip != null && currentClip.getBounds().isEmpty() == false; } else { if (area != null) { mClip = area; Loading @@ -479,14 +526,14 @@ public class GcSnapshot { return clip(new Rectangle2D.Float(left, top, right - left, bottom - top), regionOp); } /** * Returns the current clip, or null if none have been setup. */ public Shape getClip() { if (mLayers.size() > 0) { // they all have the same clip return mLayers.get(0).getGraphics().getClip(); } else { if (mClip == null) { mClip = new Area(); } return mClip; } } Loading Loading @@ -603,7 +650,7 @@ public class GcSnapshot { if ((mFlags & Canvas.CLIP_SAVE_FLAG) == 0) { Shape clip = getClip(); for (Layer layer : mPrevious.mLayers) { layer.getGraphics().setClip(clip); layer.setClip(clip); } } } Loading Loading
tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java +2 −1 Original line number Diff line number Diff line Loading @@ -499,13 +499,14 @@ public final class Canvas_Delegate { } Rectangle rect = canvasDelegate.getSnapshot().getClip().getBounds(); if (rect != null) { if (rect != null && rect.isEmpty() == false) { bounds.left = rect.x; bounds.top = rect.y; bounds.right = rect.x + rect.width; bounds.bottom = rect.y + rect.height; return true; } return false; } Loading
tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java +27 −2 Original line number Diff line number Diff line Loading @@ -69,39 +69,64 @@ public class Region_Delegate { * * If the Op is not one that combines two shapes, then this return null * * @param shape1 the firt shape to combine * @param shape1 the firt shape to combine which can be null if there's no original clip. * @param shape2 the 2nd shape to combine * @param regionOp the operande for the combine * @return a new area or null. */ public static Area combineShapes(Shape shape1, Shape shape2, int regionOp) { if (regionOp == Region.Op.DIFFERENCE.nativeInt) { // if shape1 is null (empty), then the result is null. if (shape1 == null) { return null; } // result is always a new area. Area result = new Area(shape1); result.subtract(shape2 instanceof Area ? (Area) shape2 : new Area(shape2)); return result; } else if (regionOp == Region.Op.INTERSECT.nativeInt) { // if shape1 is null, then the result is simply shape2. if (shape1 == null) { return new Area(shape2); } // result is always a new area. Area result = new Area(shape1); result.intersect(shape2 instanceof Area ? (Area) shape2 : new Area(shape2)); return result; } else if (regionOp == Region.Op.UNION.nativeInt) { // if shape1 is null, then the result is simply shape2. if (shape1 == null) { return new Area(shape2); } // result is always a new area. Area result = new Area(shape1); result.add(shape2 instanceof Area ? (Area) shape2 : new Area(shape2)); return result; } else if (regionOp == Region.Op.XOR.nativeInt) { // if shape1 is null, then the result is simply shape2 if (shape1 == null) { return new Area(shape2); } // result is always a new area. Area result = new Area(shape1); result.exclusiveOr(shape2 instanceof Area ? (Area) shape2 : new Area(shape2)); return result; } else if (regionOp == Region.Op.REVERSE_DIFFERENCE.nativeInt) { // result is always a new area. Area result = new Area(shape2); if (shape1 != null) { result.subtract(shape1 instanceof Area ? (Area) shape1 : new Area(shape1)); } return result; } Loading
tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java +58 −11 Original line number Diff line number Diff line Loading @@ -170,6 +170,29 @@ public class GcSnapshot { mBitmap.change(); } } /** * Sets the clip for the graphics2D object associated with the layer. * This should be used over the normal Graphics2D setClip method. * * @param clipShape the shape to use a the clip shape. */ void setClip(Shape clipShape) { // because setClip is only guaranteed to work with rectangle shape, // first reset the clip to max and then intersect the current (empty) // clip with the shap. mGraphics.setClip(null); mGraphics.clip(clipShape); } /** * Clips the layer with the given shape. This performs an intersect between the current * clip shape and the given shape. * @param shape the new clip shape. */ public void clip(Shape shape) { mGraphics.clip(shape); } } /** Loading Loading @@ -287,12 +310,13 @@ public class GcSnapshot { AffineTransform currentMtx = baseLayer.getGraphics().getTransform(); layerGraphics.setTransform(currentMtx); Shape currentClip = baseLayer.getGraphics().getClip(); layerGraphics.setClip(currentClip); // create a new layer for this new layer and add it to the list at the end. mLayers.add(mLocalLayer = new Layer(layerGraphics, layerImage, flags)); // set the clip on it. Shape currentClip = baseLayer.getGraphics().getClip(); mLocalLayer.setClip(currentClip); // if the drawing is not clipped to the local layer only, we save the current content // of all other layers. We are only interested in the part that will actually // be drawn, so we create as small bitmaps as we can. Loading Loading @@ -369,15 +393,24 @@ public class GcSnapshot { */ public void setBitmap(Bitmap_Delegate bitmap) { assert mLayers.size() == 0; // create a new Layer for the bitmap. This will be the base layer. Graphics2D graphics2D = bitmap.getImage().createGraphics(); mLayers.add(new Layer(graphics2D, bitmap)); Layer baseLayer = new Layer(graphics2D, bitmap); // add it to the list. mLayers.add(baseLayer); // if transform and clip where modified before, get the information and give it to the // layer. if (mTransform != null) { graphics2D.setTransform(mTransform); mTransform = null; } if (mClip != null) { graphics2D.setClip(mClip); baseLayer.setClip(mClip); mClip = null; } } Loading Loading @@ -447,7 +480,20 @@ public class GcSnapshot { } public boolean clip(Shape shape, int regionOp) { // Simple case of intersect with existing layers. // Because Graphics2D#setClip works a bit peculiarly, we optimize // the case of clipping by intersection, as it's supported natively. if (regionOp == Region.Op.INTERSECT.nativeInt && mLayers.size() > 0) { for (Layer layer : mLayers) { layer.clip(shape); } Shape currentClip = getClip(); return currentClip != null && currentClip.getBounds().isEmpty() == false; } Area area = null; if (regionOp == Region.Op.REPLACE.nativeInt) { area = new Area(shape); } else { Loading @@ -459,11 +505,12 @@ public class GcSnapshot { if (mLayers.size() > 0) { if (area != null) { for (Layer layer : mLayers) { layer.getGraphics().setClip(area); layer.setClip(area); } } return getClip().getBounds().isEmpty() == false; Shape currentClip = getClip(); return currentClip != null && currentClip.getBounds().isEmpty() == false; } else { if (area != null) { mClip = area; Loading @@ -479,14 +526,14 @@ public class GcSnapshot { return clip(new Rectangle2D.Float(left, top, right - left, bottom - top), regionOp); } /** * Returns the current clip, or null if none have been setup. */ public Shape getClip() { if (mLayers.size() > 0) { // they all have the same clip return mLayers.get(0).getGraphics().getClip(); } else { if (mClip == null) { mClip = new Area(); } return mClip; } } Loading Loading @@ -603,7 +650,7 @@ public class GcSnapshot { if ((mFlags & Canvas.CLIP_SAVE_FLAG) == 0) { Shape clip = getClip(); for (Layer layer : mPrevious.mLayers) { layer.getGraphics().setClip(clip); layer.setClip(clip); } } } Loading