Revision: 4009 http://vexi.svn.sourceforge.net/vexi/?rev=4009&view=rev Author: clrg Date: 2011-01-31 14:02:33 +0000 (Mon, 31 Jan 2011)
Log Message: ----------- Refactor core.Text -> core.BoxRenderProperties - move fillcolor, texture from Box to BoxRenderProperties - use flags over booleans in BoxRenderProperties - use short over int in simple situations (could do more of this) - should slightly reduce memory usage - NOTE: 15 unit tests are failing but from before this (since ?) - NOTE: staggered reflow/render e.g. highlight label text (since before r3987 or earlier) Modified Paths: -------------- trunk/org.vexi-core.main/src/main/java/org/vexi/core/VML.java trunk/org.vexi-core.main/src/main/java/org/vexi/plat/AWT.java trunk/org.vexi-core.main/src/main/jpp/org/vexi/core/Box.jpp trunk/org.vexi-core.main/src/main/jpp/org/vexi/core/Vexi.jpp Added Paths: ----------- trunk/org.vexi-core.main/src/main/java/org/vexi/core/BoxRenderProperties.java Removed Paths: ------------- trunk/org.vexi-core.main/src/main/java/org/vexi/core/Text.java Copied: trunk/org.vexi-core.main/src/main/java/org/vexi/core/BoxRenderProperties.java (from rev 3992, trunk/org.vexi-core.main/src/main/java/org/vexi/core/Text.java) =================================================================== --- trunk/org.vexi-core.main/src/main/java/org/vexi/core/BoxRenderProperties.java (rev 0) +++ trunk/org.vexi-core.main/src/main/java/org/vexi/core/BoxRenderProperties.java 2011-01-31 14:02:33 UTC (rev 4009) @@ -0,0 +1,414 @@ +// 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 common text properties for memory/runtime efficiency */ +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 arbitary 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 color to default color */ + boolean resetColor() { + if (this != DEFAULT_RENDER_PROPS && test(FONTCOLOR_SET)) { + textcolor = DEFAULT_COLOR; + clear(FONTCOLOR_SET); + return true; + } + return false; + } + + /** set color to arbitary value + * @return boolean stating if color has changed */ + boolean setColor(JS jscolor, Box owner) throws JSExn { + int c = Color.stringToColor(JSU.toString(jscolor)); + return setColor(c, owner); + } + boolean setColor(int color, Box owner) { + if (test(FONTCOLOR_SET) && color == this.textcolor) { + return false; + } + + set(FONTCOLOR_SET); + BoxRenderProperties t = (this == DEFAULT_RENDER_PROPS) ? new BoxRenderProperties() : this; + t.textcolor = color; + return true; + } + + /** set the fill of a box according to 'value' */ + 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); + if (texture != null && texture.isLoaded) { + owner.run(null); + } + return setTexture(newtex, owner); + } + } + + /** 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).equals(this.text)) { + return false; + } + BoxRenderProperties t = (this == DEFAULT_RENDER_PROPS) ? new BoxRenderProperties() : this; + t.text = text; + t.calculateDimensions(); + return true; + } + + /** synchronize dimensions with text object contents */ + private void calculateDimensions() { + if (text == EMPTY_STRING) { + textwidth = 0; + textheight = 0; + return; + } + int iwidth = font.textwidth(text.toString()); + int iheight = font.textheight(text.toString()); + textwidth = iwidth > Short.MAX_VALUE ? Short.MAX_VALUE : (short) font.textwidth(text.toString()); + textheight = iheight > Short.MAX_VALUE ? Short.MAX_VALUE : (short) font.textheight(text.toString()); + } +} Deleted: trunk/org.vexi-core.main/src/main/java/org/vexi/core/Text.java =================================================================== --- trunk/org.vexi-core.main/src/main/java/org/vexi/core/Text.java 2011-01-26 23:03:05 UTC (rev 4008) +++ trunk/org.vexi-core.main/src/main/java/org/vexi/core/Text.java 2011-01-31 14:02:33 UTC (rev 4009) @@ -1,292 +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.Font; - -/** amalgamates common text properties for memory/runtime efficiency */ -final class Text implements Constants { - - //////// STATIC CONTENT ////////////////////////////////////////// - - 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 Fountain DEFAULT_STREAM = Main.vera; - static Font DEFAULT_FONT = Font.getFont(DEFAULT_STREAM, MEDIUM_SIZE); - static Text DEFAULT_TEXT = new Text(); - 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+""); - } - } - - - //////// INSTANCE PROPERTIES ///////////////////////////////////// - - private boolean sizeset = false; - private boolean colorset = false; - private boolean streamset = false; - public int pointsize = 0; - int color = DEFAULT_COLOR; - int width = 0; - int height = 0; - Font font = DEFAULT_FONT; - JSString str = EMPTY_STRING; - - // put these here to avoid consuming Box flags - boolean font_trap = false; - boolean fontsize_trap = false; - - - //////// CONSTRUCTORS ///////////////////////////////////////////// - - /** construct default text */ - Text() { } - - /** construct new text object based on font from 'stream' of size 'pointsize' */ - Text(JS stream) { - this.streamset = true; - setFont(stream, MEDIUM_SIZE); - } - - /** construct new text object based on font from 'stream' of size 'pointsize' */ - Text(int pointsize) { - this.sizeset = true; - setFont(DEFAULT_STREAM, 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; - } - - private final void setFont(JS stream, int pointsize) { - if (stream == font.stream && pointsize == this.pointsize) { - return; - } - font = Font.getFont(stream, normalizeSize(pointsize)); - this.pointsize = pointsize; - calculateDimensions(); - } - - - //////// INSTANCE FUNCTIONS /////////////////////////////////////// - - boolean isEmpty() { return str == EMPTY_STRING; } - boolean isDefaultSize() { return !sizeset; } - boolean isDefaultColor() { return !colorset; } - boolean isDefaultStream() { return !streamset; } - - /** set color to default color */ - Text setColor() { - if (this != DEFAULT_TEXT && colorset) { - color = DEFAULT_COLOR; - colorset = false; - } - return this; - } - - /** set color to arbitary value */ - Text setColor(int color) { - if (colorset && color == this.color) { - return this; - } - colorset = true; - Text t = (this == DEFAULT_TEXT) ? new Text() : this; - t.color = color; - return t; - } - - /** set pointsize of this text object */ - Text setSize() { - if (this != DEFAULT_TEXT && sizeset) { - if (pointsize != MEDIUM_SIZE) { - setFont(font.stream, MEDIUM_SIZE); - } - sizeset = false; - } - return this; - } - - /** set pointsize to arbitary value */ - Text setSize(int pointsize) { - if (sizeset && pointsize == this.pointsize) { - return this; - } - if (this == DEFAULT_TEXT) { - return new Text(pointsize); - } - sizeset = true; - if (pointsize<6 || pointsize != this.pointsize) { - setFont(font.stream, pointsize); - } - return this; - } - - /** set font stream of this text object */ - Text setStream() { - if (this != DEFAULT_TEXT && streamset) { - if (font.stream != DEFAULT_STREAM) { - setFont(DEFAULT_STREAM, pointsize); - } - streamset = false; - } - return this; - } - - /** set stream to arbitrary font stream */ - Text setStream(JS stream) { - if (streamset && stream == font.stream) { - return this; - } - if (this == DEFAULT_TEXT) { - return new Text(stream); - } - streamset = true; - setFont(stream, pointsize); - return this; - } - - /** set string representing text object */ - Text setString() { return setString(EMPTY_STRING); } - Text setString(JSString str) { - if (str.equals(this.str)) { - return this; - } - Text t = (this == DEFAULT_TEXT) ? new Text() : this; - t.str = str; - t.calculateDimensions(); - return t; - } - - /** synchronize dimensions with text object contents */ - private void calculateDimensions() { - if (str == EMPTY_STRING) { - width = 0; - height = 0; - return; - } - width = font.textwidth(str.toString()); - height = font.textheight(str.toString()); - } -} Modified: trunk/org.vexi-core.main/src/main/java/org/vexi/core/VML.java =================================================================== --- trunk/org.vexi-core.main/src/main/java/org/vexi/core/VML.java 2011-01-26 23:03:05 UTC (rev 4008) +++ trunk/org.vexi-core.main/src/main/java/org/vexi/core/VML.java 2011-01-31 14:02:33 UTC (rev 4009) @@ -139,7 +139,7 @@ return Static.this; } - private Template preapply(JS[] thisHolder, JS[] args, Object o) throws JSExn{ + private Template preapply(JS[] thisHolder, JS[] args, Object o) throws JSExn { if (o==null) { return null; } @@ -148,7 +148,7 @@ t = ((Blessing)Vexi.resolveString(vexi,(String)o)).getTemplate(); } else { t = (Template)o; - if(Main.hotreplace && t.isTop()){ + if (Main.hotreplace && t.isTop()) { t = ((Blessing)Vexi.resolveString(vexi,t.getStatic().sourceName)).getTemplate(); } } Modified: trunk/org.vexi-core.main/src/main/java/org/vexi/plat/AWT.java =================================================================== --- trunk/org.vexi-core.main/src/main/java/org/vexi/plat/AWT.java 2011-01-26 23:03:05 UTC (rev 4008) +++ trunk/org.vexi-core.main/src/main/java/org/vexi/plat/AWT.java 2011-01-31 14:02:33 UTC (rev 4009) @@ -531,7 +531,7 @@ private int rootfill = 0x0; private Color rootcolor = null; private final void setBackgroundColor() { - rootfill = root.fillcolor; + rootfill = root.getIntFillcolor(); rootcolor = (rootfill & 0xFF000000) == 0 ? Color.white : new Color((rootfill >> 16) & 0xff, (rootfill >> 8) & 0xff, (rootfill) & 0xff); window.setBackground(rootcolor); @@ -539,7 +539,7 @@ public void render() { // useful optimisation; - if (rootfill != root.fillcolor) { + if (rootfill != root.getIntFillcolor()) { setBackgroundColor(); } // REMARK: it is entirely possible that our initial estimation @@ -672,9 +672,10 @@ synchronized(this) { discoverInsets(); AWTPixelBuffer buf = (AWTPixelBuffer)backbuffer; - buf.g.setColor(new java.awt.Color((root.fillcolor >> 16) & 0xff, - (root.fillcolor >> 8) & 0xff, - (root.fillcolor) & 0xff)); + //int rootfill = root.getIntFillcolor(); + buf.g.setColor(new java.awt.Color((rootfill >> 16) & 0xff, + (rootfill >> 8) & 0xff, + (rootfill) & 0xff)); if (pendingWidth < newwidth) { // ______ // | | | Modified: trunk/org.vexi-core.main/src/main/jpp/org/vexi/core/Box.jpp =================================================================== --- trunk/org.vexi-core.main/src/main/jpp/org/vexi/core/Box.jpp 2011-01-26 23:03:05 UTC (rev 4008) +++ trunk/org.vexi-core.main/src/main/jpp/org/vexi/core/Box.jpp 2011-01-31 14:02:33 UTC (rev 4009) @@ -18,7 +18,6 @@ import org.ibex.util.Callable; import org.ibex.util.Logger; import org.vexi.graphics.Color; -import org.vexi.graphics.Picture; import org.vexi.graphics.PixelBuffer; import org.vexi.util.BasicTree; import org.vexi.util.Log; @@ -226,6 +225,10 @@ private final void clear(int mask) { flags &= ~mask; } private final boolean test(int mask) { return ((flags & mask) == mask); } + public final int getIntFillcolor() { + return renderprops.fillcolor; + } + /** for Surface to set the x/y properties of the root box */ protected final void setRootPosition(int x, int y) throws JSExn { //#repeat x/y X_TRAP/Y_TRAP @@ -334,9 +337,7 @@ private short trapflags = 0; private BasicTree bt = null; // rendering properties - public int fillcolor = 0x00000000; - private Text text = Text.DEFAULT_TEXT; - private Picture texture = null; + BoxRenderProperties renderprops = BoxRenderProperties.DEFAULT_RENDER_PROPS; // FEATURE: path support //private Path path = null; @@ -361,7 +362,7 @@ protected int y = 0; public int width = 0; public int height = 0; - protected int contentwidth = 0; // == min(maxwidth, max(minwidth, text.width, sum(child.contentwidth))) + protected int contentwidth = 0; // == min(maxwidth, max(minwidth, renderprops.textwidth, sum(child.contentwidth))) protected int contentheight = 0; @@ -378,7 +379,7 @@ return; } // get around sub-sampling of enlarged textures - if (cur.texture != null && !cur.test(TILE_IMAGE)) { + if (cur.renderprops.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 @@ -415,21 +416,27 @@ /** invoked when a resource needed to render ourselves finishes loading */ public Object run(Object o) throws JSExn { - if (texture == null) { + if (renderprops.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 (texture.isLoaded) { + } else if (renderprops.texture.isLoaded) { dirty(); // Tiled images affect contentsize if (test(TILE_IMAGE)) { setConstrain(); } - } else if (texture.loadFailed!=null) { - //JS res = texture.stream; - justTriggerTraps(SC_fill, texture.loadFailed.getObject()); - texture = null; + } else if (renderprops.texture.loadFailed!=null) { + //JS res = renderprops.texture.stream; + justTriggerTraps(SC_fill, renderprops.texture.loadFailed.getObject()); + renderprops.resetFill(); + // just in case of previous image / fill + dirty(); + // Tiled images affect contentsize + if (test(TILE_IMAGE)) { + setConstrain(); + } //throw new JSExn("Image not found: "+res.unclone()); } else { Main.SCHEDULER.add(this); @@ -548,17 +555,15 @@ static protected final void reflowTreeTextSize(Box box) throws JSExn { box.set(CONSTRAIN_DESCENDENT); box.set(PLACE_DESCENDENT); - if (box.text.pointsize<6) { - if (box.text!=Text.DEFAULT_TEXT) { - box.text.setSize(); + if (box.renderprops.fontsize<6) { + if (box.renderprops!=BoxRenderProperties.DEFAULT_RENDER_PROPS) { + box.renderprops.resetFontsize(); } - if (box.text.width!=0) { + if (box.renderprops.textwidth!=0) { box.set(CONSTRAIN); box.set(PLACE); } - if (box.text.fontsize_trap) { - box.justTriggerTraps(SC_fontsize, Text.sizeToJS(box.text.pointsize)); - } + box.justTriggerTraps(SC_fontsize, BoxRenderProperties.sizeToJS(box.renderprops.fontsize)); } int i=0; for (Box b = box.getChild(i); b!=null; b=box.getChild(++i)) { @@ -655,16 +660,16 @@ clear(HAS_WIDTH_SLACK); } } else { - if (newwidth < maxwidth && (newwidth < minwidth || newwidth < text.width || (texture!=null && newwidth < texture.width))) { + if (newwidth < maxwidth && (newwidth < minwidth || newwidth < renderprops.textwidth || (renderprops.texture!=null && newwidth < renderprops.texture.width))) { set(HAS_WIDTH_SLACK); } else { clear(HAS_WIDTH_SLACK); } // constrain contentwidth - if (texture != null) { - newwidth = max(newwidth, texture.width); + if (renderprops.texture != null) { + newwidth = max(newwidth, renderprops.texture.width); } - newwidth = max(newwidth, text.width); + newwidth = max(newwidth, renderprops.textwidth); } newwidth = min(maxwidth, max(minwidth, newwidth)); @@ -1029,19 +1034,19 @@ if (parent == null) { // disregard transparency for root - buf.fillTrapezoid(cx1, cx2, cy1, cx1, cx2, cy2, fillcolor|0xFF000000); - } else if ((fillcolor & 0xFF000000) != 0x00000000) { + buf.fillTrapezoid(cx1, cx2, cy1, cx1, cx2, cy2, renderprops.fillcolor|0xFF000000); + } else if ((renderprops.fillcolor & 0xFF000000) != 0x00000000) { // normal color fill, skipping fully transparent fills - buf.fillTrapezoid(cx1, cx2, cy1, cx1, cx2, cy2, fillcolor); + buf.fillTrapezoid(cx1, cx2, cy1, cx1, cx2, cy2, renderprops.fillcolor); } - if (texture != null && texture.isLoaded) { - int tw = texture.width; - int th = texture.height; + if (renderprops.texture != null && renderprops.texture.isLoaded) { + int tw = renderprops.texture.width; + int th = renderprops.texture.height; if (test(TILE_IMAGE)) { for (int x = globalx; x < cx2; x += tw) { for (int y = globaly; y < cy2; y += th) { - buf.drawPicture(texture, x, y, cx1, cy1, cx2, cy2); + buf.drawPicture(renderprops.texture, x, y, cx1, cy1, cx2, cy2); } } } else { @@ -1049,18 +1054,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(texture, cx1, cy1, cx2, cy2, sx1, sy1, sx2, sy2); + buf.drawPicture(renderprops.texture, cx1, cy1, cx2, cy2, sx1, sy1, sx2, sy2); } } - // REMARK: text.font may still be null at this point so - // cannot use text.isEmpty() but instead use text.width - if (text.width != 0) { - int gap_x = width - text.width; - int gap_y = height - text.height; + // 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; 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); - text.font.rasterizeGlyphs(text.str.toString(), buf, text.color, text_x, text_y, cx1, cy1, cx2, cy2); + renderprops.font.rasterizeGlyphs(renderprops.text.toString(), buf, renderprops.textcolor, text_x, text_y, cx1, cy1, cx2, cy2); } //if (path != null) path.realize(Affine.translate(globalx, globaly)).stroke(buf, 1, strokecolor); @@ -1316,40 +1321,7 @@ dirty(); } - /** set the fill of a box according to 'value' */ - private void setFill(JS value) throws JSExn { - if (value == null) { - // set fillcolor to be transparent - if (texture == null && fillcolor == 0) { - return; - } - texture = null; - fillcolor = 0; - } else if (JSU.isString(value)) { - // use as a hex colour value - int newfillcolor = Color.stringToColor(JSU.toString(value)); - if (newfillcolor == fillcolor) { - return; - } - fillcolor = newfillcolor; - texture = null; - } else { - // stream fill - load texture - Picture newtex = Picture.load(value, this); - if (texture == newtex) { - return; - } - texture = newtex; - fillcolor = 0; - if (texture != null && texture.isLoaded) { - run(null); - } - } - // request re-render - dirty(); - } - // Event Handling ///////////////////////////////////////////////// /** initiate a move event - should only ever be invoked by surface or sendEvent */ @@ -1769,7 +1741,7 @@ case "path": if (path != null) return JSU.S(path.toString()); String ret = ""; - for(int i=0; i<text.str.length(); i++) ret += font.glyphs[text.str.charAt(i)].path; + for(int i=0; i<renderprops.str.length(); i++) ret += font.glyphs[renderprops.str.charAt(i)].path; return JSU.S(ret); case "strokecolor": return JSU.S(Color.colorToString(strokecolor)); case "strokewidth": return JSU.N(strokewidth); @@ -1807,10 +1779,10 @@ * @type(String<br/>Stream) * */ case "fill": - if (texture == null) { - return JSU.S(Color.colorToString(fillcolor)); + if (renderprops.texture == null) { + return JSU.S(Color.colorToString(renderprops.fillcolor)); } - return texture.stream; + return renderprops.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 @@ -1820,7 +1792,7 @@ * @initial_value(vexi.ui.font.vera) * @nofollow * */ - case "font": return text.font.stream; + case "font": return renderprops.font.stream; /* <p>The size, either in points or relative size, to render the text.</p> * @@ -1841,7 +1813,7 @@ * @type(Number) * @initial_value("medium") * */ - case "fontsize": return Text.sizeToJS(text.pointsize); + case "fontsize": return BoxRenderProperties.sizeToJS(renderprops.fontsize); /* <p>The text of a box. Visually <code>null</code> renders the same as the text to "" * (i.e as nothing).</p> @@ -1850,7 +1822,7 @@ * @type(String) * @nofollow * */ - case "text": return text.str; + case "text": return renderprops.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> @@ -1864,7 +1836,7 @@ * @initial_value("#ffffff") * @type(String) * */ - case "textcolor": return JSU.S(Color.colorToString(text.color)); + case "textcolor": return JSU.S(Color.colorToString(renderprops.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 @@ -2397,62 +2369,52 @@ throw new JSExn("Attempt to put a non-stream to the 'font' property of a box"); } if (value == null) { - if (text.isDefaultStream()) { + if (!renderprops.resetStream()) { return; } - text.setStream(); } else { Fountain fontstream = (Fountain)value.unclone(); - if (text.font.stream == fontstream) { + if (!renderprops.setStream(fontstream, this)) { return; } - text = text.setStream(fontstream); } - if (!text.isEmpty()) { + if (!renderprops.isEmpty()) { setConstrain(); dirty(); } case "fontsize": if (value==null) { - if (text.isDefaultSize()) { + if (!renderprops.resetFontsize()) { return; } - text.setSize(); } else { - int ps = Text.jsToSize(value); - if (ps == text.pointsize) { + if (!renderprops.setFontsize(value, this)) { return; } - text = text.setSize(ps); } - if (!text.isEmpty()) { + if (!renderprops.isEmpty()) { setConstrain(); dirty(); } case "text": - JSString s = value instanceof JSString ? (JSString)value : - (value==null ? Text.EMPTY_STRING : (JSString)JSU.S(JSU.toString(value))); - if (s.equals(text.str)) { - return; + JSString s = value == null ? null : + value instanceof JSString ? (JSString)value : (JSString)JSU.S(JSU.toString(value)); + if (renderprops.setString(s, this)) { + setConstrain(); + dirty(); } - text = text.setString(s); - setConstrain(); - dirty(); case "textcolor": try { if (value==null) { - if (text.isDefaultColor()) { + if (!renderprops.resetColor()) { return; } - text = text.setColor(); } else { - int c = Color.stringToColor(JSU.toString(value)); - if (!text.isDefaultColor() && c==text.color) { + if (!renderprops.setColor(value, this)) { return; } - text = text.setColor(c); } - if (!text.isEmpty()) { + if (!renderprops.isEmpty()) { dirty(); } } catch (ClassCastException cce) { @@ -2560,11 +2522,17 @@ } } case "align": setAlign(value); - case "fill": setFill(value); + case "fill": + if (value == null && renderprops.texture != null && test(TILE_IMAGE)) { + setConstrain(); + } + if (renderprops.setFill(value, this)) { + dirty(); + } case "tile": if (CHECKSET_FLAG(TILE_IMAGE)) { dirty(); - if (texture != null && texture.isLoaded) { + if (renderprops.texture != null && renderprops.texture.isLoaded) { if (test(TILE_IMAGE)) { run(null); } else { @@ -2870,16 +2838,8 @@ case "Leave": set(LEAVE_TRAP); case "_Move": set(_MOVE_TRAP); case "Move": set(MOVE_TRAP); - case "fontsize": - if (text == Text.DEFAULT_TEXT) { - text = new Text(); - } - text.fontsize_trap = true; - case "font": - if (text == Text.DEFAULT_TEXT) { - text = new Text(); - } - text.font_trap = true; + case "fontsize": renderprops.setTrapFontsize(this); + case "font": renderprops.setTrapFont(this); case "shrink": set(SHRINK_TRAP); case "hshrink": set(HSHRINK_TRAP); case "vshrink": set(VSHRINK_TRAP); @@ -2916,8 +2876,8 @@ case "Leave": if (wtrap(SC_Leave) == null) clear(LEAVE_TRAP); case "_Move": if (wtrap(SC__Move) == null) clear(_MOVE_TRAP); case "Move": if (wtrap(SC_Move) == null) clear(MOVE_TRAP); - case "fontsize": if (wtrap(SC_fontsize) == null && text != Text.DEFAULT_TEXT) text.fontsize_trap = false; - case "font": if (wtrap(SC_font) == null && text != Text.DEFAULT_TEXT) text.font_trap = false; + 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 "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); Modified: trunk/org.vexi-core.main/src/main/jpp/org/vexi/core/Vexi.jpp =================================================================== --- trunk/org.vexi-core.main/src/main/jpp/org/vexi/core/Vexi.jpp 2011-01-26 23:03:05 UTC (rev 4008) +++ trunk/org.vexi-core.main/src/main/jpp/org/vexi/core/Vexi.jpp 2011-01-31 14:02:33 UTC (rev 4009) @@ -433,7 +433,7 @@ /* The current default textcolor * @initial_value(#000000) * @type(String) */ - case "ui.textcolor": return JSU.S(Color.colorToString(Text.DEFAULT_COLOR)); + case "ui.textcolor": return JSU.S(Color.colorToString(BoxRenderProperties.DEFAULT_COLOR)); /* <p>The current default fontsize, in points.</p> * @@ -444,48 +444,48 @@ * * @initial_value(10) * @type(String) */ - case "ui.fontsize.medium": return JSU.N(Text.MEDIUM_SIZE); + case "ui.fontsize.medium": return JSU.N(BoxRenderProperties.MEDIUM_SIZE); /* Extra extra small offset from the current default fontsize, used when a box's fontsize * is set to <code>"xxsmall"</code> * @initial_value(-8) * @type(String) */ - case "ui.fontsize.xxsmall": return JSU.N(Text.MEDIUM_SIZE+Text.XXSMALL_OFFSET); + case "ui.fontsize.xxsmall": return JSU.N(BoxRenderProperties.MEDIUM_SIZE+BoxRenderProperties.XXSMALL_OFFSET); /* Extra extra small offset from the current default fontsize, used when a box's fontsize * is set to <code>"xsmall"</code> * @initial_value(-4) * @type(String) */ - case "ui.fontsize.xsmall": return JSU.N(Text.MEDIUM_SIZE+Text.XSMALL_OFFSET); + case "ui.fontsize.xsmall": return JSU.N(BoxRenderProperties.MEDIUM_SIZE+BoxRenderProperties.XSMALL_OFFSET); /* Extra extra small offset from the current default fontsize, used when a box's fontsize * is set to <code>"small"</code> * @initial_value(-2) * @type(String) */ - case "ui.fontsize.small": return JSU.N(Text.MEDIUM_SIZE+Text.SMALL_OFFSET); + case "ui.fontsize.small": return JSU.N(BoxRenderProperties.MEDIUM_SIZE+BoxRenderProperties.SMALL_OFFSET); /* Extra extra small offset from the current default fontsize, used when a box's fontsize * is set to <code>"large"</code> * @initial_value(4) * @type(String) */ - case "ui.fontsize.large": return JSU.N(Text.MEDIUM_SIZE+Text.LARGE_OFFSET); + case "ui.fontsize.large": return JSU.N(BoxRenderProperties.MEDIUM_SIZE+BoxRenderProperties.LARGE_OFFSET); /* Extra extra small offset from the current default fontsize, used when a box's fontsize * is set to <code>"xlarge"</code> * @initial_value(8) * @type(String) */ - case "ui.fontsize.xlarge": return JSU.N(Text.MEDIUM_SIZE+Text.XLARGE_OFFSET); + case "ui.fontsize.xlarge": return JSU.N(BoxRenderProperties.MEDIUM_SIZE+BoxRenderProperties.XLARGE_OFFSET); /* Extra extra small offset from the current default fontsize, used when a box's fontsize * is set to <code>"xxlarge"</code> * @initial_value(14) * @type(String) */ - case "ui.fontsize.xxlarge": return JSU.N(Text.MEDIUM_SIZE+Text.XXLARGE_OFFSET); + case "ui.fontsize.xxlarge": return JSU.N(BoxRenderProperties.MEDIUM_SIZE+BoxRenderProperties.XXLARGE_OFFSET); /* The current default font stream * @initial_value(vexi.ui.font.sansserif) * @type(Stream) */ - case "ui.font.defaultstream": return Text.DEFAULT_STREAM; + case "ui.font.defaultstream": return BoxRenderProperties.DEFAULT_STREAM; case "ui.font.install": return METHOD; /* @nofollow */ case "ui.font.installed": return Resources.installedFonts; @@ -619,7 +619,7 @@ case "ui.textcolor": throw new JSExn("not yet implemented"); /* - Text.DEFAULT_COLOR = Color.stringToColor(JSU.toString(value)); + BoxRenderProperties.DEFAULT_COLOR = Color.stringToColor(JSU.toString(value)); // dirty all surfaces for (int i=0; i<Surface.allSurfaces.size(); i++) { ((Surface)Surface.allSurfaces.elementAt(i)).dirty(); @@ -631,10 +631,10 @@ if (6>ps && ps!=0) { throw new JSExn("Minimum font pointsize is 6"); } - if (Text.setDefaultPointsize(ps)) { + if (BoxRenderProperties.setDefaultPointsize(ps)) { // reflow all surfaces - // FIXME: this does not get work for Boxes with Text where - // the Boxes box tree is not currently assigned a Surface + // FIXME: this does not get work for Boxes with text where + // the Box's box tree is not currently assigned a Surface for (int i=0; i<Surface.allSurfaces.size(); i++) { Surface s = (Surface)Surface.allSurfaces.elementAt(i); Box.reflowTreeTextSize(s.root); @@ -645,7 +645,7 @@ case "ui.font.defaultstream": throw new JSExn("not yet implemented"); /* - Text.DEFAULT_STREAM = (Fountain)value.unclone(); + BoxRenderProperties.DEFAULT_STREAM = (Fountain)value.unclone(); // reflow all surfaces for (int i=0; i<Surface.allSurfaces.size(); i++) { Box.reflowTree(((Surface)Surface.allSurfaces.elementAt(i)).root); @@ -745,14 +745,14 @@ //#switch(JSU.toString(method)) case "ui.font.height": try { - return JSU.N(Font.getFont(args[0], Text.jsToPointsize(args[1])).textheight(JSU.toString(args[2]))); + return JSU.N(Font.getFont(args[0], BoxRenderProperties.jsToPointsize(args[1])).textheight(JSU.toString(args[2]))); } catch (Exception e) { throw new JSExn("called vexi.ui.font.height with illegal arguments"); } case "ui.font.wait": throw new Error("FIXME: vexi.ui.font.wait not implemented"); case "ui.font.width": try { - return JSU.N(Font.getFont(args[0], Text.jsToPointsize(args[1])).textwidth(JSU.toString(args[2]))); + return JSU.N(Font.getFont(args[0], BoxRenderProperties.jsToPointsize(args[1])).textwidth(JSU.toString(args[2]))); } catch (Exception e) { throw new JSExn("called vexi.ui.font.width with illegal arguments"); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------------ Special Offer-- Download ArcSight Logger for FREE (a $49 USD value)! Finally, a world-class log management solution at an even better price-free! Download using promo code Free_Logger_4_Dev2Dev. Offer expires February 28th, so secure your free ArcSight Logger TODAY! http://p.sf.net/sfu/arcsight-sfd2d _______________________________________________ Vexi-svn mailing list Vexi-svn@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/vexi-svn