X-Git-Url: http://git.megacz.com/?p=org.ibex.core.git;a=blobdiff_plain;f=src%2Forg%2Fibex%2Fgraphics%2FSurface.java;h=ebf4670fd656024da0e7d13514f865955e01ffaf;hp=574cc35d503c339f8847d35aace1be56562064b6;hb=05d23fde131a7d19b378c632c6cc6b7924d8ab4d;hpb=76982fccac3c46ccc47621dd22dc0c96b6b9cd62 diff --git a/src/org/ibex/graphics/Surface.java b/src/org/ibex/graphics/Surface.java index 574cc35..ebf4670 100644 --- a/src/org/ibex/graphics/Surface.java +++ b/src/org/ibex/graphics/Surface.java @@ -1,11 +1,13 @@ -// Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL] +// Copyright 2000-2005 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.ibex.graphics; import org.ibex.js.*; import org.ibex.util.*; import org.ibex.plat.*; - -import org.ibex.core.*; // FIXME +import org.ibex.core.*; /** * A Surface, as described in the Ibex Reference. @@ -13,14 +15,14 @@ import org.ibex.core.*; // FIXME * Platform subclasses should include an inner class subclass of * Surface to return from the Platform._createSurface() method */ -public abstract class Surface extends PixelBuffer implements Task { +public abstract class Surface implements Callable { // Static Data //////////////////////////////////////////////////////////////////////////////// - private static final JS T = JS.T; - private static final JS F = JS.F; + private static final JS T = JSU.T; + private static final JS F = JSU.F; - /** all instances of Surface which need to be refreshed by the Scheduler */ + /** all instances of Surface which need to be refreshed by the Platform.Scheduler */ public static Vec allSurfaces = new Vec(); /** When set to true, render() should abort as soon as possible and restart the rendering process */ @@ -64,6 +66,7 @@ public abstract class Surface extends PixelBuffer implements Task { // Methods to be overridden by subclasses /////////////////////////////////////////////////////// + public abstract PixelBuffer getPixelBuffer(); ///< returns a PixelBuffer representing this Surface public abstract void toBack(); ///< should push surface to the back of the stacking order public abstract void toFront(); ///< should pull surface to the front of the stacking order public abstract void syncCursor(); ///< set the actual cursor to this.cursor if they do not match @@ -93,13 +96,14 @@ public abstract class Surface extends PixelBuffer implements Task { if (button == 1) new Message("_Press1", T, root); else if (button == 2) new Message("_Press2", T, root); else if (button == 3) { - Scheduler.add(new Task() { public void perform() throws JSExn { + Platform.Scheduler.add(new Callable() { public Object run(Object o) throws JSExn { Platform.clipboardReadEnabled = true; try { - root.putAndTriggerTraps(JS.S("_Press3"), T); + root.putAndTriggerTraps(JSU.S("_Press3"), T); } finally { Platform.clipboardReadEnabled = false; } + return null; }}); } } @@ -130,11 +134,11 @@ public abstract class Surface extends PixelBuffer implements Task { } } - private final static JS MOVE = JS.S("_Move"); - /** we enqueue ourselves in the Scheduler when we have a Move message to deal with */ - private Task mover = new Task() { - public void perform() { - if (mousex == newmousex && mousey == newmousey) return; + private final static JS MOVE = JSU.S("_Move"); + /** we enqueue ourselves in the Platform.Scheduler when we have a Move message to deal with */ + private Callable mover = new Callable() { + public Object run(Object o) { + if (mousex == newmousex && mousey == newmousey) return null; int oldmousex = mousex; mousex = newmousex; int oldmousey = mousey; mousey = newmousey; String oldcursor = cursor; cursor = "default"; @@ -142,6 +146,7 @@ public abstract class Surface extends PixelBuffer implements Task { if (oldmousex != mousex || oldmousey != mousey) root.putAndTriggerTrapsAndCatchExceptions(MOVE, T); if (!cursor.equals(oldcursor)) syncCursor(); + return null; } }; /** @@ -153,13 +158,13 @@ public abstract class Surface extends PixelBuffer implements Task { protected final void Move(final int newmousex, final int newmousey) { this.newmousex = newmousex; this.newmousey = newmousey; - Scheduler.add(mover); + Platform.Scheduler.add(mover); } - protected final void HScroll(int pixels) { new Message("_HScroll", JS.N(pixels), root); } - protected final void VScroll(int pixels) { new Message("_VScroll", JS.N(pixels), root); } - protected final void HScroll(float lines) { new Message("_HScroll", JS.N(lines), root); } - protected final void VScroll(float lines) { new Message("_VScroll", JS.N(lines), root); } + protected final void HScroll(int pixels) { new Message("_HScroll", JSU.N(pixels), root); } + protected final void VScroll(int pixels) { new Message("_VScroll", JSU.N(pixels), root); } + protected final void HScroll(float lines) { new Message("_HScroll", JSU.N(lines), root); } + protected final void VScroll(float lines) { new Message("_VScroll", JSU.N(lines), root); } /** subclasses should invoke this method when the user resizes the window */ protected final void SizeChange(final int width, final int height) { @@ -168,30 +173,31 @@ public abstract class Surface extends PixelBuffer implements Task { pendingHeight = height; syncRootBoxToSurface = true; abort = true; - Scheduler.renderAll(); + Refresh(); } // FEATURE: can we avoid creating objects here? protected final void PosChange(final int x, final int y) { - Scheduler.add(new Task() { public void perform() throws JSExn { + Platform.Scheduler.add(new Callable() { public Object run(Object o) throws JSExn { root.x = x; root.y = y; - root.putAndTriggerTrapsAndCatchExceptions(JS.S("PosChange"), T); + root.putAndTriggerTrapsAndCatchExceptions(JSU.S("PosChange"), T); + return null; }}); } private final String[] doubleClick = new String[] { null, "_DoubleClick1", "_DoubleClick2", "_DoubleClick3" }; protected final void DoubleClick(int button) { new Message(doubleClick[button], T, root); } - protected final void KeyPressed(String key) { new Message("_KeyPressed", JS.S(key), root); } - protected final void KeyReleased(String key) { new Message("_KeyReleased", JS.S(key), root); } + protected final void KeyPressed(String key) { new Message("_KeyPressed", JSU.S(key), root); } + protected final void KeyReleased(String key) { new Message("_KeyReleased", JSU.S(key), root); } protected final void Close() { new Message("Close", T, root); } protected final void Minimized(boolean b) { minimized = b; new Message("Minimized", b ? T : F, root); } protected final void Maximized(boolean b) { maximized = b; new Message("Maximized", b ? T : F, root); } protected final void Focused(boolean b) { new Message("Focused", b ? T : F, root); } private boolean scheduled = false; - public void Refresh() { if (!scheduled) Scheduler.add(this); scheduled = true; } - public void perform() { scheduled = false; Scheduler.renderAll(); } + public void Refresh() { if (!scheduled) Platform.Scheduler.add(this); scheduled = true; } + public Object run(Object o) { scheduled = false; Platform.Scheduler.renderAll(); return null; } public final void setMaximized(boolean b) { if (b != maximized) _setMaximized(maximized = b); } public final void setMinimized(boolean b) { if (b != minimized) _setMinimized(minimized = b); } @@ -210,10 +216,9 @@ public abstract class Surface extends PixelBuffer implements Task { } } - public void dirty(int x, int y, int w, int h) { - dirtyRegions.dirty(x, y, w, h); - Refresh(); - } + // This is how subclasses signal a 'shallow dirty', indicating that although the backbuffer is valid, the screen is not + public void Dirty(int x, int y, int w, int h) { dirty(x,y,w,h); } + public void dirty(int x, int y, int w, int h) { dirtyRegions.dirty(x, y, w, h); Refresh(); } public static Surface fromBox(Box b) { // FIXME use a hash table here @@ -270,7 +275,7 @@ public abstract class Surface extends PixelBuffer implements Task { setSize(rootwidth, rootheight); /*String oldcursor = cursor; cursor = "default"; - root.putAndTriggerTrapsAndCatchExceptions("_Move", JS.T); + root.putAndTriggerTrapsAndCatchExceptions("_Move", JSU.T); if (!cursor.equals(oldcursor)) syncCursor();*/ } while(abort); @@ -284,8 +289,8 @@ public abstract class Surface extends PixelBuffer implements Task { if (y+h > root.height) h = root.height - y; if (w <= 0 || h <= 0) continue; - root.render(0, 0, x, y, x + w, y + h, this, identity); - drawPicture(scarImage, 0, root.height - scarImage.height, x, y, x+w, y+h); + root.render(0, 0, x, y, x + w, y + h, this.getPixelBuffer(), identity); + getPixelBuffer().drawPicture(scarImage, 0, root.height - scarImage.height, x, y, x+w, y+h); if (abort) { // x,y,w,h is only partially reconstructed, so we must be careful not to re-blit it @@ -302,7 +307,7 @@ public abstract class Surface extends PixelBuffer implements Task { } // FEATURE: reinstate recycler - public class Message implements Task { + public class Message implements Callable { private Box boxContainingMouse; private JS value; @@ -312,59 +317,77 @@ public abstract class Surface extends PixelBuffer implements Task { this.boxContainingMouse = boxContainingMouse; this.name = name; this.value = value; - Scheduler.add(this); + Platform.Scheduler.add(this); } - public void perform() throws JSExn { + public Object run(Object o) throws JSExn { if (name.equals("_KeyPressed")) { - String value = JS.toString(this.value); + String value = JSU.toString(this.value); if (value.toLowerCase().endsWith("shift")) shift = true; else if (shift) value = value.toUpperCase(); if (value.toLowerCase().equals("alt")) alt = true; else if (alt) value = "A-" + value; if (value.toLowerCase().endsWith("control")) control = true; else if (control) value = "C-" + value; if (value.equals("C-v") || value.equals("A-v")) Platform.clipboardReadEnabled = true; - this.value = JS.S(value); + this.value = JSU.S(value); } else if (name.equals("_KeyReleased")) { - String value = JS.toString(this.value); + String value = JSU.toString(this.value); if (value.toLowerCase().equals("alt")) alt = false; else if (value.toLowerCase().equals("control")) control = false; else if (value.toLowerCase().equals("shift")) shift = false; - this.value = JS.S(value); + this.value = JSU.S(value); } else if (name.equals("_HScroll") || name.equals("_VScroll")) { // FIXME: technically points != pixels - if (JS.isInt(value)) - value = JS.N(JS.toInt(value) * root.fontSize()); + if (JSU.isInt(value)) + value = JSU.N(JSU.toInt(value) * root.fontSize()); } try { - boxContainingMouse.putAndTriggerTrapsAndCatchExceptions(JS.S(name), value); + boxContainingMouse.putAndTriggerTrapsAndCatchExceptions(JSU.S(name), value); } finally { Platform.clipboardReadEnabled = false; } + return null; } - public String toString() { return "Message [name=" + name + ", value=" + value + "]"; } + public String toString() { return "Message [name=" + name + ", value=" + JSU.str(value) + "]"; } } // Default PixelBuffer implementation ///////////////////////////////////////////////////////// - public static abstract class DoubleBufferedSurface extends Surface { + public static abstract class DoubleBufferedSurface extends Surface implements PixelBuffer { public DoubleBufferedSurface(Box root) { super(root); } PixelBuffer backbuffer = Platform.createPixelBuffer(Platform.getScreenWidth(), Platform.getScreenHeight(), this); DirtyList screenDirtyRegions = new DirtyList(); + public PixelBuffer getPixelBuffer() { return this; } 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 drawGlyph(Font.Glyph source, int dx, int dy, int cx1, int cy1, int cx2, int cy2, int argb) { + public void drawGlyph(Font.Glyph source, int dx, int dy, int cx1, int cy1, int cx2, int cy2, int argb, int bc) { screenDirtyRegions.dirty(cx1, cy1, cx2 - cx1, cy2 - cy1); - backbuffer.drawGlyph(source, dx, dy, cx1, cy1, cx2, cy2, argb); + backbuffer.drawGlyph(source, dx, dy, cx1, cy1, cx2, cy2, argb, bc); + } + + public void stroke(Polygon p, int color) { + // FIXME + } + + public void fill(Polygon p, Paint paint) { + // FIXME + } + + public void drawLine(int x1, int y1, int x2, int y2, int color) { + screenDirtyRegions.dirty(x1, y1, x2, y2); + backbuffer.drawLine(x1, y1, x2, y2, color); } + public abstract void _fillTrapezoid(int x1, int x2, int y1, int x3, int x4, int y2, int color); public void fillTrapezoid(int x1, int x2, int y1, int x3, int x4, int y2, int color) { + // we don't dirty trapezoid-fills since it's faster to just do them directly than to copy from the backbuffer screenDirtyRegions.dirty(Math.min(x1, x3), y1, Math.max(x2, x4) - Math.min(x1, x3), y2 - y1); backbuffer.fillTrapezoid(x1, x2, y1, x3, x4, y2, color); + //_fillTrapezoid(x1, x2, y1, x3, x4, y2, color); } public void render() { @@ -387,10 +410,11 @@ public abstract class Surface extends PixelBuffer implements Task { } } - /** This is how subclasses signal a 'shallow dirty', indicating that although the backbuffer is valid, the screen is not */ + // This is how subclasses signal a 'shallow dirty', indicating that although the backbuffer is valid, the screen is not public final void Dirty(int x, int y, int w, int h) { - screenDirtyRegions.dirty(x, y, w, h); - Scheduler.renderAll(); + //screenDirtyRegions.dirty(x, y, w, h); + //Refresh(); + blit(x,y,w,h); } public void dirty(int x, int y, int w, int h) { @@ -398,9 +422,11 @@ public abstract class Surface extends PixelBuffer implements Task { super.dirty(x, y, w, h); } - /** copies a region from the doublebuffer to this surface */ + // copies a region from the doublebuffer to this surface public abstract void blit(PixelBuffer source, int sx, int sy, int dx, int dy, int dx2, int dy2); - + protected void blit(int x, int y, int w, int h) { + blit(backbuffer, x, y, x, y, w + x, h + y); + } } }