Revision: 4584
          http://sourceforge.net/p/vexi/code/4584
Author:   clrg
Date:     2013-11-20 17:46:52 +0000 (Wed, 20 Nov 2013)
Log Message:
-----------
BoxRenderProperties renamed to BoxVisual

Modified Paths:
--------------
    branches/vexi3/org.vexi-core.main/src/main/jpp/org/vexi/core/Box.jpp

Added Paths:
-----------
    branches/vexi3/org.vexi-core.main/src/main/java/org/vexi/core/BoxVisual.java

Removed Paths:
-------------
    
branches/vexi3/org.vexi-core.main/src/main/java/org/vexi/core/BoxRenderProperties.java

Deleted: 
branches/vexi3/org.vexi-core.main/src/main/java/org/vexi/core/BoxRenderProperties.java
===================================================================
--- 
branches/vexi3/org.vexi-core.main/src/main/java/org/vexi/core/BoxRenderProperties.java
      2013-11-20 15:47:48 UTC (rev 4583)
+++ 
branches/vexi3/org.vexi-core.main/src/main/java/org/vexi/core/BoxRenderProperties.java
      2013-11-20 17:46:52 UTC (rev 4584)
@@ -1,440 +0,0 @@
-// Copyright 2000-2008 the Contributors, as shown in the revision logs.
-// Licensed under the GNU General Public License version 2 ("the License").
-// You may not use this file except in compliance with the License.
-
-package org.vexi.core;
-
-import org.ibex.js.Fountain;
-import org.ibex.js.JS;
-import org.ibex.js.JSExn;
-import org.ibex.js.JSString;
-import org.ibex.js.JSU;
-import org.vexi.graphics.Color;
-import org.vexi.graphics.Font;
-import org.vexi.graphics.Picture;
-
-/**
- *  amalgamates Box rendering properties for memory/runtime efficiency
- *  - text properties font, fontsize, text, textcolor
- *  - fill properties texture, fillcolor
- **/
-final class BoxRenderProperties implements Constants {
-
-    //////// INSTANCE PROPERTIES /////////////////////////////////////
-
-    private short flags = 0;
-    int fontsize = 0;
-    int fillcolor = DEFAULT_FILLCOLOR;
-    int textcolor = DEFAULT_COLOR;
-    short textwidth = 0;
-    short textheight = 0;
-    Font font = DEFAULT_FONT;
-    JSString text = EMPTY_STRING;
-    Picture texture = null;
-
-
-    //////// CONSTRUCTORS /////////////////////////////////////////////
-
-    /** construct default text */
-    BoxRenderProperties() { }
-
-    /** construct new text object based on font from 'stream' of size 
'pointsize' */
-    BoxRenderProperties(JS stream) {
-        set(FONTSTREAM_SET);
-        setFont(stream, MEDIUM_SIZE);
-    }
-
-    /** construct new text object based on font from 'stream' of size 
'pointsize' */
-    BoxRenderProperties(int pointsize) {
-        set(FONTSIZE_SET);
-        setFont(DEFAULT_STREAM, pointsize);
-    }
-
-
-    //////// STATIC CONTENT ///////////////////////////////////////////
-
-    private static final short FILLCOLOR_SET  = 0x0001;
-    private static final short FONTCOLOR_SET  = 0x0002;
-    private static final short FONTSIZE_SET   = 0x0004;
-    private static final short FONTSTREAM_SET = 0x0008;
-
-    private static final short FONT_TRAP      = 0x0010;
-    private static final short FONTSIZE_TRAP  = 0x0020;
-
-    static int XXSMALL_OFFSET = -8;
-    static int XSMALL_OFFSET = -4;
-    static int SMALL_OFFSET = -2;
-    static int MEDIUM_SIZE = 10;
-    static int LARGE_OFFSET = 4;
-    static int XLARGE_OFFSET = 8;
-    static int XXLARGE_OFFSET = 14;
-    
-    static int DEFAULT_COLOR = 0xFF000000;
-    static int DEFAULT_FILLCOLOR = 0x00000000;
-    static Fountain DEFAULT_STREAM = Main.vera;
-    static Font DEFAULT_FONT = Font.getFont(DEFAULT_STREAM, MEDIUM_SIZE);
-    static BoxRenderProperties DEFAULT_RENDER_PROPS = new 
BoxRenderProperties();
-    static JSString EMPTY_STRING = (JSString) JSU.S("", true);
-    
-    static int getDefaultFontSize() { return MEDIUM_SIZE; }
-    static Fountain getDefaultStream() { return DEFAULT_STREAM; }
-    static Font getDefaultFont() { return DEFAULT_FONT; }
-
-    /** access for controlling default pointsize */
-    static boolean setDefaultPointsize(int pointsize) {
-        if (pointsize == MEDIUM_SIZE) {
-            return false;
-        }
-        MEDIUM_SIZE = pointsize;
-        DEFAULT_FONT = Font.getFont(DEFAULT_STREAM, MEDIUM_SIZE);
-        return true;
-    }
-
-    /** access for controlling default stream */
-    static boolean setDefaultStream(Fountain stream) {
-        if (stream == DEFAULT_STREAM) {
-            return false;
-        }
-        DEFAULT_STREAM = stream;
-        DEFAULT_FONT = Font.getFont(DEFAULT_STREAM, MEDIUM_SIZE);
-        return true;
-    }
-    
-    /** return appropriate JS constant for size */
-    static JS sizeToJS(int pointsize) {
-        switch (pointsize) {
-        case -3: return SC_xxsmall;
-        case -2: return SC_xsmall;
-        case -1: return SC_small;
-        case 0: return SC_medium;
-        case 1: return SC_large;
-        case 2: return SC_xlarge;
-        case 3: return SC_xxlarge;
-        default: return JSU.N(pointsize);
-        }
-    }
-
-    /** convert size represented in JS to appropriate pointsize */
-    static int jsToPointsize(JS size) throws JSExn {
-        return normalizeSize(jsToSize(size));
-    }
-    
-    /** convert size represented in JS to appropriate integer value */
-    static int jsToSize(JS size) throws JSExn {
-        if (size==null) {
-            return MEDIUM_SIZE;
-        }
-        if (size.type()==SC_number) {
-            int ps = JSU.toInt(size);
-            if (ps<6) {
-                throw new JSExn("Minimum fontsize is 6 - set to null or 
'medium' for default size");
-            }
-            return ps;
-        } else {
-            if (size.type()!=SC_string) {
-                throw new JSExn("type not applicable for fontsize: 
'"+size.type()+"'");
-            }
-        }
-        String sizeStr = JSU.toString(size);
-        try {
-            switch (sizeStr.charAt(0)) {
-            case 'm':
-                if (sizeStr.equals("medium")) {
-                    return 0;
-                }
-            case 's':
-                if (sizeStr.equals("small")) {
-                    return -1;
-                }
-            case 'l': 
-                if (sizeStr.equals("large")) {
-                    return 1;
-                }
-            case 'x':
-                if (sizeStr.charAt(1) == 'x') {
-                    if (sizeStr.equals("xxsmall")) {// || 
sizeStr.equals("xx-small")) {
-                        return -3;
-                    }
-                    if (sizeStr.equals("xxlarge")) {// || 
sizeStr.equals("xx-large")) {
-                        return 3;
-                    }
-                } else {
-                    if (sizeStr.equals("xsmall")) {// || 
sizeStr.equals("x-small")) {
-                        return -2;
-                    }
-                    if (sizeStr.equals("xlarge")) {// || 
sizeStr.equals("x-large")) {
-                        return 2;
-                    }
-                }
-            default:
-                return Integer.parseInt(sizeStr, 10);
-            }
-        } catch (Exception e) {
-            throw new JSExn("illegal fontsize: "+sizeStr+"");
-        }
-    }
-    
-    /** check/convert offset pointsize to literal pointsize */
-    static final int normalizeSize(int pointsize) {
-        if (pointsize>5) {
-            return pointsize;
-        }
-        int ps = MEDIUM_SIZE;
-        switch (pointsize) {
-        case -3: ps += XXSMALL_OFFSET; break;
-        case -2: ps += XSMALL_OFFSET; break;
-        case -1: ps += SMALL_OFFSET; break;
-        case 0: break;
-        case 1: ps += LARGE_OFFSET; break;
-        case 2: ps += XLARGE_OFFSET; break;
-        case 3: ps += XXLARGE_OFFSET; break;
-        }
-        return ps>5 ? ps : 6;
-    }
-    
-    
-    //////// HELPER FUNCTIONS /////////////////////////////////////////
-
-    // FLAGS helper functions
-    private final void set(short mask) { flags |= mask; }
-    private final void clear(short mask) { flags &= ~mask; }
-    private final boolean test(short mask) { return ((flags & mask) == mask); }
-
-    boolean activeTrapFontsize() { return test(FONTSIZE_TRAP); }
-    void clearTrapFont() { clear(FONT_TRAP); }
-    void clearTrapFontsize() { clear(FONTSIZE_TRAP); }
-    void setTrapFont(Box owner) {
-        if (this == DEFAULT_RENDER_PROPS) {
-            BoxRenderProperties t = new BoxRenderProperties();
-            t.set(FONT_TRAP);
-            owner.renderprops = t;
-        } else {
-            set(FONT_TRAP);
-        }
-    }
-    void setTrapFontsize(Box owner) {
-        if (this == DEFAULT_RENDER_PROPS) {
-            BoxRenderProperties t = new BoxRenderProperties();
-            t.set(FONTSIZE_TRAP);
-            owner.renderprops = t;
-        } else {
-            set(FONTSIZE_TRAP);
-        }
-    }
-    
-    private final void setFont(JS stream, int pointsize) {
-        if (stream == font.stream && pointsize == this.fontsize) {
-            return;
-        }
-        font = Font.getFont(stream, normalizeSize(pointsize));
-        this.fontsize = pointsize;
-        calculateDimensions();
-    }
-
-    /** set fillcolor to arbitrary value */
-    private boolean setFillcolor(int fillcolor, Box owner) {
-        if (test(FILLCOLOR_SET) && fillcolor == this.fillcolor) {
-            return false;
-        }
-        if (this == DEFAULT_RENDER_PROPS) {
-            BoxRenderProperties t = new BoxRenderProperties();
-            t.fillcolor = fillcolor;
-            t.set(FILLCOLOR_SET);
-            owner.renderprops = t;
-        } else {
-            set(FILLCOLOR_SET);
-            this.fillcolor = fillcolor;
-            if (texture != null) {
-                texture = null;
-            }
-        }
-        return true;
-    }
-    
-    private boolean setTexture(Picture texture, Box owner) {
-        if (texture == this.texture) {
-            return false;
-        }
-        if (this == DEFAULT_RENDER_PROPS) {
-            BoxRenderProperties t =  new BoxRenderProperties();
-            t.texture = texture;
-            owner.renderprops = t;
-        } else {
-            this.texture = texture;
-            // set fillcolor to be transparent
-            fillcolor = DEFAULT_FILLCOLOR;
-            clear(FILLCOLOR_SET);
-        }
-        return true;
-    }
-
-
-    //////// INSTANCE FUNCTIONS ///////////////////////////////////////
-    
-    boolean isEmpty() { return text == EMPTY_STRING; }
-    boolean isDefaultSize() { return !test(FONTSIZE_SET); }
-    boolean isDefaultColor() { return !test(FONTCOLOR_SET); }
-    boolean isDefaultStream() { return !test(FONTSTREAM_SET); }
-    
-    /** set textcolor to default color
-     * @return boolean stating if textcolor has changed */
-    boolean resetTextcolor() {
-        if (this != DEFAULT_RENDER_PROPS && test(FONTCOLOR_SET)) {
-            textcolor = DEFAULT_COLOR;
-            clear(FONTCOLOR_SET);
-            return true;
-        }
-        return false;
-    }
-    
-    /** set textcolor using arbitrary string, converting as necessary
-     * @return boolean stating if textcolor has changed */
-    boolean setTextcolor(JS jstextcolor, Box owner) throws JSExn {
-        int c = Color.stringToColor(JSU.toString(jstextcolor));
-        return setTextcolor(c, owner);
-    }
-    
-    /** set textcolor to integer value 
-     * @return boolean stating if textcolor has changed */
-    boolean setTextcolor(int textcolor, Box owner) {
-        if (test(FONTCOLOR_SET) && textcolor == this.textcolor) {
-            return false;
-        }
-        if (this == DEFAULT_RENDER_PROPS) {
-            BoxRenderProperties t = new BoxRenderProperties();
-            t.set(FONTCOLOR_SET);
-            t.textcolor = textcolor;
-            owner.renderprops = t;
-        } else {
-            set(FONTCOLOR_SET);
-            this.textcolor = textcolor;
-        }
-        return true;
-    }
-    
-    /** set the fill of a box according to 'value', converting as necessary */
-    boolean setFill(JS value, Box owner) throws JSExn {
-        if (value == null) {
-            return resetFill();
-        } else if (JSU.isString(value)) {
-            // use as a hex colour value
-            int newfillcolor = Color.stringToColor(JSU.toString(value));
-            return setFillcolor(newfillcolor, owner);
-        } else {
-            // stream fill - load texture
-            Picture newtex = Picture.load(value, owner);
-            // REMARK - Box.run() depends on renderprops
-            // so we need to call setTexture() before it
-            boolean textureChanged = setTexture(newtex, owner);
-            if (textureChanged && newtex.isLoaded) {
-                owner.run(null);
-            }
-            return textureChanged;
-        }
-    }
-    
-    /** set fillcolor to default fillcolor */
-    boolean resetFill() {
-        if (texture==null && !test(FILLCOLOR_SET)) {
-            return false;
-        }
-        // set fillcolor to be transparent
-        fillcolor = DEFAULT_FILLCOLOR;
-        clear(FILLCOLOR_SET);
-        texture = null;
-        return true;
-    }
-
-    /** set pointsize of this text object */
-    boolean resetFontsize() {
-        if (test(FONTSIZE_SET) && this != DEFAULT_RENDER_PROPS) {
-            if (fontsize != MEDIUM_SIZE) {
-                setFont(font.stream, MEDIUM_SIZE);
-            }
-            clear(FONTSIZE_SET);
-            return true;
-        }
-        return false;
-    }
-    
-    /** set pointsize to arbitary value */
-    boolean setFontsize(JS jsfontsize, Box owner) throws JSExn {
-        int ps = jsToSize(jsfontsize);
-        return setFontsize(ps, owner);
-    }
-    boolean setFontsize(int fontsize, Box owner) {
-        if (test(FONTSIZE_SET) && fontsize == this.fontsize) {
-            return false;
-        }
-        if (this == DEFAULT_RENDER_PROPS) {
-            owner.renderprops = new BoxRenderProperties(fontsize);
-        } else {
-            set(FONTSIZE_SET);
-            if (fontsize<6 || fontsize != this.fontsize) {
-                setFont(font.stream, fontsize);
-            }
-        }
-        return true;
-    }
-
-    /** set font stream of this text object */
-    boolean resetStream() {
-        if (this != DEFAULT_RENDER_PROPS && test(FONTSTREAM_SET)) {
-            if (font.stream != DEFAULT_STREAM) {
-                setFont(DEFAULT_STREAM, fontsize);
-            }
-            clear(FONTSTREAM_SET);
-            return true;
-        }
-        return false;
-    }
-    
-    /** set stream to arbitrary font stream */
-    boolean setStream(JS stream, Box owner) {
-        if (test(FONTSTREAM_SET) && stream == font.stream) {
-            return false;
-        }
-        if (this == DEFAULT_RENDER_PROPS) {
-            owner.renderprops = new BoxRenderProperties(stream);
-        } else {
-            set(FONTSTREAM_SET);
-            setFont(stream, fontsize);
-        }
-        return true;
-    }
-
-    /** set string representing text object */
-    //void resetString() { return setString(EMPTY_STRING); }
-    boolean setString(JSString text, Box owner) {
-        if (text==null) {
-            text = EMPTY_STRING;
-        }
-        if (text.equals(this.text)) {
-            return false;
-        }
-        if (this == DEFAULT_RENDER_PROPS) {
-            BoxRenderProperties t = new BoxRenderProperties();
-            owner.renderprops = t;
-            t.text = text;
-            t.calculateDimensions();
-        } else {
-            this.text = text;
-            calculateDimensions();
-        }
-        return true;
-    }
-
-    /** establish dimensions of rendered text contents */
-    private void calculateDimensions() {
-        if (text == EMPTY_STRING) {
-            textwidth = 0;
-            textheight = 0;
-            return;
-        }
-        long textsize = font.textsize(text.toString());
-        int iwidth = (int)((textsize >>> 32) & 0xffffffff);
-        int iheight = (int)(textsize & 0xffffffffL);
-        textwidth = iwidth > Short.MAX_VALUE ? Short.MAX_VALUE : (short)iwidth;
-        textheight = iheight > Short.MAX_VALUE ? Short.MAX_VALUE : 
(short)iheight;
-    }
-}

Copied: 
branches/vexi3/org.vexi-core.main/src/main/java/org/vexi/core/BoxVisual.java 
(from rev 4581, 
branches/vexi3/org.vexi-core.main/src/main/java/org/vexi/core/BoxRenderProperties.java)
===================================================================
--- 
branches/vexi3/org.vexi-core.main/src/main/java/org/vexi/core/BoxVisual.java    
                            (rev 0)
+++ 
branches/vexi3/org.vexi-core.main/src/main/java/org/vexi/core/BoxVisual.java    
    2013-11-20 17:46:52 UTC (rev 4584)
@@ -0,0 +1,440 @@
+// Copyright 2000-2008 the Contributors, as shown in the revision logs.
+// Licensed under the GNU General Public License version 2 ("the License").
+// You may not use this file except in compliance with the License.
+
+package org.vexi.core;
+
+import org.ibex.js.Fountain;
+import org.ibex.js.JS;
+import org.ibex.js.JSExn;
+import org.ibex.js.JSString;
+import org.ibex.js.JSU;
+import org.vexi.graphics.Color;
+import org.vexi.graphics.Font;
+import org.vexi.graphics.Picture;
+
+/**
+ *  Amalgamates Box's visual properties for memory/runtime efficiency:
+ *  - text properties font, fontsize, text, textcolor
+ *  - fill properties texture, fillcolor
+ **/
+final class BoxVisual implements Constants {
+
+    //////// INSTANCE PROPERTIES /////////////////////////////////////
+
+    private short flags = 0;
+    int fontsize = 0;
+    int fillcolor = DEFAULT_FILLCOLOR;
+    int textcolor = DEFAULT_COLOR;
+    short textwidth = 0;
+    short textheight = 0;
+    Font font = DEFAULT_FONT;
+    JSString text = EMPTY_STRING;
+    Picture texture = null;
+
+
+    //////// CONSTRUCTORS /////////////////////////////////////////////
+
+    /** construct default text */
+    BoxVisual() { }
+
+    /** construct new text object based on font from 'stream' of size 
'pointsize' */
+    BoxVisual(JS stream) {
+        set(FONTSTREAM_SET);
+        setFont(stream, MEDIUM_SIZE);
+    }
+
+    /** construct new text object based on font from 'stream' of size 
'pointsize' */
+    BoxVisual(int pointsize) {
+        set(FONTSIZE_SET);
+        setFont(DEFAULT_STREAM, pointsize);
+    }
+
+
+    //////// STATIC CONTENT ///////////////////////////////////////////
+
+    private static final short FILLCOLOR_SET  = 0x0001;
+    private static final short FONTCOLOR_SET  = 0x0002;
+    private static final short FONTSIZE_SET   = 0x0004;
+    private static final short FONTSTREAM_SET = 0x0008;
+
+    private static final short FONT_TRAP      = 0x0010;
+    private static final short FONTSIZE_TRAP  = 0x0020;
+
+    static int XXSMALL_OFFSET = -8;
+    static int XSMALL_OFFSET = -4;
+    static int SMALL_OFFSET = -2;
+    static int MEDIUM_SIZE = 10;
+    static int LARGE_OFFSET = 4;
+    static int XLARGE_OFFSET = 8;
+    static int XXLARGE_OFFSET = 14;
+    
+    static int DEFAULT_COLOR = 0xFF000000;
+    static int DEFAULT_FILLCOLOR = 0x00000000;
+    static Fountain DEFAULT_STREAM = Main.vera;
+    static Font DEFAULT_FONT = Font.getFont(DEFAULT_STREAM, MEDIUM_SIZE);
+    static BoxVisual DEFAULT = new BoxVisual();
+    static JSString EMPTY_STRING = (JSString) JSU.S("", true);
+    
+    static int getDefaultFontSize() { return MEDIUM_SIZE; }
+    static Fountain getDefaultStream() { return DEFAULT_STREAM; }
+    static Font getDefaultFont() { return DEFAULT_FONT; }
+
+    /** access for controlling default pointsize */
+    static boolean setDefaultPointsize(int pointsize) {
+        if (pointsize == MEDIUM_SIZE) {
+            return false;
+        }
+        MEDIUM_SIZE = pointsize;
+        DEFAULT_FONT = Font.getFont(DEFAULT_STREAM, MEDIUM_SIZE);
+        return true;
+    }
+
+    /** access for controlling default stream */
+    static boolean setDefaultStream(Fountain stream) {
+        if (stream == DEFAULT_STREAM) {
+            return false;
+        }
+        DEFAULT_STREAM = stream;
+        DEFAULT_FONT = Font.getFont(DEFAULT_STREAM, MEDIUM_SIZE);
+        return true;
+    }
+    
+    /** return appropriate JS constant for size */
+    static JS sizeToJS(int pointsize) {
+        switch (pointsize) {
+        case -3: return SC_xxsmall;
+        case -2: return SC_xsmall;
+        case -1: return SC_small;
+        case 0: return SC_medium;
+        case 1: return SC_large;
+        case 2: return SC_xlarge;
+        case 3: return SC_xxlarge;
+        default: return JSU.N(pointsize);
+        }
+    }
+
+    /** convert size represented in JS to appropriate pointsize */
+    static int jsToPointsize(JS size) throws JSExn {
+        return normalizeSize(jsToSize(size));
+    }
+    
+    /** convert size represented in JS to appropriate integer value */
+    static int jsToSize(JS size) throws JSExn {
+        if (size==null) {
+            return MEDIUM_SIZE;
+        }
+        if (size.type()==SC_number) {
+            int ps = JSU.toInt(size);
+            if (ps<6) {
+                throw new JSExn("Minimum fontsize is 6 - set to null or 
'medium' for default size");
+            }
+            return ps;
+        } else {
+            if (size.type()!=SC_string) {
+                throw new JSExn("type not applicable for fontsize: 
'"+size.type()+"'");
+            }
+        }
+        String sizeStr = JSU.toString(size);
+        try {
+            switch (sizeStr.charAt(0)) {
+            case 'm':
+                if (sizeStr.equals("medium")) {
+                    return 0;
+                }
+            case 's':
+                if (sizeStr.equals("small")) {
+                    return -1;
+                }
+            case 'l': 
+                if (sizeStr.equals("large")) {
+                    return 1;
+                }
+            case 'x':
+                if (sizeStr.charAt(1) == 'x') {
+                    if (sizeStr.equals("xxsmall")) {// || 
sizeStr.equals("xx-small")) {
+                        return -3;
+                    }
+                    if (sizeStr.equals("xxlarge")) {// || 
sizeStr.equals("xx-large")) {
+                        return 3;
+                    }
+                } else {
+                    if (sizeStr.equals("xsmall")) {// || 
sizeStr.equals("x-small")) {
+                        return -2;
+                    }
+                    if (sizeStr.equals("xlarge")) {// || 
sizeStr.equals("x-large")) {
+                        return 2;
+                    }
+                }
+            default:
+                return Integer.parseInt(sizeStr, 10);
+            }
+        } catch (Exception e) {
+            throw new JSExn("illegal fontsize: "+sizeStr+"");
+        }
+    }
+    
+    /** check/convert offset pointsize to literal pointsize */
+    static final int normalizeSize(int pointsize) {
+        if (pointsize>5) {
+            return pointsize;
+        }
+        int ps = MEDIUM_SIZE;
+        switch (pointsize) {
+        case -3: ps += XXSMALL_OFFSET; break;
+        case -2: ps += XSMALL_OFFSET; break;
+        case -1: ps += SMALL_OFFSET; break;
+        case 0: break;
+        case 1: ps += LARGE_OFFSET; break;
+        case 2: ps += XLARGE_OFFSET; break;
+        case 3: ps += XXLARGE_OFFSET; break;
+        }
+        return ps>5 ? ps : 6;
+    }
+    
+    
+    //////// HELPER FUNCTIONS /////////////////////////////////////////
+
+    // FLAGS helper functions
+    private final void set(short mask) { flags |= mask; }
+    private final void clear(short mask) { flags &= ~mask; }
+    private final boolean test(short mask) { return ((flags & mask) == mask); }
+
+    boolean activeTrapFontsize() { return test(FONTSIZE_TRAP); }
+    void clearTrapFont() { clear(FONT_TRAP); }
+    void clearTrapFontsize() { clear(FONTSIZE_TRAP); }
+    void setTrapFont(Box box) {
+        if (this == DEFAULT) {
+            BoxVisual t = new BoxVisual();
+            t.set(FONT_TRAP);
+            box.visual = t;
+        } else {
+            set(FONT_TRAP);
+        }
+    }
+    void setTrapFontsize(Box box) {
+        if (this == DEFAULT) {
+            BoxVisual t = new BoxVisual();
+            t.set(FONTSIZE_TRAP);
+            box.visual = t;
+        } else {
+            set(FONTSIZE_TRAP);
+        }
+    }
+    
+    private final void setFont(JS stream, int pointsize) {
+        if (stream == font.stream && pointsize == this.fontsize) {
+            return;
+        }
+        font = Font.getFont(stream, normalizeSize(pointsize));
+        this.fontsize = pointsize;
+        calculateDimensions();
+    }
+
+
+    //////// INSTANCE FUNCTIONS ///////////////////////////////////////
+    
+    boolean isEmpty() { return text == EMPTY_STRING; }
+    boolean isDefaultSize() { return !test(FONTSIZE_SET); }
+    boolean isDefaultColor() { return !test(FONTCOLOR_SET); }
+    boolean isDefaultStream() { return !test(FONTSTREAM_SET); }
+    
+    /** set textcolor to default color
+     * @return boolean stating if textcolor has changed */
+    boolean resetTextcolor() {
+        if (this != DEFAULT && test(FONTCOLOR_SET)) {
+            textcolor = DEFAULT_COLOR;
+            clear(FONTCOLOR_SET);
+            return true;
+        }
+        return false;
+    }
+    
+    /** set textcolor using arbitrary string, converting as necessary
+     * @return boolean stating if textcolor has changed */
+    boolean setTextcolor(JS jstextcolor, Box box) throws JSExn {
+        int c = Color.stringToColor(JSU.toString(jstextcolor));
+        return setTextcolor(c, box);
+    }
+    
+    /** set textcolor to integer value 
+     * @return boolean stating if textcolor has changed */
+    boolean setTextcolor(int textcolor, Box box) {
+        if (test(FONTCOLOR_SET) && textcolor == this.textcolor) {
+            return false;
+        }
+        if (this == DEFAULT) {
+            BoxVisual t = new BoxVisual();
+            t.set(FONTCOLOR_SET);
+            t.textcolor = textcolor;
+            box.visual = t;
+        } else {
+            set(FONTCOLOR_SET);
+            this.textcolor = textcolor;
+        }
+        return true;
+    }
+
+    /** set fillcolor to arbitrary value */
+    private boolean setFillcolor(int fillcolor, Box box) {
+        if (test(FILLCOLOR_SET) && fillcolor == this.fillcolor) {
+            return false;
+        }
+        if (this == DEFAULT) {
+            BoxVisual t = new BoxVisual();
+            t.fillcolor = fillcolor;
+            t.set(FILLCOLOR_SET);
+            box.visual = t;
+        } else {
+            set(FILLCOLOR_SET);
+            this.fillcolor = fillcolor;
+            if (texture != null) {
+                texture = null;
+            }
+        }
+        return true;
+    }
+    
+    private boolean setTexture(Picture texture, Box box) {
+        if (texture == this.texture) {
+            return false;
+        }
+        if (this == DEFAULT) {
+            BoxVisual t =  new BoxVisual();
+            t.texture = texture;
+            box.visual = t;
+        } else {
+            this.texture = texture;
+            // set fillcolor to be transparent
+            fillcolor = DEFAULT_FILLCOLOR;
+            clear(FILLCOLOR_SET);
+        }
+        return true;
+    }
+    
+    /** set the fill of a box according to 'value', converting as necessary */
+    boolean setFill(JS value, Box box) throws JSExn {
+        if (value == null) {
+            return resetFill();
+        } else if (JSU.isString(value)) {
+            // use as a hex colour value
+            int newfillcolor = Color.stringToColor(JSU.toString(value));
+            return setFillcolor(newfillcolor, box);
+        } else {
+            // stream fill - load texture
+            Picture newtex = Picture.load(value, box);
+            // REMARK - Box.run() depends on visual
+            // so we need to call setTexture() before it
+            boolean textureChanged = setTexture(newtex, box);
+            if (textureChanged && newtex.isLoaded) {
+                box.run(null);
+            }
+            return textureChanged;
+        }
+    }
+    
+    /** set fillcolor to default fillcolor */
+    boolean resetFill() {
+        if (texture==null && !test(FILLCOLOR_SET)) {
+            return false;
+        }
+        // set fillcolor to be transparent
+        fillcolor = DEFAULT_FILLCOLOR;
+        clear(FILLCOLOR_SET);
+        texture = null;
+        return true;
+    }
+
+    /** set pointsize of this text object */
+    boolean resetFontsize() {
+        if (test(FONTSIZE_SET) && this != DEFAULT) {
+            if (fontsize != MEDIUM_SIZE) {
+                setFont(font.stream, MEDIUM_SIZE);
+            }
+            clear(FONTSIZE_SET);
+            return true;
+        }
+        return false;
+    }
+    
+    /** set pointsize to arbitary value */
+    boolean setFontsize(JS jsfontsize, Box box) throws JSExn {
+        int ps = jsToSize(jsfontsize);
+        return setFontsize(ps, box);
+    }
+    boolean setFontsize(int fontsize, Box box) {
+        if (test(FONTSIZE_SET) && fontsize == this.fontsize) {
+            return false;
+        }
+        if (this == DEFAULT) {
+            box.visual = new BoxVisual(fontsize);
+        } else {
+            set(FONTSIZE_SET);
+            if (fontsize<6 || fontsize != this.fontsize) {
+                setFont(font.stream, fontsize);
+            }
+        }
+        return true;
+    }
+
+    /** set font stream of this text object */
+    boolean resetStream() {
+        if (this != DEFAULT && test(FONTSTREAM_SET)) {
+            if (font.stream != DEFAULT_STREAM) {
+                setFont(DEFAULT_STREAM, fontsize);
+            }
+            clear(FONTSTREAM_SET);
+            return true;
+        }
+        return false;
+    }
+    
+    /** set stream to arbitrary font stream */
+    boolean setStream(JS stream, Box box) {
+        if (test(FONTSTREAM_SET) && stream == font.stream) {
+            return false;
+        }
+        if (this == DEFAULT) {
+            box.visual = new BoxVisual(stream);
+        } else {
+            set(FONTSTREAM_SET);
+            setFont(stream, fontsize);
+        }
+        return true;
+    }
+
+    /** set string representing text object */
+    //void resetString() { return setString(EMPTY_STRING); }
+    boolean setString(JSString text, Box box) {
+        if (text==null) {
+            text = EMPTY_STRING;
+        }
+        if (text.equals(this.text)) {
+            return false;
+        }
+        if (this == DEFAULT) {
+            BoxVisual t = new BoxVisual();
+            box.visual = t;
+            t.text = text;
+            t.calculateDimensions();
+        } else {
+            this.text = text;
+            calculateDimensions();
+        }
+        return true;
+    }
+
+    /** establish dimensions of rendered text contents */
+    private void calculateDimensions() {
+        if (text == EMPTY_STRING) {
+            textwidth = 0;
+            textheight = 0;
+            return;
+        }
+        long textsize = font.textsize(text.toString());
+        int iwidth = (int)((textsize >>> 32) & 0xffffffff);
+        int iheight = (int)(textsize & 0xffffffffL);
+        textwidth = iwidth > Short.MAX_VALUE ? Short.MAX_VALUE : (short)iwidth;
+        textheight = iheight > Short.MAX_VALUE ? Short.MAX_VALUE : 
(short)iheight;
+    }
+}

Modified: branches/vexi3/org.vexi-core.main/src/main/jpp/org/vexi/core/Box.jpp
===================================================================
--- branches/vexi3/org.vexi-core.main/src/main/jpp/org/vexi/core/Box.jpp        
2013-11-20 15:47:48 UTC (rev 4583)
+++ branches/vexi3/org.vexi-core.main/src/main/jpp/org/vexi/core/Box.jpp        
2013-11-20 17:46:52 UTC (rev 4584)
@@ -220,7 +220,7 @@
     private final boolean test(int mask) { return ((flags & mask) == mask); }
     
     public final int getIntFillcolor() {
-        return renderprops.fillcolor;
+        return visual.fillcolor;
     }
     
     /** for Surface to set the x/y properties of the root box */
@@ -331,7 +331,7 @@
     private short trapflags = 0;
     private BasicTree bt = null;
     // rendering properties
-    BoxRenderProperties renderprops = BoxRenderProperties.DEFAULT_RENDER_PROPS;
+    BoxVisual visual = BoxVisual.DEFAULT;
 
     // FEATURE: path support
     //private Path path = null;
@@ -356,7 +356,7 @@
     protected int y = 0;
     public int width = 0;
     public int height = 0;
-    protected int contentwidth = 0; // == min(maxwidth, max(minwidth, 
renderprops.textwidth, sum(child.contentwidth)))
+    protected int contentwidth = 0; // == min(maxwidth, max(minwidth, 
visual.textwidth, sum(child.contentwidth)))
     protected int contentheight = 0;
 
 
@@ -373,7 +373,7 @@
                 return;
             }
             // get around sub-sampling of enlarged textures
-            if (cur.renderprops.texture != null && !cur.test(TILE_IMAGE)) {
+            if (cur.visual.texture != null && !cur.test(TILE_IMAGE)) {
                 // REMARK: inefficient but otherwise the consistency of
                 // translating enlarged pixels to on-screen coordinates
                 // can not be guaranteed as it depends upon first
@@ -410,23 +410,23 @@
 
     /** invoked when a resource needed to render ourselves finishes loading */
     public Object run(Object o) throws JSExn {
-        if (renderprops.texture == null) {
+        if (visual.texture == null) {
             // Pictures are loaded asynchronously, then the Box is scheduled.
             // It is possible that the texture has been removed inbetween,
             // not an error though it may indicate bad Vexi code.
             Log.system.debug(Box.class, "Called run() on a Box with a null 
texture");
-        } else if (renderprops.texture.isLoaded) {
+        } else if (visual.texture.isLoaded) {
             dirty();
             // Tiled images affect contentsize
             if (test(TILE_IMAGE)) {
-               setMinWidth(renderprops.texture.width, true);
-               setMinHeight(renderprops.texture.height, true);
+               setMinWidth(visual.texture.width, true);
+               setMinHeight(visual.texture.height, true);
                 setConstrain();
             }
-        } else if (renderprops.texture.loadFailed!=null) {
-            //JS res = renderprops.texture.stream;
-            justTriggerTraps(SC_fill, 
renderprops.texture.loadFailed.asObject());
-            renderprops.resetFill();
+        } else if (visual.texture.loadFailed!=null) {
+            //JS res = visual.texture.stream;
+            justTriggerTraps(SC_fill, visual.texture.loadFailed.asObject());
+            visual.resetFill();
             // just in case of previous image / fill
             dirty();
             // Tiled images affect contentsize
@@ -541,15 +541,15 @@
     static protected final void reflowTreeTextSize(Box box) throws JSExn {
         box.set(CONSTRAIN_DESCENDENT);
         box.set(PLACE_DESCENDENT);
-        if (box.renderprops.fontsize<6) {
-            if (box.renderprops!=BoxRenderProperties.DEFAULT_RENDER_PROPS) {
-                box.renderprops.resetFontsize();
+        if (box.visual.fontsize<6) {
+            if (box.visual!=BoxVisual.DEFAULT) {
+                box.visual.resetFontsize();
             }
-            if (box.renderprops.textwidth!=0) {
+            if (box.visual.textwidth!=0) {
                 box.set(CONSTRAIN);
                 box.set(PLACE);
             }
-            box.justTriggerTraps(SC_fontsize, 
BoxRenderProperties.sizeToJS(box.renderprops.fontsize));
+            box.justTriggerTraps(SC_fontsize, 
BoxVisual.sizeToJS(box.visual.fontsize));
         }
         int i=0;
         for (Box b = box.getChild(i); b!=null; b=box.getChild(++i)) {
@@ -658,13 +658,13 @@
                 clear(HAS_WIDTH_SLACK);
             }
         } else {
-            if (new_contentwidth < maxwidth && (new_contentwidth < minwidth || 
new_contentwidth < renderprops.textwidth ||
-                       (renderprops.texture!=null && new_contentwidth < 
renderprops.texture.width))) {
+            if (new_contentwidth < maxwidth && (new_contentwidth < minwidth || 
new_contentwidth < visual.textwidth ||
+                       (visual.texture!=null && new_contentwidth < 
visual.texture.width))) {
                 set(HAS_WIDTH_SLACK);
             } else {
                 clear(HAS_WIDTH_SLACK);
             }
-            new_contentwidth = max(new_contentwidth, renderprops.textwidth);
+            new_contentwidth = max(new_contentwidth, visual.textwidth);
         }
 
         new_contentwidth = min(maxwidth, max(minwidth, new_contentwidth));
@@ -719,7 +719,7 @@
             
             // place children individually in box space
             if (!test(PACK)) {
-                for (Box child = getChild(i=0); child != null; child = 
getChild(++i)) {
+                for (Box child = getChild(i=treeSize()-1); child != null; 
child = getChild(--i)) {
                     if (!child.test(DISPLAY)) {
                         continue;
                     }
@@ -1031,19 +1031,19 @@
 
         if (parent == null) {
             // disregard transparency for root
-            buf.fillTrapezoid(cx1, cx2, cy1, cx1, cx2, cy2, 
renderprops.fillcolor|0xFF000000);
-        } else if ((renderprops.fillcolor & 0xFF000000) != 0x00000000) {
+            buf.fillTrapezoid(cx1, cx2, cy1, cx1, cx2, cy2, 
visual.fillcolor|0xFF000000);
+        } else if ((visual.fillcolor & 0xFF000000) != 0x00000000) {
             // normal color fill, skipping fully transparent fills
-            buf.fillTrapezoid(cx1, cx2, cy1, cx1, cx2, cy2, 
renderprops.fillcolor);
+            buf.fillTrapezoid(cx1, cx2, cy1, cx1, cx2, cy2, visual.fillcolor);
         }
 
-        if (renderprops.texture != null && renderprops.texture.isLoaded) {
-            int tw = renderprops.texture.width;
-            int th = renderprops.texture.height;
+        if (visual.texture != null && visual.texture.isLoaded) {
+            int tw = visual.texture.width;
+            int th = visual.texture.height;
             if (test(TILE_IMAGE)) {
                 for (int x = globalx; x < cx2; x += tw) {
                     for (int y = globaly; y < cy2; y += th) {
-                        buf.drawPicture(renderprops.texture, x, y, cx1, cy1, 
cx2, cy2);
+                        buf.drawPicture(visual.texture, x, y, cx1, cy1, cx2, 
cy2);
                     }
                 }
             } else {
@@ -1051,18 +1051,18 @@
                 int sy1 = (int)(th * ((float)(cy1-globaly)/height) + 0.5);
                 int sx2 = (int)(tw * ((float)(cx2-globalx)/width)  + 0.5);
                 int sy2 = (int)(th * ((float)(cy2-globaly)/height) + 0.5);
-                buf.drawPicture(renderprops.texture, cx1, cy1, cx2, cy2, sx1, 
sy1, sx2, sy2);
+                buf.drawPicture(visual.texture, cx1, cy1, cx2, cy2, sx1, sy1, 
sx2, sy2);
             }
         }
         
-        // REMARK: renderprops.font may still be null at this point so
-        // cannot use renderprops.isEmpty() but instead use 
renderprops.textwidth
-        if (renderprops.textwidth != 0) {
-            int gap_x = width - renderprops.textwidth;
-            int gap_y = height - renderprops.textheight;
+        // REMARK: visual.font may still be null at this point so
+        // cannot use visual.isEmpty() but instead use visual.textwidth
+        if (visual.textwidth != 0) {
+            int gap_x = width - visual.textwidth;
+            int gap_y = height - visual.textheight;
             int text_x = globalx + (test(ALIGN_RIGHT) ? gap_x : 
!test(ALIGN_LEFT) ? gap_x/2 : 0);
             int text_y = globaly + (test(ALIGN_BOTTOM) ? gap_y : 
!test(ALIGN_TOP) ? gap_y/2 : 0);
-            renderprops.font.rasterizeGlyphs(renderprops.text.toString(), buf, 
renderprops.textcolor, text_x, text_y, cx1, cy1, cx2, cy2);
+            visual.font.rasterizeGlyphs(visual.text.toString(), buf, 
visual.textcolor, text_x, text_y, cx1, cy1, cx2, cy2);
         }
 
         //if (path != null) path.realize(Affine.translate(globalx, 
globaly)).stroke(buf, 1, strokecolor);
@@ -1652,7 +1652,7 @@
         // FIXME: another hack
         // we really should return a re-usable JS stream
         Box b = new Box();
-        BoxRenderProperties r = b.renderprops = new BoxRenderProperties();
+        BoxVisual r = b.visual = new BoxVisual();
         r.texture = pb.toPicture();
         return b;
     }
@@ -1782,7 +1782,7 @@
         case "path":
             if (path != null) return JSU.S(path.toString());
             String ret = "";
-            for(int i=0; i<renderprops.str.length(); i++) ret += 
font.glyphs[renderprops.str.charAt(i)].path;
+            for(int i=0; i<visual.str.length(); i++) ret += 
font.glyphs[visual.str.charAt(i)].path;
             return JSU.S(ret);
         case "strokecolor": return JSU.S(Color.colorToString(strokecolor));
         case "strokewidth": return JSU.N(strokewidth);
@@ -1820,10 +1820,10 @@
          * @type(String<br/>Stream)
          * */
         case "fill":
-            if (renderprops.texture == null) {
-                return JSU.S(Color.colorToString(renderprops.fillcolor));
+            if (visual.texture == null) {
+                return JSU.S(Color.colorToString(visual.fillcolor));
             }
-            return renderprops.texture.stream;
+            return visual.texture.stream;
         
         /* <p>When an object is written to this property, its stream is read 
using the 
          * <a href="http://www.freetype.org/"; target="_top">freetype2 
library</a>, and the
@@ -1833,7 +1833,7 @@
          * @initial_value(vexi.ui.font.vera)
          * @nofollow
          * */
-        case "font": return renderprops.font.stream;
+        case "font": return visual.font.stream;
         
         /* <p>The size, either in points or relative size, to render the 
text.</p>
          * 
@@ -1854,7 +1854,7 @@
          * @type(Number)
          * @initial_value("medium")
          * */
-        case "fontsize": return 
BoxRenderProperties.sizeToJS(renderprops.fontsize);
+        case "fontsize": return BoxVisual.sizeToJS(visual.fontsize);
         
         /* <p>The text of a box. Visually <code>null</code> renders the same 
as the text to ""
          * (i.e as nothing).</p>
@@ -1863,7 +1863,7 @@
          * @type(String)
          * @nofollow
          * */
-        case "text": return renderprops.text;
+        case "text": return visual.text;
         
         /* <p>If the value is a 5-character hex string (#RGB), 7-character hex 
string (#RRGGBB),
          * 9-character hex string (#AARRGGBB), a box's text color will be set 
to that color.</p>
@@ -1877,7 +1877,7 @@
          * @initial_value("#ffffff")
          * @type(String)
          * */
-        case "textcolor": return 
JSU.S(Color.colorToString(renderprops.textcolor));
+        case "textcolor": return JSU.S(Color.colorToString(visual.textcolor));
         
         /* <p>This property can be set to any of the values specified for 
textcolor. If the value
          * written is a stream then it will interpreted as a PNG, GIF, or JPEG 
image, which will
@@ -2443,52 +2443,52 @@
                 throw new JSExn("Attempt to put a non-stream to the 'font' 
property of a box");
             }
             if (value == null) {
-                if (!renderprops.resetStream()) {
+                if (!visual.resetStream()) {
                     return;
                 }
             } else {
                 Fountain fontstream = (Fountain)value.unclone();
-                if (!renderprops.setStream(fontstream, this)) {
+                if (!visual.setStream(fontstream, this)) {
                     return;
                 }
             }
-            if (!renderprops.isEmpty()) {
+            if (!visual.isEmpty()) {
                 setConstrain();
                 dirty();
             }
         case "fontsize":
             if (value==null) {
-                if (!renderprops.resetFontsize()) {
+                if (!visual.resetFontsize()) {
                     return;
                 }
             } else {
-                if (!renderprops.setFontsize(value, this)) {
+                if (!visual.setFontsize(value, this)) {
                     return;
                 }
             }
-            if (!renderprops.isEmpty()) {
+            if (!visual.isEmpty()) {
                 setConstrain();
                 dirty();
             }
         case "text":
             JSString s = value == null ? null :
                 value instanceof JSString ? (JSString)value : 
(JSString)JSU.S(JSU.toString(value));
-            if (renderprops.setString(s, this)) {
+            if (visual.setString(s, this)) {
                 setConstrain();
                 dirty();
             }
         case "textcolor":
             try {
                 if (value==null) {
-                    if (!renderprops.resetTextcolor()) {
+                    if (!visual.resetTextcolor()) {
                         return;
                     }
                 } else {
-                    if (!renderprops.setTextcolor(value, this)) {
+                    if (!visual.setTextcolor(value, this)) {
                         return;
                     }
                 }
-                if (!renderprops.isEmpty()) {
+                if (!visual.isEmpty()) {
                     dirty();
                 }
             } catch (ClassCastException cce) {
@@ -2595,16 +2595,16 @@
             }
         case "align":       setAlign(value);
         case "fill":
-            if (value == null && renderprops.texture != null && 
test(TILE_IMAGE)) {
+            if (value == null && visual.texture != null && test(TILE_IMAGE)) {
                 setConstrain();
             }
-            if (renderprops.setFill(value, this)) {
+            if (visual.setFill(value, this)) {
                 dirty();
             }
         case "tile":
             if (CHECKSET_FLAG(TILE_IMAGE)) {
                 dirty();
-                if (renderprops.texture != null && 
renderprops.texture.isLoaded) {
+                if (visual.texture != null && visual.texture.isLoaded) {
                     if (test(TILE_IMAGE)) {
                        // this will cause the Box's minimum dimensions
                        // to be set to the image dimensions when tiled
@@ -2913,8 +2913,8 @@
         case "_Move":     set(_MOVE_TRAP);
         case "Move":      set(MOVE_TRAP);
         case "Resize":    set(RESIZE_TRAP);
-        case "fontsize":  renderprops.setTrapFontsize(this);
-        case "font":      renderprops.setTrapFont(this);
+        case "fontsize":  visual.setTrapFontsize(this);
+        case "font":      visual.setTrapFont(this);
         case "shrink":    set(SHRINK_TRAP);
         case "hshrink":   set(HSHRINK_TRAP);
         case "vshrink":   set(VSHRINK_TRAP);
@@ -2954,8 +2954,8 @@
         case "_Move":     if (wtrap(SC__Move) == null) clear(_MOVE_TRAP);
         case "Move":      if (wtrap(SC_Move) == null) clear(MOVE_TRAP);
         case "Resize":    if (wtrap(SC_Resize) == null) clear(RESIZE_TRAP);
-        case "fontsize":  if (wtrap(SC_fontsize) == null && renderprops != 
BoxRenderProperties.DEFAULT_RENDER_PROPS) renderprops.clearTrapFontsize();
-        case "font":      if (wtrap(SC_font) == null && renderprops != 
BoxRenderProperties.DEFAULT_RENDER_PROPS) renderprops.clearTrapFont();
+        case "fontsize":  if (wtrap(SC_fontsize) == null && visual != 
BoxVisual.DEFAULT) visual.clearTrapFontsize();
+        case "font":      if (wtrap(SC_font) == null && visual != 
BoxVisual.DEFAULT) visual.clearTrapFont();
         case "shrink":    if (wtrap(SC_shrink) == null) clear(SHRINK_TRAP);
         case "hshrink":   if (wtrap(SC_hshrink) == null) clear(HSHRINK_TRAP);
         case "vshrink":   if (wtrap(SC_vshrink) == null) clear(VSHRINK_TRAP);

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.


------------------------------------------------------------------------------
Shape the Mobile Experience: Free Subscription
Software experts and developers: Be at the forefront of tech innovation.
Intel(R) Software Adrenaline delivers strategic insight and game-changing 
conversations that shape the rapidly evolving mobile landscape. Sign up now. 
http://pubads.g.doubleclick.net/gampad/clk?id=63431311&iu=/4140/ostg.clktrk
_______________________________________________
Vexi-svn mailing list
Vexi-svn@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/vexi-svn

Reply via email to