Moved html engine

This commit is contained in:
Andrea Cavalli 2018-07-22 23:40:51 +02:00
parent dd9fab3841
commit 20097e1fcb
5 changed files with 752 additions and 752 deletions

View File

@ -1,296 +1,296 @@
package org.warp.picalculator.gui.graphicengine.html;
import java.io.IOException;
import java.util.concurrent.Semaphore;
import org.teavm.jso.JSBody;
import org.teavm.jso.JSObject;
import org.teavm.jso.browser.Window;
import org.teavm.jso.canvas.CanvasGradient;
import org.teavm.jso.canvas.CanvasRenderingContext2D;
import org.teavm.jso.dom.events.Event;
import org.teavm.jso.dom.events.EventListener;
import org.teavm.jso.dom.events.EventTarget;
import org.teavm.jso.dom.events.KeyboardEvent;
import org.teavm.jso.dom.html.HTMLButtonElement;
import org.teavm.jso.dom.html.HTMLCanvasElement;
import org.teavm.jso.dom.html.HTMLDocument;
import org.teavm.jso.dom.html.HTMLElement;
import org.teavm.jso.dom.html.HTMLInputElement;
import org.teavm.jso.dom.xml.NodeList;
import org.teavm.jso.json.JSON;
import org.warp.picalculator.PlatformUtils;
import org.warp.picalculator.Utils;
import org.warp.picalculator.deps.DSemaphore;
import org.warp.picalculator.deps.StorageUtils;
import org.warp.picalculator.device.Keyboard;
import org.warp.picalculator.gui.graphicengine.BinaryFont;
import org.warp.picalculator.gui.graphicengine.GraphicEngine;
import org.warp.picalculator.gui.graphicengine.Renderer;
import org.warp.picalculator.gui.graphicengine.RenderingLoop;
import org.warp.picalculator.gui.graphicengine.Skin;
import org.warp.picalculator.gui.graphicengine.cpu.CPUFont;
import org.warp.picalculator.gui.graphicengine.cpu.CPUSkin;
public class HtmlEngine implements GraphicEngine {
private boolean initialized;
public DSemaphore exitSemaphore = new DSemaphore(0);
private static final HTMLDocument document = Window.current().getDocument();
private HTMLCanvasElement canvas;
private CanvasRenderingContext2D g;
private RenderingLoop renderingLoop;
private HtmlRenderer renderer;
private int width = -1, height = -1;
private final int frameTime = (int) (1000d/10d);
@Override
public int[] getSize() {
return new int[] { getWidth(), getHeight() };
}
@Override
public boolean isInitialized() {
return initialized;
}
@Override
public void setTitle(String title) {
HtmlEngine.setHTMLTitle(title);
}
@JSBody(params = {"wndTitle"}, script = "document.title = wndTitle")
private static native void setHTMLTitle(String wndTitle);
@Override
public void setResizable(boolean r) {}
@Override
public void setDisplayMode(int ww, int wh) {
canvas.setWidth(ww);
width = ww;
canvas.setHeight(wh);
height = wh;
}
private String previousValue="";
@Override
public void create(Runnable onInitialized) {
canvas = (HTMLCanvasElement) document.createElement("canvas");
g = (CanvasRenderingContext2D ) canvas.getContext("2d");
HTMLInputElement keyInput = (HTMLInputElement) document.createElement("input");
keyInput.setType("text");
keyInput.getStyle().setProperty("opacity", "0.1");
setDisplayMode(480, 320);
document.getElementById("container").appendChild(canvas);
document.getBody().appendChild(keyInput);
keyInput.setTabIndex(0);
keyInput.addEventListener("keydown", (KeyboardEvent evt) -> {
evt.preventDefault();
new Thread(() -> {
previousValue = keyInput.getValue();
Keyboard.debugKeyPressed(evt.getKeyCode());
System.out.println(evt.getKeyCode());
System.out.println(""+(int) evt.getKey().charAt(0));
}).start();
});
keyInput.addEventListener("input", (Event evt) -> {
evt.preventDefault();
final String previousValue = this.previousValue;
final String newValue = keyInput.getValue();
final int prevLen = previousValue.length();
final int newLen = newValue.length();
new Thread(() -> {
if (newLen == prevLen) {
} else if (newLen - prevLen == 1) {
Keyboard.debugKeyPressed((int) newValue.toUpperCase().charAt(newLen-1));
} else if (newLen - prevLen > 1) {
for (int i = 0; i < newLen - prevLen; i++) {
Keyboard.debugKeyPressed((int) newValue.toUpperCase().charAt(prevLen + i));
}
} else if (newLen - prevLen < 1) {
for (int i = 0; i < prevLen - newLen; i++) {
Keyboard.debugKeyPressed(8);
}
}
}).start();
});
canvas.addEventListener("click", (Event evt) -> {
keyInput.focus();
});
document.addEventListener("DOMContentLoaded", (Event e) -> {
keyInput.focus();
});
NodeList<? extends HTMLElement> buttons = document.getBody().getElementsByTagName("button");
for (int i = 0; i < buttons.getLength(); i++) {
if (buttons.item(i).hasAttribute("keycode")) {
buttons.item(i).addEventListener("click", (Event evt) -> {
evt.preventDefault();
EventTarget target = evt.getCurrentTarget();
HTMLButtonElement button = target.cast();
new Thread(() -> {
try {
if (button.hasAttribute("keycode") && button.getAttribute("keycode").contains(",")) {
String code = button.getAttribute("keycode");
String[] coordinates = code.split(",", 2);
boolean removeshift = Keyboard.shift && Integer.parseInt(coordinates[0]) != 0 && Integer.parseInt(coordinates[1]) != 0;
boolean removealpha = Keyboard.alpha && Integer.parseInt(coordinates[0]) != 0 && Integer.parseInt(coordinates[1]) != 1;
Keyboard.keyPressedRaw(Integer.parseInt(coordinates[0]), Integer.parseInt(coordinates[1]));
if (removeshift) {
Keyboard.keyPressedRaw(0,0);
}
if (removealpha) {
Keyboard.keyPressedRaw(0,1);
}
Thread.sleep(100);
Keyboard.keyReleasedRaw(Integer.parseInt(coordinates[0]), Integer.parseInt(coordinates[1]));
if (removeshift) {
Keyboard.keyReleasedRaw(0,0);
}
if (removealpha) {
Keyboard.keyReleasedRaw(0,1);
}
} else {
if (Keyboard.alpha && !Keyboard.shift) {
if (button.hasAttribute("keycodea")) {
Keyboard.debugKeyPressed(Integer.parseInt(button.getAttribute("keycodea")));
} else {
Keyboard.debugKeyPressed(Integer.parseInt(button.getAttribute("keycode")));
}
} else if (!Keyboard.alpha && Keyboard.shift) {
if (button.hasAttribute("keycodes")) {
Keyboard.debugKeyPressed(Integer.parseInt(button.getAttribute("keycodes")));
} else {
Keyboard.debugKeyPressed(Integer.parseInt(button.getAttribute("keycode")));
}
} else if (Keyboard.alpha && Keyboard.shift) {
if (button.hasAttribute("keycodesa")) {
Keyboard.debugKeyPressed(Integer.parseInt(button.getAttribute("keycodesa")));
} else {
if (button.hasAttribute("keycodes")) {
Keyboard.debugKeyPressed(Integer.parseInt(button.getAttribute("keycodes")));
} else {
Keyboard.debugKeyPressed(Integer.parseInt(button.getAttribute("keycode")));
}
}
} else {
Keyboard.debugKeyPressed(Integer.parseInt(button.getAttribute("keycode")));
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}).start();
});
}
}
renderer = new HtmlRenderer(this, g);
initialized = true;
if (onInitialized != null) {
onInitialized.run();
}
}
@Override
public boolean wasResized() {
return false;
}
@Override
public int getWidth() {
if (width == -1) {
width = canvas.getWidth();
}
return width;
}
@Override
public int getHeight() {
if (height == -1) {
height = canvas.getHeight();
}
return height;
}
@Override
public void destroy() {
document.getBody().removeChild(canvas);
initialized = false;
exitSemaphore.release();
}
@Override
public void start(RenderingLoop d) {
renderingLoop = d;
final Thread th = new Thread(() -> {
try {
double extratime = 0;
while (initialized) {
final long start = System.currentTimeMillis();
repaint();
final long end = System.currentTimeMillis();
final double delta = (end - start) / 1000d;
final int deltaInt = (int) Math.floor(delta);
final int extraTimeInt = (int) Math.floor(extratime);
if (extraTimeInt + deltaInt < frameTime) {
Thread.sleep(frameTime - (extraTimeInt + deltaInt));
extratime = 0;
} else {
extratime += delta - frameTime;
}
}
} catch (final InterruptedException e) {
e.printStackTrace();
}
});
PlatformUtils.setThreadName(th, "Canvas rendering thread");
PlatformUtils.setDaemon(th);
th.start();
}
@Override
public void repaint() {
renderingLoop.refresh();
}
@Override
public HtmlRenderer getRenderer() {
return renderer;
}
@Override
public HtmlFont loadFont(String fontName) throws IOException {
return new HtmlFont(fontName);
}
@Override
public HtmlFont loadFont(String path, String fontName) throws IOException {
return new HtmlFont(fontName);
}
@Override
public HtmlSkin loadSkin(String file) throws IOException {
return new HtmlSkin(file);
}
@Override
public void waitForExit() {
try {
exitSemaphore.acquire();
} catch (final InterruptedException e) {}
}
@Override
public boolean isSupported() {
return PlatformUtils.isJavascript;
}
@Override
public boolean doesRefreshPauses() {
return true;
}
}
package org.warp.picalculator.gui.graphicengine.html;
import java.io.IOException;
import java.util.concurrent.Semaphore;
import org.teavm.jso.JSBody;
import org.teavm.jso.JSObject;
import org.teavm.jso.browser.Window;
import org.teavm.jso.canvas.CanvasGradient;
import org.teavm.jso.canvas.CanvasRenderingContext2D;
import org.teavm.jso.dom.events.Event;
import org.teavm.jso.dom.events.EventListener;
import org.teavm.jso.dom.events.EventTarget;
import org.teavm.jso.dom.events.KeyboardEvent;
import org.teavm.jso.dom.html.HTMLButtonElement;
import org.teavm.jso.dom.html.HTMLCanvasElement;
import org.teavm.jso.dom.html.HTMLDocument;
import org.teavm.jso.dom.html.HTMLElement;
import org.teavm.jso.dom.html.HTMLInputElement;
import org.teavm.jso.dom.xml.NodeList;
import org.teavm.jso.json.JSON;
import org.warp.picalculator.PlatformUtils;
import org.warp.picalculator.Utils;
import org.warp.picalculator.deps.DSemaphore;
import org.warp.picalculator.deps.StorageUtils;
import org.warp.picalculator.device.Keyboard;
import org.warp.picalculator.gui.graphicengine.BinaryFont;
import org.warp.picalculator.gui.graphicengine.GraphicEngine;
import org.warp.picalculator.gui.graphicengine.Renderer;
import org.warp.picalculator.gui.graphicengine.RenderingLoop;
import org.warp.picalculator.gui.graphicengine.Skin;
import org.warp.picalculator.gui.graphicengine.cpu.CPUFont;
import org.warp.picalculator.gui.graphicengine.cpu.CPUSkin;
public class HtmlEngine implements GraphicEngine {
private boolean initialized;
public DSemaphore exitSemaphore = new DSemaphore(0);
private static final HTMLDocument document = Window.current().getDocument();
private HTMLCanvasElement canvas;
private CanvasRenderingContext2D g;
private RenderingLoop renderingLoop;
private HtmlRenderer renderer;
private int width = -1, height = -1;
private final int frameTime = (int) (1000d/10d);
@Override
public int[] getSize() {
return new int[] { getWidth(), getHeight() };
}
@Override
public boolean isInitialized() {
return initialized;
}
@Override
public void setTitle(String title) {
HtmlEngine.setHTMLTitle(title);
}
@JSBody(params = {"wndTitle"}, script = "document.title = wndTitle")
private static native void setHTMLTitle(String wndTitle);
@Override
public void setResizable(boolean r) {}
@Override
public void setDisplayMode(int ww, int wh) {
canvas.setWidth(ww);
width = ww;
canvas.setHeight(wh);
height = wh;
}
private String previousValue="";
@Override
public void create(Runnable onInitialized) {
canvas = (HTMLCanvasElement) document.createElement("canvas");
g = (CanvasRenderingContext2D ) canvas.getContext("2d");
HTMLInputElement keyInput = (HTMLInputElement) document.createElement("input");
keyInput.setType("text");
keyInput.getStyle().setProperty("opacity", "0.1");
setDisplayMode(480, 320);
document.getElementById("container").appendChild(canvas);
document.getBody().appendChild(keyInput);
keyInput.setTabIndex(0);
keyInput.addEventListener("keydown", (KeyboardEvent evt) -> {
evt.preventDefault();
new Thread(() -> {
previousValue = keyInput.getValue();
Keyboard.debugKeyPressed(evt.getKeyCode());
System.out.println(evt.getKeyCode());
System.out.println(""+(int) evt.getKey().charAt(0));
}).start();
});
keyInput.addEventListener("input", (Event evt) -> {
evt.preventDefault();
final String previousValue = this.previousValue;
final String newValue = keyInput.getValue();
final int prevLen = previousValue.length();
final int newLen = newValue.length();
new Thread(() -> {
if (newLen == prevLen) {
} else if (newLen - prevLen == 1) {
Keyboard.debugKeyPressed((int) newValue.toUpperCase().charAt(newLen-1));
} else if (newLen - prevLen > 1) {
for (int i = 0; i < newLen - prevLen; i++) {
Keyboard.debugKeyPressed((int) newValue.toUpperCase().charAt(prevLen + i));
}
} else if (newLen - prevLen < 1) {
for (int i = 0; i < prevLen - newLen; i++) {
Keyboard.debugKeyPressed(8);
}
}
}).start();
});
canvas.addEventListener("click", (Event evt) -> {
keyInput.focus();
});
document.addEventListener("DOMContentLoaded", (Event e) -> {
keyInput.focus();
});
NodeList<? extends HTMLElement> buttons = document.getBody().getElementsByTagName("button");
for (int i = 0; i < buttons.getLength(); i++) {
if (buttons.item(i).hasAttribute("keycode")) {
buttons.item(i).addEventListener("click", (Event evt) -> {
evt.preventDefault();
EventTarget target = evt.getCurrentTarget();
HTMLButtonElement button = target.cast();
new Thread(() -> {
try {
if (button.hasAttribute("keycode") && button.getAttribute("keycode").contains(",")) {
String code = button.getAttribute("keycode");
String[] coordinates = code.split(",", 2);
boolean removeshift = Keyboard.shift && Integer.parseInt(coordinates[0]) != 0 && Integer.parseInt(coordinates[1]) != 0;
boolean removealpha = Keyboard.alpha && Integer.parseInt(coordinates[0]) != 0 && Integer.parseInt(coordinates[1]) != 1;
Keyboard.keyPressedRaw(Integer.parseInt(coordinates[0]), Integer.parseInt(coordinates[1]));
if (removeshift) {
Keyboard.keyPressedRaw(0,0);
}
if (removealpha) {
Keyboard.keyPressedRaw(0,1);
}
Thread.sleep(100);
Keyboard.keyReleasedRaw(Integer.parseInt(coordinates[0]), Integer.parseInt(coordinates[1]));
if (removeshift) {
Keyboard.keyReleasedRaw(0,0);
}
if (removealpha) {
Keyboard.keyReleasedRaw(0,1);
}
} else {
if (Keyboard.alpha && !Keyboard.shift) {
if (button.hasAttribute("keycodea")) {
Keyboard.debugKeyPressed(Integer.parseInt(button.getAttribute("keycodea")));
} else {
Keyboard.debugKeyPressed(Integer.parseInt(button.getAttribute("keycode")));
}
} else if (!Keyboard.alpha && Keyboard.shift) {
if (button.hasAttribute("keycodes")) {
Keyboard.debugKeyPressed(Integer.parseInt(button.getAttribute("keycodes")));
} else {
Keyboard.debugKeyPressed(Integer.parseInt(button.getAttribute("keycode")));
}
} else if (Keyboard.alpha && Keyboard.shift) {
if (button.hasAttribute("keycodesa")) {
Keyboard.debugKeyPressed(Integer.parseInt(button.getAttribute("keycodesa")));
} else {
if (button.hasAttribute("keycodes")) {
Keyboard.debugKeyPressed(Integer.parseInt(button.getAttribute("keycodes")));
} else {
Keyboard.debugKeyPressed(Integer.parseInt(button.getAttribute("keycode")));
}
}
} else {
Keyboard.debugKeyPressed(Integer.parseInt(button.getAttribute("keycode")));
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}).start();
});
}
}
renderer = new HtmlRenderer(this, g);
initialized = true;
if (onInitialized != null) {
onInitialized.run();
}
}
@Override
public boolean wasResized() {
return false;
}
@Override
public int getWidth() {
if (width == -1) {
width = canvas.getWidth();
}
return width;
}
@Override
public int getHeight() {
if (height == -1) {
height = canvas.getHeight();
}
return height;
}
@Override
public void destroy() {
document.getBody().removeChild(canvas);
initialized = false;
exitSemaphore.release();
}
@Override
public void start(RenderingLoop d) {
renderingLoop = d;
final Thread th = new Thread(() -> {
try {
double extratime = 0;
while (initialized) {
final long start = System.currentTimeMillis();
repaint();
final long end = System.currentTimeMillis();
final double delta = (end - start) / 1000d;
final int deltaInt = (int) Math.floor(delta);
final int extraTimeInt = (int) Math.floor(extratime);
if (extraTimeInt + deltaInt < frameTime) {
Thread.sleep(frameTime - (extraTimeInt + deltaInt));
extratime = 0;
} else {
extratime += delta - frameTime;
}
}
} catch (final InterruptedException e) {
e.printStackTrace();
}
});
PlatformUtils.setThreadName(th, "Canvas rendering thread");
PlatformUtils.setDaemon(th);
th.start();
}
@Override
public void repaint() {
renderingLoop.refresh();
}
@Override
public HtmlRenderer getRenderer() {
return renderer;
}
@Override
public HtmlFont loadFont(String fontName) throws IOException {
return new HtmlFont(fontName);
}
@Override
public HtmlFont loadFont(String path, String fontName) throws IOException {
return new HtmlFont(fontName);
}
@Override
public HtmlSkin loadSkin(String file) throws IOException {
return new HtmlSkin(file);
}
@Override
public void waitForExit() {
try {
exitSemaphore.acquire();
} catch (final InterruptedException e) {}
}
@Override
public boolean isSupported() {
return PlatformUtils.isJavascript;
}
@Override
public boolean doesRefreshPauses() {
return true;
}
}

View File

@ -1,68 +1,68 @@
package org.warp.picalculator.gui.graphicengine.html;
import java.io.IOException;
import org.teavm.jso.browser.Window;
import org.teavm.jso.canvas.CanvasRenderingContext2D;
import org.teavm.jso.dom.html.HTMLCanvasElement;
import org.teavm.jso.dom.html.HTMLDocument;
import org.teavm.jso.dom.html.HTMLImageElement;
import org.teavm.jso.typedarrays.Uint8ClampedArray;
import org.warp.picalculator.StaticVars;
import org.warp.picalculator.gui.graphicengine.GraphicEngine;
import org.warp.picalculator.gui.graphicengine.cpu.CPUFont;
public class HtmlFont extends CPUFont {
public HTMLCanvasElement imgEl;
public CanvasRenderingContext2D imgElCtx;
public HtmlFont(String fontName) throws IOException {
super(fontName);
HTMLDocument doc = Window.current().getDocument();
imgEl = doc.createElement("canvas").cast();
imgEl.setClassName("hidden");
doc.getBody().appendChild(imgEl);
imgElCtx = imgEl.getContext("2d").cast();
imgEl.setWidth(this.charW);
imgEl.setHeight(this.charH * intervalsTotalSize);
int screenPos = 0;
int currentInt;
int currentIntBitPosition;
int bitData;
int j;
imgElCtx.clearRect(0, 0, imgEl.getWidth(), imgEl.getHeight());
imgElCtx.setFillStyle("#000");
int minBound = 0, maxBound = intervalsTotalSize-1;
System.out.println("charIndex:"+0);
System.out.println("minBound"+minBound);
System.out.println("maxBound"+maxBound);
for (int charIndex = minBound; charIndex < maxBound; charIndex++) {
for (int dy = 0; dy < charH; dy++) {
for (int dx = 0; dx < charW; dx++) {
j = dx;
final int bit = dx + dy * charW;
currentInt = (int) (Math.floor(bit) / (HtmlFont.intBits));
currentIntBitPosition = bit - (currentInt * HtmlFont.intBits);
final int charIdx = charIndex * charIntCount + currentInt;
if (charIdx >= 0 && charIdx < chars32.length) {
bitData = (chars32[charIdx] >> currentIntBitPosition) & 1;
if (bitData == 1) {
imgElCtx.fillRect( dx, charIndex*charH+dy, 1, 1 );
}
}
}
}
}
}
@Override
public void use(GraphicEngine d) {
if (d.getRenderer() instanceof HtmlRenderer) {
((HtmlRenderer) d.getRenderer()).f = this;
}
}
}
package org.warp.picalculator.gui.graphicengine.html;
import java.io.IOException;
import org.teavm.jso.browser.Window;
import org.teavm.jso.canvas.CanvasRenderingContext2D;
import org.teavm.jso.dom.html.HTMLCanvasElement;
import org.teavm.jso.dom.html.HTMLDocument;
import org.teavm.jso.dom.html.HTMLImageElement;
import org.teavm.jso.typedarrays.Uint8ClampedArray;
import org.warp.picalculator.StaticVars;
import org.warp.picalculator.gui.graphicengine.GraphicEngine;
import org.warp.picalculator.gui.graphicengine.cpu.CPUFont;
public class HtmlFont extends CPUFont {
public HTMLCanvasElement imgEl;
public CanvasRenderingContext2D imgElCtx;
public HtmlFont(String fontName) throws IOException {
super(fontName);
HTMLDocument doc = Window.current().getDocument();
imgEl = doc.createElement("canvas").cast();
imgEl.setClassName("hidden");
doc.getBody().appendChild(imgEl);
imgElCtx = imgEl.getContext("2d").cast();
imgEl.setWidth(this.charW);
imgEl.setHeight(this.charH * intervalsTotalSize);
int screenPos = 0;
int currentInt;
int currentIntBitPosition;
int bitData;
int j;
imgElCtx.clearRect(0, 0, imgEl.getWidth(), imgEl.getHeight());
imgElCtx.setFillStyle("#000");
int minBound = 0, maxBound = intervalsTotalSize-1;
System.out.println("charIndex:"+0);
System.out.println("minBound"+minBound);
System.out.println("maxBound"+maxBound);
for (int charIndex = minBound; charIndex < maxBound; charIndex++) {
for (int dy = 0; dy < charH; dy++) {
for (int dx = 0; dx < charW; dx++) {
j = dx;
final int bit = dx + dy * charW;
currentInt = (int) (Math.floor(bit) / (HtmlFont.intBits));
currentIntBitPosition = bit - (currentInt * HtmlFont.intBits);
final int charIdx = charIndex * charIntCount + currentInt;
if (charIdx >= 0 && charIdx < chars32.length) {
bitData = (chars32[charIdx] >> currentIntBitPosition) & 1;
if (bitData == 1) {
imgElCtx.fillRect( dx, charIndex*charH+dy, 1, 1 );
}
}
}
}
}
}
@Override
public void use(GraphicEngine d) {
if (d.getRenderer() instanceof HtmlRenderer) {
((HtmlRenderer) d.getRenderer()).f = this;
}
}
}

View File

@ -1,292 +1,292 @@
package org.warp.picalculator.gui.graphicengine.html;
import org.teavm.jso.canvas.CanvasImageSource;
import org.teavm.jso.canvas.CanvasRenderingContext2D;
import org.teavm.jso.dom.html.HTMLImageElement;
import org.teavm.jso.typedarrays.Uint8ClampedArray;
import org.warp.picalculator.StaticVars;
import org.warp.picalculator.gui.graphicengine.Renderer;
public class HtmlRenderer implements Renderer {
private static final boolean ENABLE_SUPERSAMPLING = false;
private static final boolean ENABLE_TRANSPARENCY = true;
private String currentColor = "#000000ff";
private String clearColor = "#000000ff";
HtmlFont f = null;
HtmlSkin currentSkin = null;
private final CanvasRenderingContext2D g;
private final HtmlEngine e;
public HtmlRenderer(HtmlEngine e, CanvasRenderingContext2D g) {
this.g = g;
this.e = e;
}
private String toHex(int c) {
final int a = c >> 24 & 0xFF;
final int r = c >> 16 & 0xFF;
final int gg = c >> 8 & 0xFF;
final int b = c & 0xFF;
return String.format("#%02x%02x%02x%02x", r, gg, b, a);
}
private String toHex8(int c) {
final int r = c >> 16 & 0xFF;
final int gg = c >> 8 & 0xFF;
final int b = c & 0xFF;
return String.format("#%02x%02x%02x", r, gg, b);
}
private String toHex(int r, int g, int b) {
return String.format("#%02x%02x%02x", r, g, b);
}
private String toHex(int r, int g, int b, int a) {
return String.format("#%02x%02x%02x%02x", r, g, b, a);
}
@Override
public int glGetClearColor() {
return hexToInt(clearColor);
}
private int hexToInt(String hex) {
switch (hex.length()) {
case 6:
return (0xFF << 24) |
(Integer.valueOf(hex.substring(0, 2), 16) << 16) |
(Integer.valueOf(hex.substring(2, 4), 16) << 8) |
Integer.valueOf(hex.substring(4, 6), 16);
case 6+1:
return (0xFF << 24) |
(Integer.valueOf(hex.substring(0+1, 2+1), 16) << 16) |
(Integer.valueOf(hex.substring(2+1, 4+1), 16) << 8) |
Integer.valueOf(hex.substring(4+1, 6+1), 16);
case 8:
return (Integer.valueOf(hex.substring(6, 8), 16) << 24) |
(Integer.valueOf(hex.substring(0, 2), 16) << 16) |
(Integer.valueOf(hex.substring(2, 4), 16) << 8) |
Integer.valueOf(hex.substring(4, 6), 16);
case 8+1:
return (Integer.valueOf(hex.substring(6+1, 8+1), 16) << 24) |
(Integer.valueOf(hex.substring(0+1, 2+1), 16) << 16) |
(Integer.valueOf(hex.substring(2+1, 4+1), 16) << 8) |
Integer.valueOf(hex.substring(4+1, 6+1), 16);
}
return 0xFF000000;
}
@Override
public void glFillRect(float x, float y, float width, float height, float uvX, float uvY, float uvWidth,
float uvHeight) {
if (currentSkin != null) {
glDrawSkin((int) x, (int) y, (int) (x + width), (int) (y + height), (int) uvX, (int) uvY, (int) (uvWidth + uvX), (int) (uvHeight + uvY), true);
} else {
glFillColor(x, y, width, height);
}
}
@SuppressWarnings("unused")
private void glDrawSkin(int x0, int y0, int x1, int y1, int s0, int t0, int s1, int t1, boolean transparent) {
final int[] size = e.getSize();
x0 += StaticVars.screenPos[0];
y0 += StaticVars.screenPos[1];
final double incrementX = Math.abs((double) (x1 - x0) / (double) (s1 - s0));
final double incrementY = Math.abs((double) (y1 - y0) / (double) (t1 - t0));
final boolean flippedX = (x1 - x0) / (s1 - s0) < 0;
final boolean flippedY = (y1 - y0) / (t1 - t0) < 0;
int oldColor = 0;
int newColor;
final int onex = s0 <= s1 ? 1 : -1;
final int oney = t0 <= t1 ? 1 : -1;
int width = 0;
int height = 0;
if (onex == -1) {
final int s00 = s0;
s0 = s1;
s1 = s00;
width = s1 - s0;
}
if (oney == -1) {
final int t00 = t0;
t0 = t1;
t1 = t00;
height = t1 - t0;
}
if (x0 >= size[0] || y0 >= size[0]) {
return;
}
if (x0 + width >= size[0]) {
s1 = size[0] - x0 + s0;
}
if (y0 + height >= size[1]) {
t1 = size[1] - y0 + t0;
}
if (x0 < 0) {
if (onex == -1) {
width += x0;
s1 += x0 + 1;
} else {
s0 -= x0;
}
x0 = 0;
}
if (y0 < 0) {
if (oney == -1) {
height += y0;
t1 += y0 + 1;
} else {
t0 -= y0;
}
y0 = 0;
}
g.drawImage(currentSkin.getImgElement(), s0, t0, s1-s0, t1-t0, x0, y0, x1-x0, y1-y0);
}
@Override
public void glFillColor(float x, float y, float width, float height) {
x += StaticVars.screenPos[0];
y += StaticVars.screenPos[1];
g.setFillStyle(currentColor);
g.fillRect( x, y, width, height );
}
@Override
public void glDrawStringRight(float x, float y, String text) {
glDrawStringLeft(x - f.getStringWidth(text), y, text);
}
@Override
public void glDrawStringLeft(float x, float y, String textString) {
x += StaticVars.screenPos[0];
y += StaticVars.screenPos[1];
f.imgElCtx.setGlobalCompositeOperation("source-in");
f.imgElCtx.setFillStyle(currentColor);
f.imgElCtx.fillRect(0, 0, f.imgEl.getWidth(), f.imgEl.getHeight());
final int[] text = f.getCharIndexes(textString);
final int[] screenSize = e.getSize();
int cpos;
final int l = text.length;
for (int i = 0; i < l; i++) {
cpos = (i * (f.charW));
final int charIndex = text[i];
g.drawImage(f.imgEl, 0, charIndex*f.charH, f.charW, f.charH, x+cpos, y, f.charW, f.charH);
}
}
private int stackColors(int... color) {
double a = 0;
double r = 0;
double g = 0;
double b = 0;
for (final int newColor : color) {
final double alpha = (newColor >> 24 & 0xFF) / 255d;
a = a * (1d - alpha) + (newColor >> 24 & 0xFF) * alpha;
r = r * (1d - alpha) + (newColor >> 16 & 0xFF) * alpha;
g = g * (1d - alpha) + (newColor >> 8 & 0xFF) * alpha;
b = b * (1d - alpha) + (newColor & 0xFF) * alpha;
}
return ((int) a) << 24 | ((int) r) << 16 | ((int) g) << 8 | ((int) b);
}
@Override
public void glDrawStringCenter(float x, float y, String text) {
glDrawStringLeft(x - (f.getStringWidth(text) / 2), y, text);
}
@Override
public void glDrawLine(float x0, float y0, float x1, float y1) {
if (x1-x0 > 0 && y1-y0 > 0) {
g.beginPath();
g.moveTo(x0, y0);
g.lineTo(x1, y1);
g.stroke();
} else {
g.fillRect(x0, y0, (x1-x0)+1, (y1-y0)+1);
}
}
@Override
public void glDrawCharRight(int x, int y, char ch) {
glDrawStringRight(x, y, ch + "");
}
@Override
public void glDrawCharLeft(int x, int y, char ch) {
glDrawStringLeft(x, y, ch + "");
}
@Override
public void glDrawCharCenter(int x, int y, char ch) {
glDrawStringCenter(x, y, ch + "");
}
@Override
public void glColor4i(int red, int green, int blue, int alpha) {
g.setFillStyle(currentColor = toHex(red, green, blue, alpha));
}
@Override
public void glColor4f(float red, float green, float blue, float alpha) {
glColor4i((int) (red * 255d), (int) (green * 255d), (int) (blue * 255d), (int) (alpha * 255d));
}
@Override
public void glColor3i(int r, int gg, int b) {
g.setFillStyle(currentColor = toHex(r, gg, b));
}
@Override
public void glColor3f(float red, float green, float blue) {
glColor3i((int) (red * 255d), (int) (green * 255d), (int) (blue * 255d));
}
@Override
public void glColor(int c) {
final int a = c >> 24 & 0xFF;
final int r = c >> 16 & 0xFF;
final int gg = c >> 8 & 0xFF;
final int b = c & 0xFF;
g.setFillStyle(currentColor = toHex(r, gg, b, a));
}
@Override
public void glClearSkin() {
currentSkin = null;
}
@Override
public void glClearColor4i(int red, int green, int blue, int alpha) {
clearColor = toHex(red, green, blue, alpha);
}
@Override
public void glClearColor4f(float red, float green, float blue, float alpha) {
clearColor = toHex((int)(red*255),
(int)(green*255),
(int)(blue*255),
(int)(alpha*255));
}
@Override
public void glClearColor(int c) {
final int r = c >> 16 & 0xFF;
final int gg = c >> 8 & 0xFF;
final int b = c & 0xFF;
clearColor = toHex(r, gg, b);
}
@Override
public void glClear(int screenWidth, int screenHeight) {
g.setFillStyle(clearColor);
g.fillRect(0, 0, screenWidth, screenHeight);
g.setFillStyle(currentColor);
}
@Override
public HtmlFont getCurrentFont() {
return f;
}
}
package org.warp.picalculator.gui.graphicengine.html;
import org.teavm.jso.canvas.CanvasImageSource;
import org.teavm.jso.canvas.CanvasRenderingContext2D;
import org.teavm.jso.dom.html.HTMLImageElement;
import org.teavm.jso.typedarrays.Uint8ClampedArray;
import org.warp.picalculator.StaticVars;
import org.warp.picalculator.gui.graphicengine.Renderer;
public class HtmlRenderer implements Renderer {
private static final boolean ENABLE_SUPERSAMPLING = false;
private static final boolean ENABLE_TRANSPARENCY = true;
private String currentColor = "#000000ff";
private String clearColor = "#000000ff";
HtmlFont f = null;
HtmlSkin currentSkin = null;
private final CanvasRenderingContext2D g;
private final HtmlEngine e;
public HtmlRenderer(HtmlEngine e, CanvasRenderingContext2D g) {
this.g = g;
this.e = e;
}
private String toHex(int c) {
final int a = c >> 24 & 0xFF;
final int r = c >> 16 & 0xFF;
final int gg = c >> 8 & 0xFF;
final int b = c & 0xFF;
return String.format("#%02x%02x%02x%02x", r, gg, b, a);
}
private String toHex8(int c) {
final int r = c >> 16 & 0xFF;
final int gg = c >> 8 & 0xFF;
final int b = c & 0xFF;
return String.format("#%02x%02x%02x", r, gg, b);
}
private String toHex(int r, int g, int b) {
return String.format("#%02x%02x%02x", r, g, b);
}
private String toHex(int r, int g, int b, int a) {
return String.format("#%02x%02x%02x%02x", r, g, b, a);
}
@Override
public int glGetClearColor() {
return hexToInt(clearColor);
}
private int hexToInt(String hex) {
switch (hex.length()) {
case 6:
return (0xFF << 24) |
(Integer.valueOf(hex.substring(0, 2), 16) << 16) |
(Integer.valueOf(hex.substring(2, 4), 16) << 8) |
Integer.valueOf(hex.substring(4, 6), 16);
case 6+1:
return (0xFF << 24) |
(Integer.valueOf(hex.substring(0+1, 2+1), 16) << 16) |
(Integer.valueOf(hex.substring(2+1, 4+1), 16) << 8) |
Integer.valueOf(hex.substring(4+1, 6+1), 16);
case 8:
return (Integer.valueOf(hex.substring(6, 8), 16) << 24) |
(Integer.valueOf(hex.substring(0, 2), 16) << 16) |
(Integer.valueOf(hex.substring(2, 4), 16) << 8) |
Integer.valueOf(hex.substring(4, 6), 16);
case 8+1:
return (Integer.valueOf(hex.substring(6+1, 8+1), 16) << 24) |
(Integer.valueOf(hex.substring(0+1, 2+1), 16) << 16) |
(Integer.valueOf(hex.substring(2+1, 4+1), 16) << 8) |
Integer.valueOf(hex.substring(4+1, 6+1), 16);
}
return 0xFF000000;
}
@Override
public void glFillRect(float x, float y, float width, float height, float uvX, float uvY, float uvWidth,
float uvHeight) {
if (currentSkin != null) {
glDrawSkin((int) x, (int) y, (int) (x + width), (int) (y + height), (int) uvX, (int) uvY, (int) (uvWidth + uvX), (int) (uvHeight + uvY), true);
} else {
glFillColor(x, y, width, height);
}
}
@SuppressWarnings("unused")
private void glDrawSkin(int x0, int y0, int x1, int y1, int s0, int t0, int s1, int t1, boolean transparent) {
final int[] size = e.getSize();
x0 += StaticVars.screenPos[0];
y0 += StaticVars.screenPos[1];
final double incrementX = Math.abs((double) (x1 - x0) / (double) (s1 - s0));
final double incrementY = Math.abs((double) (y1 - y0) / (double) (t1 - t0));
final boolean flippedX = (x1 - x0) / (s1 - s0) < 0;
final boolean flippedY = (y1 - y0) / (t1 - t0) < 0;
int oldColor = 0;
int newColor;
final int onex = s0 <= s1 ? 1 : -1;
final int oney = t0 <= t1 ? 1 : -1;
int width = 0;
int height = 0;
if (onex == -1) {
final int s00 = s0;
s0 = s1;
s1 = s00;
width = s1 - s0;
}
if (oney == -1) {
final int t00 = t0;
t0 = t1;
t1 = t00;
height = t1 - t0;
}
if (x0 >= size[0] || y0 >= size[0]) {
return;
}
if (x0 + width >= size[0]) {
s1 = size[0] - x0 + s0;
}
if (y0 + height >= size[1]) {
t1 = size[1] - y0 + t0;
}
if (x0 < 0) {
if (onex == -1) {
width += x0;
s1 += x0 + 1;
} else {
s0 -= x0;
}
x0 = 0;
}
if (y0 < 0) {
if (oney == -1) {
height += y0;
t1 += y0 + 1;
} else {
t0 -= y0;
}
y0 = 0;
}
g.drawImage(currentSkin.getImgElement(), s0, t0, s1-s0, t1-t0, x0, y0, x1-x0, y1-y0);
}
@Override
public void glFillColor(float x, float y, float width, float height) {
x += StaticVars.screenPos[0];
y += StaticVars.screenPos[1];
g.setFillStyle(currentColor);
g.fillRect( x, y, width, height );
}
@Override
public void glDrawStringRight(float x, float y, String text) {
glDrawStringLeft(x - f.getStringWidth(text), y, text);
}
@Override
public void glDrawStringLeft(float x, float y, String textString) {
x += StaticVars.screenPos[0];
y += StaticVars.screenPos[1];
f.imgElCtx.setGlobalCompositeOperation("source-in");
f.imgElCtx.setFillStyle(currentColor);
f.imgElCtx.fillRect(0, 0, f.imgEl.getWidth(), f.imgEl.getHeight());
final int[] text = f.getCharIndexes(textString);
final int[] screenSize = e.getSize();
int cpos;
final int l = text.length;
for (int i = 0; i < l; i++) {
cpos = (i * (f.charW));
final int charIndex = text[i];
g.drawImage(f.imgEl, 0, charIndex*f.charH, f.charW, f.charH, x+cpos, y, f.charW, f.charH);
}
}
private int stackColors(int... color) {
double a = 0;
double r = 0;
double g = 0;
double b = 0;
for (final int newColor : color) {
final double alpha = (newColor >> 24 & 0xFF) / 255d;
a = a * (1d - alpha) + (newColor >> 24 & 0xFF) * alpha;
r = r * (1d - alpha) + (newColor >> 16 & 0xFF) * alpha;
g = g * (1d - alpha) + (newColor >> 8 & 0xFF) * alpha;
b = b * (1d - alpha) + (newColor & 0xFF) * alpha;
}
return ((int) a) << 24 | ((int) r) << 16 | ((int) g) << 8 | ((int) b);
}
@Override
public void glDrawStringCenter(float x, float y, String text) {
glDrawStringLeft(x - (f.getStringWidth(text) / 2), y, text);
}
@Override
public void glDrawLine(float x0, float y0, float x1, float y1) {
if (x1-x0 > 0 && y1-y0 > 0) {
g.beginPath();
g.moveTo(x0, y0);
g.lineTo(x1, y1);
g.stroke();
} else {
g.fillRect(x0, y0, (x1-x0)+1, (y1-y0)+1);
}
}
@Override
public void glDrawCharRight(int x, int y, char ch) {
glDrawStringRight(x, y, ch + "");
}
@Override
public void glDrawCharLeft(int x, int y, char ch) {
glDrawStringLeft(x, y, ch + "");
}
@Override
public void glDrawCharCenter(int x, int y, char ch) {
glDrawStringCenter(x, y, ch + "");
}
@Override
public void glColor4i(int red, int green, int blue, int alpha) {
g.setFillStyle(currentColor = toHex(red, green, blue, alpha));
}
@Override
public void glColor4f(float red, float green, float blue, float alpha) {
glColor4i((int) (red * 255d), (int) (green * 255d), (int) (blue * 255d), (int) (alpha * 255d));
}
@Override
public void glColor3i(int r, int gg, int b) {
g.setFillStyle(currentColor = toHex(r, gg, b));
}
@Override
public void glColor3f(float red, float green, float blue) {
glColor3i((int) (red * 255d), (int) (green * 255d), (int) (blue * 255d));
}
@Override
public void glColor(int c) {
final int a = c >> 24 & 0xFF;
final int r = c >> 16 & 0xFF;
final int gg = c >> 8 & 0xFF;
final int b = c & 0xFF;
g.setFillStyle(currentColor = toHex(r, gg, b, a));
}
@Override
public void glClearSkin() {
currentSkin = null;
}
@Override
public void glClearColor4i(int red, int green, int blue, int alpha) {
clearColor = toHex(red, green, blue, alpha);
}
@Override
public void glClearColor4f(float red, float green, float blue, float alpha) {
clearColor = toHex((int)(red*255),
(int)(green*255),
(int)(blue*255),
(int)(alpha*255));
}
@Override
public void glClearColor(int c) {
final int r = c >> 16 & 0xFF;
final int gg = c >> 8 & 0xFF;
final int b = c & 0xFF;
clearColor = toHex(r, gg, b);
}
@Override
public void glClear(int screenWidth, int screenHeight) {
g.setFillStyle(clearColor);
g.fillRect(0, 0, screenWidth, screenHeight);
g.setFillStyle(currentColor);
}
@Override
public HtmlFont getCurrentFont() {
return f;
}
}

View File

@ -1,86 +1,86 @@
package org.warp.picalculator.gui.graphicengine.html;
import java.io.IOException;
import java.net.URISyntaxException;
import org.teavm.jso.JSObject;
import org.teavm.jso.browser.Window;
import org.teavm.jso.dom.html.HTMLDocument;
import org.teavm.jso.dom.html.HTMLImageElement;
import org.warp.picalculator.deps.StorageUtils;
import org.warp.picalculator.gui.graphicengine.GraphicEngine;
import org.warp.picalculator.gui.graphicengine.Skin;
import ar.com.hjg.pngj.PngReader;
public class HtmlSkin implements Skin {
private String url;
private int[] skinSize;
private boolean initd;
private HTMLImageElement imgEl;
public HtmlSkin(String file) throws IOException {
load(file);
}
public void use(GraphicEngine d) {
if (d instanceof HtmlEngine) {
if (!initd)
initialize(d);
((HtmlEngine) d).getRenderer().currentSkin = this;
}
}
@Override
public void load(String file) throws IOException {
if (!file.startsWith("/"))
file = "/"+file;
url = StorageUtils.basepath+file;
try {
PngReader r = new PngReader(StorageUtils.getResourceStream(file));
skinSize = new int[] { r.imgInfo.cols, r.imgInfo.rows };
r.close();
} catch (URISyntaxException e) {
IOException ex = new IOException();
ex.initCause(e);
throw ex;
}
}
@Override
public void initialize(GraphicEngine d) {
HTMLDocument doc = Window.current().getDocument();
imgEl = doc.createElement("img").cast();
imgEl.setSrc(url);
imgEl.setClassName("hidden");
doc.getBody().appendChild(imgEl);
initd = true;
}
@Override
public boolean isInitialized() {
return initd;
}
@Override
public int getSkinWidth() {
return skinSize[0];
}
@Override
public int getSkinHeight() {
return skinSize[1];
}
public final String getUrl() {
return url;
}
public final HTMLImageElement getImgElement() {
return imgEl;
}
}
package org.warp.picalculator.gui.graphicengine.html;
import java.io.IOException;
import java.net.URISyntaxException;
import org.teavm.jso.JSObject;
import org.teavm.jso.browser.Window;
import org.teavm.jso.dom.html.HTMLDocument;
import org.teavm.jso.dom.html.HTMLImageElement;
import org.warp.picalculator.deps.StorageUtils;
import org.warp.picalculator.gui.graphicengine.GraphicEngine;
import org.warp.picalculator.gui.graphicengine.Skin;
import ar.com.hjg.pngj.PngReader;
public class HtmlSkin implements Skin {
private String url;
private int[] skinSize;
private boolean initd;
private HTMLImageElement imgEl;
public HtmlSkin(String file) throws IOException {
load(file);
}
public void use(GraphicEngine d) {
if (d instanceof HtmlEngine) {
if (!initd)
initialize(d);
((HtmlEngine) d).getRenderer().currentSkin = this;
}
}
@Override
public void load(String file) throws IOException {
if (!file.startsWith("/"))
file = "/"+file;
url = StorageUtils.basepath+file;
try {
PngReader r = new PngReader(StorageUtils.getResourceStream(file));
skinSize = new int[] { r.imgInfo.cols, r.imgInfo.rows };
r.close();
} catch (URISyntaxException e) {
IOException ex = new IOException();
ex.initCause(e);
throw ex;
}
}
@Override
public void initialize(GraphicEngine d) {
HTMLDocument doc = Window.current().getDocument();
imgEl = doc.createElement("img").cast();
imgEl.setSrc(url);
imgEl.setClassName("hidden");
doc.getBody().appendChild(imgEl);
initd = true;
}
@Override
public boolean isInitialized() {
return initd;
}
@Override
public int getSkinWidth() {
return skinSize[0];
}
@Override
public int getSkinHeight() {
return skinSize[1];
}
public final String getUrl() {
return url;
}
public final HTMLImageElement getImgElement() {
return imgEl;
}
}

View File

@ -1,10 +1,10 @@
package org.warp.picalculator.gui.graphicengine.html;
import org.teavm.jso.JSProperty;
import org.teavm.jso.dom.events.Event;
public interface InputEvent extends Event {
@JSProperty
String getValue();
}
package org.warp.picalculator.gui.graphicengine.html;
import org.teavm.jso.JSProperty;
import org.teavm.jso.dom.events.Event;
public interface InputEvent extends Event {
@JSProperty
String getValue();
}