* trigger a Surface.abort; if rendering were done in the same pass,
* rendering work done prior to the Surface.abort would be wasted.
*/
-public final class Box extends JS.Obj implements Callable {
+public final class Box extends JS.Obj implements Callable, Mesh.Chain {
+
+ public Mesh.Chain getMeshChainParent() { return parent; }
+ public Mesh getMesh() { return mesh; }
+ public Affine getAffine() { return transform; }
// Macros //////////////////////////////////////////////////////////////////////
private int strokecolor = 0xFF000000;
public float flex = 1;
private Path path = null;
+ private Path clippath = null;
private Affine transform = Affine.identity();
// FEATURE: polygon caching
- private Polygon polygon = null;
+ private Mesh polygon = null;
private Mesh mesh = null;
// specified directly by user
transform.f = 0;
a = a.copy().premultiply(transform);
- boolean relevant = packed() || ((fillcolor&0xff000000)!=0x0) || path!=null;
+ //boolean relevant = packed() || ((fillcolor&0xff000000)!=0x0) || path!=null;
+ boolean relevant = true;
int save_xmin = xmin, save_ymin = ymin, save_xmax = xmax, save_ymax = ymax;
if (!relevant) {
for(Box child = getChild(0); child != null; child = child.nextSibling()) {
private static final boolean OPTIMIZE = false;
/** Renders self and children within the specified region. All rendering operations are clipped to xIn,yIn,wIn,hIn */
- public void render(PixelBuffer buf, Affine a) {
+ public void render(PixelBuffer buf, Affine a, Mesh clipFrom) { render(buf, a, clipFrom, Affine.identity()); }
+ public void render(PixelBuffer buf, Affine a, Mesh clipFrom, Affine clipa) {
if (!test(VISIBLE)) return;
- a = a.copy().premultiply(transform);
-
- // FIXME: clipping
- if (path == null) {
- if (((fillcolor & 0xFF000000) != 0x00000000 || parent == null) && (text==null||"".equals(text))) {
- if (OPTIMIZE && a.doesNotRotate()) {
- int x = (int)a.multiply_px(0, 0);
- int y = (int)a.multiply_py(0, 0);
- int x2 = (int)a.multiply_px(contentwidth, contentheight);
- int y2 = (int)a.multiply_py(contentwidth, contentheight);
- buf.fillTrapezoid(x, x, y, x2, x2, y2, (fillcolor & 0xFF000000) == 0 ? 0xffffffff : fillcolor);
- } else {
- new Polygon().addrect(0, 0, contentwidth, contentheight, a).fill(buf, new Paint.SingleColorPaint(fillcolor));
- }
+ a = a.copy().multiply(transform);
+ clipa = clipa.copy().multiply(transform);
+
+ if (mesh == null)
+ if (path != null) mesh = new Mesh(path, true);
+ else {
+ if (((fillcolor & 0xFF000000) != 0x00000000 || parent == null) && (text==null||"".equals(text)))
+ mesh = new Mesh().addRect(0, 0, contentwidth, contentheight);
+ // long ret = font.rasterizeGlyphs(text, buf, a, null, 0x777777, 0);
+ // minwidth = maxwidth = font.textwidth(text);
+ // minheight = maxheight = font.textwidth(text);
+ // if (ret == 0) Platform.Scheduler.add(this);
+ // FIXME: texture
}
- if (text != null) {
- long ret = font.rasterizeGlyphs(text, buf, a, null, 0x777777, 0);
- minwidth = maxwidth = font.textwidth(text);
- minheight = maxheight = font.textwidth(text);
- if (ret == 0) Platform.Scheduler.add(this);
- }
- // FIXME: texture
- } else {
- if (mesh == null) {
- Log.warn(this, "generating mesh...");
- mesh = new Mesh(new Polygon(path, Affine.identity()));
- Log.warn(this, " done generating mesh.");
- }
- mesh.fill(buf, a, fillcolor, true, false);
- mesh.stroke(buf, a, strokecolor);
- //mesh.fill(buf, a, fillcolor, true, true);
+ if (mesh==null) {
+ for(Box b = getChild(0); b != null; b = b.nextSibling()) b.render(buf, a, clipFrom, clipa);
+ return;
}
- for(Box b = getChild(0); b != null; b = b.nextSibling()) b.render(buf, a);
+ if (clipFrom != null) clipFrom.subtract(mesh, clipa);
+ Mesh mesh = treeSize() > 0 ? this.mesh.copy() : this.mesh;
+ for(Box b = getChild(0); b != null; b = b.nextSibling()) b.render(buf, a, mesh, Affine.identity());
+ mesh.fill(buf, a, null, fillcolor, true);
}
-
// Methods to implement org.ibex.js.JS //////////////////////////////////////
public JS call(JS method, JS[] args) throws JSExn {
case "hshrink": CHECKSET_FLAG(HSHRINK); RECONSTRAIN();
case "vshrink": CHECKSET_FLAG(VSHRINK); RECONSTRAIN();
case "path": {
+ mesh = null;
path = new Path(JSU.toString(value));
float tx = -1 * Encode.longToFloat2(path.horizontalBounds(Affine.identity()));
float ty = -1 * Encode.longToFloat2(path.verticalBounds(Affine.identity()));
dirty();
polygon = null;
}
+ case "clippath": {
+ clippath = new Path(JSU.toString(value));
+ //float tx = -1 * Encode.longToFloat2(clippath.horizontalBounds(Affine.identity()));
+ //float ty = -1 * Encode.longToFloat2(clippath.verticalBounds(Affine.identity()));
+ //clippath.transform(Affine.translate(tx, ty), true);
+ REPLACE();
+ RECONSTRAIN();
+ dirty();
+ polygon = null;
+ }
case "transform": {
transform = Affine.parse(JSU.toString(value));
transform.e = 0;
transform.f = 0;
- if (getSurface() != null) getSurface().dirty(0, 0, 500, 500); // FIXME
+ if (getSurface() != null) // FIXME
+ getSurface().dirty(0, 0, getSurface().root.contentwidth, getSurface().root.contentheight);
REPLACE();
RECONSTRAIN(); dirty(); polygon = null;
}