if (image != null)
if ((flags & TILE_FLAG) != 0) renderTiledImage(globalx, globaly, clipx, clipy, clipw, cliph, buf);
- else renderStretchedImage(globalx, globaly, clipx, clipy, clipw, cliph, buf);
+ else buf.drawPicture(image, globalx, globaly, clipx, clipy, clipx + clipw, clipy + cliph);
if (text != null && !text.equals(""))
renderText(globalx, globaly, clipx, clipy, clipw, cliph, buf);
}
}
- void renderStretchedImage(int globalx, int globaly, int clipx, int clipy, int clipw, int cliph, PixelBuffer buf) {
- // FIXME: wrong
- buf.drawPicture(image, clipx, clipy, clipx + clipw, clipy + cliph, 0, 0, image.getWidth(), image.getHeight());
- }
-
void renderTiledImage(int globalx, int globaly, int x, int y, int w, int h, PixelBuffer buf) {
+ /*
+ FIXME
int iw = image.getWidth();
int ih = image.getHeight();
for(int i=(x - x)/iw; i <= (x + w - x)/iw; i++) {
buf.drawPicture(image, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2);
}
}
+ */
}
void renderText(int x, int y, int clipx, int clipy, int clipw, int cliph, PixelBuffer buf) {
buf.drawPictureAlphaOnly(g.p,
x,
y + g.max_ascent - g.baseline + g.max_descent,
+ x,
+ y + g.max_ascent - g.baseline + g.max_descent,
x + g.p.getWidth(),
y + g.max_ascent - g.baseline + g.max_descent + g.p.getHeight(),
- 0, 0,
- g.p.getWidth(), g.p.getHeight(),
textcolor);
x += g.advance;
}
public Object get(Box b) { return b; }
public void put(Box b, Object value) {
if (value == null) b.remove();
- else if (value.equals("window") || value.equals("frame")) Platform.createSurface(b, value.equals("frame"), true);
else if (Log.on) Log.log(this, "put invalid value to 'thisbox' property: " + value);
}
});
});
//#end
- //#repeat width/height minwidth/minheight maxwidth/maxheight
+ //#repeat width/height height/width minwidth/minheight maxwidth/maxheight true/false
specialBoxProperties.put("width", new SpecialBoxProperty() {
public Object get(Box b) { return new Integer(b.width); }
public void put(Box b, Object value) {
- int width = stoi(value);
+ int newval = stoi(value);
if (b.parent == null && b.surface != null) {
- b.width = width;
- b.surface.setSize();
+ // hack to circumvent #repeat
+ int other = b.height;
+ if (true) b.surface.setSize(newval, other);
+ else b.surface.setSize(other, newval);
MARK_FOR_REFLOW_b;
} else {
- if (b.minwidth == width && b.maxwidth == width) return;
- b.minwidth = b.maxwidth = width;
+ if (b.minwidth == newval && b.maxwidth == newval) return;
+ b.minwidth = b.maxwidth = newval;
MARK_FOR_REFLOW_b;
}
} });
} });
specialBoxProperties.put("image", new SpecialBoxProperty() {
- /* FIXME
- public Object get(Box b) { return b.image == null ? null : ImageDecoder.imageToNameMap.get(b.image); }
- */
+ public Object get(Box b) { return b.image == null ? null : b.image.res; }
public void put(Box b, Object value) {
- //if (image != null) System.out.println("hit");
if (value == null) {
b.image = null;
} else if (value instanceof Res) {
Glyph ret = (Glyph)glyphCache.get(res, new Integer((((int)c) << 16) | pointsize));
if (ret != null) return ret;
+ ThreadMessage.fakeBackground = true;
// FEATURE: be smarter here
- if (c < 256) Freetype.renderGlyphs(res, pointsize, 0, 255, glyphCache);
+ if (c >= 32 && c < 127) Freetype.renderGlyphs(res, pointsize, 32, 126, glyphCache);
else Freetype.renderGlyphs(res, pointsize, (int)c, (int)c, glyphCache);
+ ThreadMessage.fakeBackground = false;
ret = (Glyph)glyphCache.get(res, new Integer((((int)c) << 16) | pointsize));
if (ret != null) return ret;
public static java.net.InetAddress originAddr = null;
public static String originHost = null;
public static String origin = null;
-
- public static Res builtin = null;
+
+ public static final Res builtin = new Res.Zip(new Res() {
+ public InputStream getInputStream(String path) { return Platform.getBuiltinInputStream(); } });
+ public static Picture scarImage = null;
public static void printUsage() {
System.err.println("Usage: xwt [-s] [-v] [-l <port>/<url>] source-location [initial-template]");
Platform.forceLoad();
if (Log.on) for(int i=0; i<args.length; i++) Log.log(Main.class, "argument " + i + ": " + args[i]);
- Res zip = new Res() { public InputStream getInputStream(String path) { return Platform.getBuiltinInputStream(); } };
- builtin = new Res.Zip(zip);
-
String initialTemplateName = args.length > startargs + 1 ? args[startargs + 1] : "main";
initialTemplateName = initialTemplateName.replace('/', '.');
origin = args[startargs];
Message.Q.startQ();
ThreadMessage.newthread(new JS.Callable() {
public Object call(JS.Array args) {
+ scarImage = Picture.fromRes((Res)Main.builtin.get("org/xwt/builtin/scar.png"));
Template.getTemplate(((Res)final_rr.get(initialTemplate))).apply(new Box(), null, xwt);
return null;
}
private static Cache cache = new Cache();
private static GIF gif = new GIF();
- private static PNG png = new PNG();
/** turns a resource into a Picture.Source */
public static Picture fromRes(Res r) {
- // FIXME: put self in background thread if needed
Picture ret = (Picture)cache.get(r);
if (ret == null) {
try {
int c = pbis.read();
pbis.unread(c);
if (c == 'G') ret = gif.fromInputStream(pbis, r.getDescriptiveName());
- else if (c == 137) ret = png.fromInputStream(pbis, r.getDescriptiveName());
+ else if (c == 137) ret = new PNG().fromInputStream(pbis, r.getDescriptiveName());
else if (c == 0xff) ret = Platform.decodeJPEG(pbis, r.getDescriptiveName());
else throw new JS.Exn("couldn't figure out image type from first byte");
cache.put(r, ret);
+ ret.res = r;
} catch (IOException e) {
Log.logJS(Picture.class, e);
return null;
return ret;
}
+ /** the resource that created this Picture */
+ public Res res = null;
+
/** the height of the picture */
public abstract int getHeight();
*/
public abstract class PixelBuffer {
- /** Draw the region of source within s onto the region d on this PixelBuffer, scaling as needed */
- public abstract void drawPicture(Picture source, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2);
+ /** draw the picture at (dx1, dy1), cropping to (cx1, cy1, cx2, cy2) */
+ public abstract void drawPicture(Picture source, int dx1, int dy1, int cx1, int cy1, int cx2, int cy2);
/** fill a trapezoid whose top and bottom edges are horizontal */
public abstract void fillTrapezoid(int x1, int x2, int y1, int x3, int x4, int y2, int color);
* channels of the Picture in the process. This method may assume that the RGB channels of the image are all zero IFF it
* restores this invariant before returning.
*/
- public abstract void drawPictureAlphaOnly(Picture source, int dx1, int dy1, int dx2, int dy2,
- int sx1, int sy1, int sx2, int sy2, int rgb);
+ public abstract void drawPictureAlphaOnly(Picture source, int dx1, int dy1, int cx1, int cy1, int cx2, int cy2, int rgb);
// FIXME: we want floats (inter-pixel spacing) for antialiasing, but this hoses the fastpath line drawing... argh!
/** draws a line of width <tt>w</tt>; note that the coordinates here are <i>post-transform</i> */
else if (!version.startsWith("1.0") && !version.startsWith("1.1")) platform_class = "Java2";
/*
- // Disable 2d hardware acceleration on Jaguar
- if (os_name.equals("Mac OS X") && os_version.equals("10.2"))
+ // Disable 2d hardware acceleration on Jaguar
+ if (os_name.equals("Mac OS X") && os_version.startsWith("10.2")) System.setProperty("com.apple.hwaccel", "false");
*/
- System.setProperty("com.apple.hwaccel", "false");
if (platform_class != null) {
platform = (Platform)Class.forName("org.xwt.plat." + platform_class).newInstance();
public static class HTTP extends CachedRes {
private String url;
HTTP(String url) { this.url = url; }
+ public String getDescriptiveName() { return url; }
public InputStream _getInputStream(String path) throws IOException {
return new org.xwt.HTTP(url + path).GET(); }
}
public static class ByteArray extends Res {
private byte[] bytes;
ByteArray(byte[] bytes) { this.bytes = bytes; }
+ public String getDescriptiveName() { return "byte[]"; }
public InputStream getInputStream(String path) throws IOException {
if (!"".equals(path)) throw new JS.Exn("can't get subresources of a byte[] resource");
return new ByteArrayInputStream(bytes);
public static class File extends Res {
private String path;
File(String path) { this.path = path; }
+ public String getDescriptiveName() { return "file://" + path; }
public InputStream getInputStream(String rest) throws IOException {
return new FileInputStream((path + rest).replace('/', java.io.File.separatorChar)); }
}
public static class Zip extends Res {
private Res parent;
Zip(Res parent) { this.parent = parent; }
+ public String getDescriptiveName() { return parent.getDescriptiveName() + "!"; }
public InputStream getInputStream(String path) throws IOException {
if (path.startsWith("/")) path = path.substring(1);
- ZipInputStream zis = new ZipInputStream(parent.getInputStream());
+ InputStream pis = parent.getInputStream();
+ ZipInputStream zis = new ZipInputStream(pis);
ZipEntry ze = zis.getNextEntry();
while(ze != null && !ze.getName().equals(path)) ze = zis.getNextEntry();
if (ze == null) throw new JS.Exn("requested file (" + path + ") not found in archive");
final Res watchee;
JS.Callable callback;
ProgressWatcher(Res watchee, JS.Callable callback) { this.watchee = watchee; this.callback = callback; }
+ public String getDescriptiveName() { return watchee.getDescriptiveName(); }
public InputStream getInputStream(String s) throws IOException {
final InputStream is = watchee.getInputStream(s);
return new FilterInputStream(is) {
public abstract void setInvisible(boolean b); ///< If <tt>b</tt>, make window invisible; otherwise, make it non-invisible.
protected abstract void _setMaximized(boolean b); ///< If <tt>b</tt>, maximize the surface; otherwise, un-maximize it.
protected abstract void _setMinimized(boolean b); ///< If <tt>b</tt>, minimize the surface; otherwise, un-minimize it.
- protected abstract void setSize(int width, int height); ///< Sets the surface's width and height.
public abstract void setLocation(); ///< Set the surface's x/y position to that of the root box
public abstract void setTitleBarText(String s); ///< Sets the surface's title bar text, if applicable
public abstract void setIcon(Picture i); ///< Sets the surface's title bar text, if applicable
public abstract void _dispose(); ///< Destroy the surface
public void setLimits(int min_width, int min_height, int max_width, int max_height) { }
+ protected abstract void _setSize(int width, int height); ///< Sets the surface's width and height.
+ protected final void setSize(int width, int height) {
+ if (root.width != width || root.height != height) {
+ root.dirty(0, root.height - Main.scarImage.getHeight(), Main.scarImage.getWidth(), Main.scarImage.getHeight());
+ root.width = Math.max(Main.scarImage.getWidth(), width);
+ root.height = Math.max(Main.scarImage.getHeight(), height);
+ }
+ _setSize(root.width, root.height);
+ }
// Helper methods for subclasses ////////////////////////////////////////////////////////////
// Other Methods ///////////////////////////////////////////////////////////////////////////////
- /** wrapper for setSize() which makes sure to dirty the place where the scar used to be */
- void setSize() {
- root.width = Math.max(root.width, 10);
- root.height = Math.max(root.height, 10);
- setSize(root.width, root.height);
- }
-
/** Indicates that the Surface is no longer needed */
public final void dispose(boolean quitIfAllSurfacesGone) {
if (Log.on) Log.log(this, "disposing " + this);
do {
abort = false;
root.reflow();
- setSize();
+ setSize(root.width, root.height);
// update mouseinside and trigger Enter/Leave as a result of box size/position changes
String oldcursor = cursor;
cursor = "default";
if (w <= 0 || h <= 0) continue;
root.render(0, 0, x, y, w, h, this, identity);
+ drawPicture(Main.scarImage,
+ 0, root.height - Main.scarImage.getHeight(),
+ x, y, w, h);
if (abort) {
PixelBuffer backbuffer = Platform.createPixelBuffer(Platform.getScreenWidth(), Platform.getScreenHeight(), this);
DirtyList screenDirtyRegions = new DirtyList();
- public void drawPicture(Picture source, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2) {
- screenDirtyRegions.dirty(dx1, dy1, dx2 - dx1, dy2 - dy1);
- backbuffer.drawPicture(source, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2); }
+ public void drawPicture(Picture source, int dx, int dy, int cx1, int cy1, int cx2, int cy2) {
+ screenDirtyRegions.dirty(cx1, cy1, cx2 - cx1, cy2 - cy1);
+ backbuffer.drawPicture(source, dx, dy, cx1, cy1, cx2, cy2);
+ }
- public void drawPictureAlphaOnly(Picture source,
- int dx1, int dy1, int dx2, int dy2,
- int sx1, int sy1, int sx2, int sy2,
- int argb) {
- screenDirtyRegions.dirty(dx1, dy1, dx2 - dx1, dy2 - dy1);
- backbuffer.drawPictureAlphaOnly(source, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, argb); }
+ public void drawPictureAlphaOnly(Picture source, int dx, int dy, int cx1, int cy1, int cx2, int cy2, int argb) {
+ screenDirtyRegions.dirty(cx1, cy1, cx2 - cx1, cy2 - cy1);
+ backbuffer.drawPictureAlphaOnly(source, dx, dy, cx1, cy1, cx2, cy2, argb);
+ }
public void fillTrapezoid(int x1, int x2, int y1, int x3, int x4, int y2, int color) {
screenDirtyRegions.dirty(Math.min(x1, x3), y1, Math.max(x2, x4) - Math.min(x1, x3), y2 - y1);
* this invariant.
*/
public class ThreadMessage extends Thread implements Message {
+
+ public static boolean fakeBackground = false;
private volatile static int threadcount = 0;
/** attempts to put this thread into the background to perform a blocking operation; returns false if unable to do so */
public static boolean suspendThread() {
+ if (fakeBackground) return true;
// put ourselves in the background
Thread thread = Thread.currentThread();
if (!(thread instanceof ThreadMessage)) {
/** re-enqueues this thread */
public static void resumeThread() {
+ if (fakeBackground) return;
ThreadMessage mythread = (ThreadMessage)Thread.currentThread();
Message.Q.add(mythread);
mythread.setPriority(Thread.NORM_PRIORITY);
public void put(Object name, Object value) {
if (name.equals("thread") && value != null && value instanceof JS.Callable) ThreadMessage.newthread((JS.Callable)value);
else if (name.equals("clipboard")) Platform.setClipBoard(value.toString());
+ else if (name.equals("frame")) Platform.createSurface((Box)value, true, true);
+ else if (name.equals("window")) Platform.createSurface((Box)value, false, true);
else if (name.equals("proxyAuthorization")) {
HTTP.Proxy.Authorization.authorization = value.toString();
HTTP.Proxy.Authorization.waitingForUser.release();