summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorXavier Ducrohet <xav@android.com>2011-01-06 15:50:42 -0800
committerXavier Ducrohet <xav@android.com>2011-01-06 18:13:49 -0800
commita7cac5e0542779cadf0f5ccf71584e4b4425f7a6 (patch)
tree3a58441f7362a9e2b03afec07fe9f669da9a828d /tools
parentadba8021cd2fd0d20856fb4fbfed2cb000f3f1d5 (diff)
downloadframeworks_base-a7cac5e0542779cadf0f5ccf71584e4b4425f7a6.zip
frameworks_base-a7cac5e0542779cadf0f5ccf71584e4b4425f7a6.tar.gz
frameworks_base-a7cac5e0542779cadf0f5ccf71584e4b4425f7a6.tar.bz2
LayoutLib: fix clipping issues.
There were two issues: - Graphics2D.setClip only works on rectangular shapes. This means doing a setClip on a non rectangular shape should basically reset the clip and intersect with the new shape. - the current clip can be null, so the combineShape method must handle it. Change-Id: Id2cd7475e991d8b533ff2e8850cc2c27663f9e52
Diffstat (limited to 'tools')
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java3
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java29
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java69
3 files changed, 87 insertions, 14 deletions
diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
index def0f02..61bf33b 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
@@ -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;
}
diff --git a/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java
index 684bb90..bc13b52 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java
@@ -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);
- result.subtract(shape1 instanceof Area ? (Area) shape1 : new Area(shape1));
+
+ if (shape1 != null) {
+ result.subtract(shape1 instanceof Area ? (Area) shape1 : new Area(shape1));
+ }
+
return result;
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java
index a2fcb3b..72773c8 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java
@@ -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);
+ }
}
/**
@@ -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.
@@ -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;
}
}
@@ -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 {
@@ -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;
@@ -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;
}
}
@@ -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);
}
}
}