rename vtm-gdx-*

This commit is contained in:
Hannes Janetzek
2014-03-21 04:21:21 +01:00
parent f224486e70
commit 07b2d57b52
80 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<!-- TODO: Add <servlet> tags for each servlet here. -->
<!-- TODO: Add <servlet-mapping> tags for each <servlet> here. -->
<!-- TODO: Optionally add a <welcome-file-list> tag to display a welcome file. -->
</web-app>

View File

@@ -0,0 +1,164 @@
<!doctype html>
<html>
<head>
<title>vtm-gdx</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<!-- pixel and dpi are way too simple concepts for web devs, lets also have css-pixels! -->
<!-- http://www.html5rocks.com/de/mobile/touch/ -->
<!-- http://www.quirksmode.org/mobile/viewports.html -->
<!-- http://www.quirksmode.org/blog/archives/2012/07/more_about_devi.html -->
<!-- devicePixelRatio: http://coding.smashingmagazine.com/2012/08/20/towards-retina-web/ -->
<meta name="viewport"
content="width=device-width, initial-scale=1, user-scalable=no">
<style>
.header {
background-color: #ddd;
text-align: center;
}
html, body {
height: 100%;
width: 100%;
margin: 0 0 0 0;
font-family: Arial, "MS Trebuchet", sans-serif;
}
#gdx-canvas {
cursor: default;
outline: none;
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 0;
}
#credits {
position: absolute;
bottom: 0.2em;
right: 0.2em;
z-index: 20000;
color: white;
background-color: #000;
opacity: 0.5;
padding: 0.2em 0.5em 0.2em 0.5em;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
border-radius: 3px;
font-size: 11px;
}
#credits a {
color: white;
text-decoration: none;
font-variant: small-caps;
}
#search {
z-index: 20000;
position: absolute;
top: 0.5em;
left: 0.5em;
background-color: rgba(0,0,0,0.8);
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
border-radius: 3px;
visibility: hidden;
}
#listContainer{
color: #FFFFFF;
}
#nameFieldContainer, .gwt-TextBox {
width: 250px;
}
/* Turn on a 16x16 scrollbar */
::-webkit-scrollbar {
width: 10px;
height: 0px;
}
/* Turn on single button up on top, and down on bottom */
::-webkit-scrollbar-button:start:decrement, ::-webkit-scrollbar-button:end:increment {
display: block;
}
/* Turn off the down area up on top, and up area on bottom */
::-webkit-scrollbar-button:vertical:start:increment, ::-webkit-scrollbar-button:vertical:end:decrement {
display: none;
}
/* Place The scroll down button at the bottom */
::-webkit-scrollbar-button:end:increment {
/*background-image: url(images/scroll_cntrl_dwn.png);*/
}
/* Place The scroll up button at the up */
::-webkit-scrollbar-button:start:decrement {
/*background-image: url(images/scroll_cntrl_up.png);*/
}
/* Top area above thumb and below up button */
::-webkit-scrollbar-track-piece:vertical:start {
/*background-image: url(images/scroll_gutter_top.png), url(images/scroll_gutter_mid.png);
background-repeat: no-repeat, repeat-y;*/
}
/* Bottom area below thumb and down button */
::-webkit-scrollbar-track-piece:vertical:end {
/*background-image: url(images/scroll_gutter_btm.png), url(images/scroll_gutter_mid.png);
background-repeat: no-repeat, repeat-y;
background-position: bottom left, 0 0;*/
}
/* The thumb itself */
::-webkit-scrollbar-thumb:vertical {
height: 56px;
width: 12px;
/* -webkit-border-image: url(images/scroll_thumb.png) 8 0 8 0 stretch stretch;*/
background-color: #DDDDDD;
opacity: 0.5;
}
</style>
<script type="text/javascript">
var mapconfig = {
tilesource : "oscimap4",
tileurl : "http://opensciencemap.org/tiles/vtm",
zoom : 2,
latitude : 0.0,
longitude : 0.0
}
//background : "naturalearth"
</script>
</head>
<body oncontextmenu="return false;">
<script type="text/javascript" src="js/_tessellate.js"></script>
<script type="text/javascript" src="js/tessellate.js"></script>
<script type="text/javascript"
src="org.oscim.gdx.GwtDefinition/org.oscim.gdx.GwtDefinition.nocache.js"></script>
<div id="credits">
<a href="https://github.com/hjanetzek/vtm">Source</a>
| map data © <a href="http://www.openstreemap.org">OpenStreetMap</a> contributors
| <a href="http://www.opensciencemap.org">OpenScienceMap</a>
</div>
<div id="search">
<table align="center">
<tr>
<td id="nameFieldContainer">
<td id="sendButtonContainer">
</tr>
<tr>
<td colspan="2" id="listContainer">
</tr>
</table>
</div>
</body>
</html>

View File

@@ -0,0 +1,37 @@
Copyright notice and license for the libtess files (all source files besides
tessellate.[ch] and main.c):
SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice including the dates of first publication and
either this permission notice or a reference to
http://oss.sgi.com/projects/FreeB/
shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Except as contained in this notice, the name of Silicon Graphics, Inc.
shall not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization from
Silicon Graphics, Inc.
--------------------------------------------------------------------------------
Copyright notice for the other files:
SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
Copyright (C) 2013 AT&T Intellectual Property. All Rights Reserved.

View File

@@ -0,0 +1,18 @@
# A minimal, self-contained port of SGI's GLU libtess
Polygon tessellation is a major pain in the neck. Have you ever tried
writing fast and robust code for it? libtess is, to my knowledge, the
only GPL-compatible, liberally-licensed, high-quality polygon
triangulator out there.
This repository includes a self-contained function (tessellate, in
tessellate.c) that you can call to triangulate a polygon that is
potentially self-intersecting, with holes, or with duplicate
vertices. Simple examples of calling the tessellate function directly
are located in main.c.
More interestingly, this repository also includes an
Emscripten-compiled module, _tessellate.js, and a Javascript-friendly
wrapper, in tessellate.js. Simple examples are available under
index.html.

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,107 @@
tessellate = (function() {
Module.TOTAL_MEMORY = 1024 * 1024;
var c_tessellate = Module.cwrap('tessellate', 'void', [ 'number', 'number',
'number', 'number', 'number', 'number' ]);
// special tessellator for extrusion layer - only returns triangle indices
var tessellate = function(vertices, v_start, v_end, boundaries, b_start,
b_end, mode) {
var i;
var v_len = (v_end - v_start);
var b_len = (b_end - b_start);
var p = Module._malloc(v_len * 8);
for (i = 0; i < v_len; ++i)
Module.setValue(p + i * 8, vertices[v_start + i], 'double');
var contours = Module._malloc((b_len + 1) * 4);
// pointer to first contour
Module.setValue(contours + 0, p + 0, 'i32');
var offset = p;
// pointer to further contours + end
for (i = 0; i < b_len; ++i) {
offset += 8 * boundaries[b_start + i];
Module.setValue(contours + 4 * (i + 1), offset, 'i32');
}
var ppcoordinates_out = Module._malloc(4);
var pptris_out = Module._malloc(4);
var pnverts = Module._malloc(4);
var pntris = Module._malloc(4);
c_tessellate(ppcoordinates_out, pnverts, pptris_out, pntris, contours,
contours + 4 * (b_len + 1));
var pcoordinates_out = Module.getValue(ppcoordinates_out, 'i32');
var ptris_out = Module.getValue(pptris_out, 'i32');
var nverts = Module.getValue(pnverts, 'i32');
var ntris = Module.getValue(pntris, 'i32');
var result_triangles = null;
var result_vertices = null;
if (mode){
result_triangles = new Int32Array(ntris * 3);
for (i = 0; i < 3 * ntris; ++i)
result_triangles[i] = Module.getValue(ptris_out + i * 4, 'i32');
result_vertices = new Float32Array(nverts * 2);
for (i = 0; i < 2 * nverts; ++i)
result_vertices[i] = Module.getValue(pcoordinates_out + i * 8, 'double');
} else {
if (nverts * 2 == v_len) {
result_triangles = new Int32Array(ntris * 3);
for (i = 0; i < 3 * ntris; ++i) {
result_triangles[i] = Module.getValue(ptris_out + i * 4, 'i32') * 2;
}
// when a ring has an odd number of points one (or rather two)
// additional vertices will be added. so the following rings
// needs extra offset...
var start = 0;
for ( var j = 0, m = b_len - 1; j < m; j++) {
start += boundaries[b_start + j];
// even number of points?
if (!((boundaries[b_start + j] >> 1) & 1))
continue;
for ( var n = ntris * 3, tri = 0; tri < n; tri++)
if (result_triangles[tri] >= start)
result_triangles[tri] += 2;
start += 2;
}
}
}
Module._free(pnverts);
Module._free(pntris);
Module._free(ppcoordinates_out);
Module._free(pcoordinates_out);
Module._free(pptris_out);
Module._free(ptris_out);
Module._free(p);
Module._free(contours);
if (mode)
return { vertices: result_vertices, triangles: result_triangles };
else
return result_triangles;
};
return tessellate;
})();

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<module>
<entry-point class="org.oscim.gdx.client.GwtLauncher" />
<inherits name="com.google.gwt.xml.XML" />
<inherits name="ru.finam.slf4jgwt.logging.gwt.Logging"/>
<set-property name='gwt.logging.enabled' value='TRUE' />
<set-property name='gwt.logging.consoleHandler' value='ENABLED' />
<set-property name='gwt.logging.firebugHandler' value='DISABLED' />
<set-property name='gwt.logging.popupHandler' value='DISABLED' />
<set-property name="gwt.logging.logLevel" value="FINE"/>
<inherits name="GdxMap" />
<inherits name="com.badlogic.gdx.backends.gdx_backends_gwt" />
<inherits name="com.google.gwt.user.theme.chrome.Chrome" />
<!-- super dev mode -->
<add-linker name="xsiframe"/>
<set-configuration-property name='xsiframe.failIfScriptTag' value='FALSE'/>
<set-configuration-property name="devModeRedirectEnabled" value="true"/>
<super-source path="emu" />
<set-configuration-property name="gdx.assetpath" value="./assets" />
<!-- for gradle build, commend out for eclipse build/devmode -->
<set-configuration-property name="gdx.assetoutputpath" value="build/gwt/draftOut" />
<set-property name="user.agent" value="safari"/>
</module>

View File

@@ -0,0 +1,100 @@
/*
* Copyright 2013 Hannes Janetzek
*
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.oscim.gdx.client;
import org.oscim.backend.GL20;
import org.oscim.backend.canvas.Bitmap;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.Pixmap;
import com.google.gwt.dom.client.ImageElement;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.RootPanel;
public class GwtBitmap implements Bitmap {
Pixmap pixmap;
Image image;
boolean disposable;
public GwtBitmap(Image data) {
ImageElement imageElement = ImageElement.as(data.getElement());
pixmap = new Pixmap(imageElement);
image = data;
}
/** always argb8888 */
public GwtBitmap(int width, int height, int format) {
pixmap = new Pixmap(width, height, null);
}
public GwtBitmap(String fileName) {
FileHandle handle = Gdx.files.internal(fileName);
pixmap = new Pixmap(handle);
disposable = true;
}
@Override
public int getWidth() {
return pixmap.getWidth();
}
@Override
public int getHeight() {
return pixmap.getHeight();
}
@Override
public void recycle() {
// FIXME this should be called at some point in time
pixmap.dispose();
if (image != null)
RootPanel.get().remove(image);
}
@Override
public int[] getPixels() {
return null;
}
@Override
public void eraseColor(int color) {
}
@Override
public void uploadToTexture(boolean replace) {
Gdx.gl.glTexImage2D(GL20.GL_TEXTURE_2D, 0, pixmap.getGLInternalFormat(), pixmap.getWidth(),
pixmap.getHeight(), 0,
pixmap.getGLFormat(), pixmap.getGLType(), pixmap.getPixels());
if (disposable || image != null) {
//log.debug("dispose pixmap " + getWidth() + "/" + getHeight());
pixmap.dispose();
if (image != null)
RootPanel.get().remove(image);
}
}
@Override
public boolean isValid() {
return true;
}
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright 2013 Hannes Janetzek
*
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.oscim.gdx.client;
import org.oscim.backend.canvas.Bitmap;
import org.oscim.backend.canvas.Paint;
import com.google.gwt.canvas.dom.client.Context2d;
import com.google.gwt.canvas.dom.client.Context2d.LineJoin;
public class GwtCanvas implements org.oscim.backend.canvas.Canvas {
GwtBitmap bitmap;
public GwtCanvas() {
// canvas comes with gdx pixmap
}
@Override
public void setBitmap(Bitmap bitmap) {
this.bitmap = (GwtBitmap) bitmap;
Context2d ctx = this.bitmap.pixmap.getContext();
ctx.clearRect(0, 0, this.bitmap.getWidth(), this.bitmap.getHeight());
ctx.setLineJoin(LineJoin.BEVEL);
}
@Override
public void drawText(String string, float x, float y, Paint paint) {
if (bitmap == null) {
//log.debug("no bitmap set");
return;
}
GwtPaint p = (GwtPaint) paint;
if (p.stroke && GwtCanvasAdapter.NO_STROKE_TEXT)
return;
Context2d ctx = bitmap.pixmap.getContext();
ctx.setFont(p.font);
if (p.stroke) {
ctx.setLineWidth(p.strokeWidth);
ctx.setStrokeStyle(p.color);
ctx.strokeText(string, (int) (x + 1), (int) (y + 1));
} else {
ctx.setFillStyle(p.color);
ctx.fillText(string, (int) (x + 1), (int) (y + 1));
}
}
@Override
public void drawBitmap(Bitmap bitmap, float x, float y) {
}
}

View File

@@ -0,0 +1,75 @@
/*
* Copyright 2013 Hannes Janetzek
*
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.oscim.gdx.client;
import java.io.InputStream;
import org.oscim.backend.CanvasAdapter;
import org.oscim.backend.canvas.Bitmap;
import org.oscim.backend.canvas.Paint;
import com.google.gwt.canvas.client.Canvas;
import com.google.gwt.canvas.dom.client.Context2d;
import com.google.gwt.canvas.dom.client.TextMetrics;
public class GwtCanvasAdapter extends CanvasAdapter {
public static boolean NO_STROKE_TEXT = false;
public static final GwtCanvasAdapter INSTANCE = new GwtCanvasAdapter();
static final Context2d ctx;
static {
Canvas canvas = Canvas.createIfSupported();
canvas.setCoordinateSpaceWidth(1);
canvas.setCoordinateSpaceHeight(1);
ctx = canvas.getContext2d();
}
static synchronized float getTextWidth(String text, String font) {
ctx.setFont(font);
TextMetrics tm = ctx.measureText(text);
return (float) tm.getWidth();
}
@Override
public Bitmap decodeBitmap(InputStream in) {
//ImageData data = new ImageData();
return null;
}
@Override
public Bitmap loadBitmapAsset(String fileName) {
return new GwtBitmap(fileName);
}
@Override
public Paint getPaint() {
return new GwtPaint();
}
@Override
public Bitmap getBitmap(int width, int height, int format) {
return new GwtBitmap(width, height, format);
}
@Override
public org.oscim.backend.canvas.Canvas getCanvas() {
return new GwtCanvas();
}
}

View File

@@ -0,0 +1,74 @@
/*
* Copyright 2013 Hannes Janetzek
*
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.oscim.gdx.client;
import java.nio.Buffer;
import java.nio.IntBuffer;
import org.oscim.backend.GL20;
import com.badlogic.gdx.backends.gwt.GwtGL20;
import com.badlogic.gdx.graphics.Pixmap;
import com.google.gwt.typedarrays.client.Uint8ArrayNative;
import com.google.gwt.webgl.client.WebGLRenderingContext;
public class GwtGLAdapter extends GwtGL20 implements GL20 {
protected final WebGLRenderingContext gl;
public GwtGLAdapter(WebGLRenderingContext gl) {
super(gl);
gl.pixelStorei(WebGLRenderingContext.UNPACK_PREMULTIPLY_ALPHA_WEBGL, 1);
this.gl = gl;
}
@Override
public void glGetShaderSource(int shader, int bufsize, Buffer length, String source) {
}
@Override
public void glTexImage2D(int target, int level, int internalformat, int width, int height,
int border, int format, int type, Buffer pixels) {
if (pixels == null) {
gl.texImage2D(target, level, internalformat,
width, height, border, format,
type, null);
return;
}
Pixmap pixmap = Pixmap.pixmaps.get(((IntBuffer) pixels).get(0));
if (pixmap != null) {
gl.texImage2D(target, level, internalformat, format, type, pixmap.getCanvasElement());
} else if (format == GL20.GL_ALPHA) {
int tmp[] = new int[(width * height) >> 2];
((IntBuffer) pixels).get(tmp);
Uint8ArrayNative v = com.google.gwt.typedarrays.client.Uint8ArrayNative.create(width
* height);
for (int i = 0, n = (width * height) >> 2; i < n; i++) {
v.set(i * 4 + 3, (tmp[i] >> 24) & 0xff);
v.set(i * 4 + 2, (tmp[i] >> 16) & 0xff);
v.set(i * 4 + 1, (tmp[i] >> 8) & 0xff);
v.set(i * 4 + 0, (tmp[i]) & 0xff);
}
gl.texImage2D(target, level, internalformat, width, height, 0, format, type, v);
}
}
}

View File

@@ -0,0 +1,221 @@
/*
* Copyright 2013 Hannes Janetzek
*
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.oscim.gdx.client;
import java.util.HashMap;
import org.oscim.backend.CanvasAdapter;
import org.oscim.backend.GL20;
import org.oscim.backend.GLAdapter;
import org.oscim.core.MapPosition;
import org.oscim.core.MercatorProjection;
import org.oscim.gdx.GdxMap;
import org.oscim.layers.tile.bitmap.BitmapTileLayer;
import org.oscim.layers.tile.vector.VectorTileLayer;
import org.oscim.layers.tile.vector.labeling.LabelLayer;
import org.oscim.renderer.MapRenderer;
import org.oscim.theme.VtmThemes;
import org.oscim.tiling.TileSource;
import org.oscim.tiling.source.bitmap.BitmapTileSource;
import org.oscim.tiling.source.bitmap.DefaultSources;
import org.oscim.tiling.source.bitmap.DefaultSources.StamenToner;
import org.oscim.tiling.source.oscimap4.OSciMap4TileSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.backends.gwt.GwtApplication;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
class GwtGdxMap extends GdxMap {
static final Logger log = LoggerFactory.getLogger(GwtGdxMap.class);
SearchBox mSearchBox;
@Override
public void create() {
MapConfig c = MapConfig.get();
// stroke text takes about 70% cpu time in firefox:
// https://bug568526.bugzilla.mozilla.org/attachment.cgi?id=447932
// <- circle/stroke test 800ms firefox, 80ms chromium..
// TODO use texture atlas to avoid drawing text-textures
if (GwtApplication.agentInfo().isLinux() && GwtApplication.agentInfo().isFirefox())
GwtCanvasAdapter.NO_STROKE_TEXT = true;
CanvasAdapter.g = GwtCanvasAdapter.INSTANCE;
CanvasAdapter.textScale = 0.7f;
GLAdapter.g = (GL20) Gdx.graphics.getGL20();
GLAdapter.GDX_WEBGL_QUIRKS = true;
MapRenderer.setBackgroundColor(0xffffff);
//Gdx.app.setLogLevel(Application.LOG_DEBUG);
super.create();
double lat = c.getLatitude();
double lon = c.getLongitude();
int zoom = c.getZoom();
float tilt = 0;
float rotation = 0;
String themeName = null;
String mapName = null;
final HashMap<String, String> params = new HashMap<String, String>();
String addOpts = "";
if (Window.Location.getHash() != null) {
String hash = Window.Location.getHash();
hash = hash.substring(1);
String[] urlParams = null;
urlParams = hash.split("&");
if (urlParams.length == 1)
urlParams = hash.split(",");
for (String p : urlParams) {
try {
if (p.startsWith("lat="))
lat = Double.parseDouble(p.substring(4));
else if (p.startsWith("lon="))
lon = Double.parseDouble(p.substring(4));
else if (p.startsWith("scale="))
zoom = Integer.parseInt(p.substring(6));
else if (p.startsWith("rot="))
rotation = Float.parseFloat(p.substring(4));
else if (p.startsWith("tilt="))
tilt = Float.parseFloat(p.substring(5));
else if (p.startsWith("theme="))
themeName = p.substring(6);
else if (p.startsWith("map="))
mapName = p.substring(4);
else {
String[] opt = p.split("=");
if (opt.length > 1)
params.put(opt[0], opt[1]);
else
params.put(opt[0], null);
addOpts += p + "&";
}
} catch (NumberFormatException e) {
}
}
}
final String addParam =
(themeName == null ? "" : ("theme=" + themeName + "&"))
+ (mapName == null ? "" : ("map=" + mapName + "&"))
+ addOpts;
MapPosition p = new MapPosition();
p.setZoomLevel(zoom);
p.setPosition(lat, lon);
p.bearing = rotation;
p.tilt = tilt;
mMap.setMapPosition(p);
VectorTileLayer l = null;
if (c.getBackgroundLayer() != null || mapName != null) {
BitmapTileSource ts;
if ("toner".equals(mapName))
ts = new StamenToner();
else if ("osm".equals(mapName))
ts = new DefaultSources.OpenStreetMap();
else if ("watercolor".equals(mapName))
ts = new DefaultSources.StamenWatercolor();
else if ("arcgis-shaded".equals(mapName))
ts = new DefaultSources.ArcGISWorldShaded();
else if ("imagico".equals(mapName))
ts = new DefaultSources.ImagicoLandcover();
else
ts = new StamenToner();
mMap.setBackgroundMap(new BitmapTileLayer(mMap, ts));
} else {
String url = c.getTileUrl();
TileSource ts = new OSciMap4TileSource(url);
l = mMap.setBaseMap(ts);
if (themeName == null) {
mMap.setTheme(VtmThemes.DEFAULT);
} else {
if ("osmarender".equals(themeName))
mMap.setTheme(VtmThemes.OSMARENDER);
else if ("tron".equals(themeName))
mMap.setTheme(VtmThemes.TRONRENDER);
else if ("newtron".equals(themeName))
mMap.setTheme(VtmThemes.NEWTRON);
else
mMap.setTheme(VtmThemes.DEFAULT);
}
}
if (l != null) {
if (!params.containsKey("nolabel"))
mMap.layers().add(new LabelLayer(mMap, l));
}
mSearchBox = new SearchBox(mMap);
// update URL hash to current position, every 5 seconds
Timer timer = new Timer() {
private int curLon, curLat, curZoom, curTilt, curRot;
private MapPosition pos = new MapPosition();
public void run() {
mMap.viewport().getMapPosition(pos);
int lat = (int) (MercatorProjection.toLatitude(pos.y) * 1000);
int lon = (int) (MercatorProjection.toLongitude(pos.x) * 1000);
int rot = (int) (pos.bearing);
rot = (int) (pos.bearing) % 360;
//rot = rot < 0 ? -rot : rot;
if (curZoom != pos.zoomLevel || curLat != lat || curLon != lon
|| curTilt != rot || curRot != (int) (pos.bearing)) {
curLat = lat;
curLon = lon;
curZoom = pos.zoomLevel;
curTilt = (int) pos.tilt;
curRot = rot;
String newURL = Window.Location
.createUrlBuilder()
.setHash(addParam
+ "scale=" + pos.zoomLevel
+ "&rot=" + curRot
+ "&tilt=" + curTilt
+ "&lat=" + (curLat / 1000f)
+ "&lon=" + (curLon / 1000f))
.buildString();
Window.Location.replace(newURL);
}
}
};
timer.scheduleRepeating(5000);
}
@Override
protected void createLayers() {
}
}

View File

@@ -0,0 +1,89 @@
/*
* Copyright 2013 Hannes Janetzek
*
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.oscim.gdx.client;
// -draftCompile -localWorkers 2
import org.oscim.core.Tile;
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.backends.gwt.GwtApplication;
import com.badlogic.gdx.backends.gwt.GwtApplicationConfiguration;
import com.badlogic.gdx.backends.gwt.GwtGraphics;
import com.badlogic.gdx.backends.gwt.preloader.Preloader.PreloaderCallback;
import com.badlogic.gdx.backends.gwt.preloader.Preloader.PreloaderState;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.user.client.ui.DockLayoutPanel;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.RootPanel;
public class GwtLauncher extends GwtApplication {
@Override
public GwtApplicationConfiguration getConfig() {
GwtApplicationConfiguration cfg =
new GwtApplicationConfiguration(GwtGraphics.getWindowWidthJSNI(),
GwtGraphics.getWindowHeightJSNI());
DockLayoutPanel p = new DockLayoutPanel(Unit.EM);
p.setHeight("100%");
p.setWidth("100%");
RootPanel.get().add(p);
//HTML header = new HTML("header");
//p.addNorth(header, 2);
//header.setStyleName("header");
//HTML footer = new HTML("footer");
//footer.setStyleName("footer");
//p.addSouth(footer, 2);
cfg.rootPanel = new FlowPanel();
p.add(cfg.rootPanel);
//cfg.antialiasing = true;
cfg.stencil = true;
cfg.fps = 60;
return cfg;
}
@Override
public ApplicationListener getApplicationListener() {
if (GwtGraphics.getDevicePixelRatioJSNI() > 1)
Tile.SIZE = 400;
else
Tile.SIZE = 360;
return new GwtGdxMap();
}
@Override
public PreloaderCallback getPreloaderCallback() {
return new PreloaderCallback() {
@Override
public void update(PreloaderState state) {
}
@Override
public void error(String file) {
//log.debug("error loading " + file);
}
};
}
}

View File

@@ -0,0 +1,140 @@
/*
* Copyright 2013 Hannes Janetzek
*
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.oscim.gdx.client;
import org.oscim.backend.canvas.Bitmap;
import org.oscim.backend.canvas.Paint;
import com.badlogic.gdx.graphics.Pixmap;
public class GwtPaint implements Paint {
String color;
boolean stroke;
float strokeWidth;
Align mAlign;
float fontSize = 12;
private FontStyle fontStyle = FontStyle.NORMAL;
//private FontFamily fontFamily = FontFamily.DEFAULT;
//String font = "12px sans-serif";
String font = "13px Helvetica";
//private int cap;
@Override
public int getColor() {
return 0;
}
@Override
public int getTextHeight(String text) {
return 0;
}
@Override
public int getTextWidth(String text) {
return 0;
}
@Override
public void setBitmapShader(Bitmap bitmap) {
}
@Override
public void setColor(int color) {
float a = ((color >>> 24) & 0xff) / 255f;
int r = (color >>> 16) & 0xff;
int g = (color >>> 8) & 0xff;
int b = (color & 0xff);
this.color = Pixmap.make(r, g, b, a);
}
@Override
public void setDashPathEffect(float[] strokeDasharray) {
}
@Override
public void setStrokeCap(Cap cap) {
stroke = true;
}
@Override
public void setStrokeWidth(float width) {
stroke = true;
strokeWidth = width;
}
@Override
public void setStyle(Style style) {
}
@Override
public void setTextAlign(Align align) {
mAlign = align;
}
@Override
public void setTextSize(float size) {
fontSize = size;
buildFont();
}
@Override
public void setTypeface(FontFamily fontFamily, FontStyle fontStyle) {
this.fontStyle = fontStyle;
//this.fontFamily = fontFamily;
buildFont();
}
@Override
public float measureText(String text) {
return GwtCanvasAdapter.getTextWidth(text, font);
}
// FIXME all estimates. no idea how to properly measure canvas text..
@Override
public float getFontHeight() {
return 2 + fontSize + strokeWidth * 2;
}
@Override
public float getFontDescent() {
return 4 + strokeWidth;
}
void buildFont() {
StringBuilder sb = new StringBuilder();
if (this.fontStyle == FontStyle.BOLD)
sb.append("bold ");
else if (this.fontStyle == FontStyle.ITALIC)
sb.append("italic ");
sb.append(Math.round(this.fontSize));
sb.append("px ");
sb.append("Helvetica");
this.font = sb.toString();
}
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright 2013 Hannes Janetzek
*
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.oscim.gdx.client;
import com.google.gwt.core.client.JavaScriptObject;
class MapConfig extends JavaScriptObject {
protected MapConfig() {
}
public static native MapConfig get()/*-{
return $wnd.mapconfig;
}-*/;
public final native double getLatitude() /*-{
return this.latitude;
}-*/;
public final native double getLongitude() /*-{
return this.longitude;
}-*/;
public final native int getZoom() /*-{
return this.zoom;
}-*/;
public final native String getTileSource() /*-{
return this.tilesource;
}-*/;
public final native String getTileUrl() /*-{
return this.tileurl;
}-*/;
public final native String getBackgroundLayer() /*-{
return this.background;
}-*/;
}

View File

@@ -0,0 +1,366 @@
/*
* Copyright 2013 Hannes Janetzek
*
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.oscim.gdx.client;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.oscim.core.BoundingBox;
import org.oscim.core.GeometryBuffer;
import org.oscim.core.MapPosition;
import org.oscim.layers.PathLayer;
import org.oscim.map.Map;
import com.google.gwt.cell.client.AbstractCell;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.core.client.JsArrayNumber;
import com.google.gwt.dom.client.Style.Visibility;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.FocusEvent;
import com.google.gwt.event.dom.client.FocusHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.http.client.URL;
import com.google.gwt.jsonp.client.JsonpRequestBuilder;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.cellview.client.CellList;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.view.client.ProvidesKey;
import com.google.gwt.view.client.SelectionChangeEvent;
import com.google.gwt.view.client.SingleSelectionModel;
/**
* Entry point classes define <code>onModuleLoad()</code>.
*/
public class SearchBox {
protected static final Logger log = LoggerFactory.getLogger(SearchBox.class);
private static final String NOMINATIM_GLOBAL = "http://nominatim.openstreetmap.org/search?polygon_text=1&addressdetails=0&format=json&limit=25&q=";
interface PoiData {
public static final ProvidesKey<PoiData> KEY_PROVIDER = new ProvidesKey<PoiData>() {
@Override
public Object getKey(PoiData item) {
return item == null ? null : item.getId();
}
};
String getId();
String getName();
double getLatitude();
double getLongitude();
String getIcon();
BoundingBox getBoundingBox();
}
final static class NominatimData extends JavaScriptObject implements
PoiData {
protected NominatimData() {
}
final static class BBox extends JsArrayNumber {
protected BBox() {
}
}
final static class Polygon extends JsArray<JsArrayNumber> {
protected Polygon() {
}
}
@Override
public final native String getId()
/*-{
return this.osm_id;
}-*/;
public final native String name() /*-{
return this.display_name;
}-*/;
public final native BBox getBBox() /*-{
return this.boundingbox
}-*/;
public final native String getWkt() /*-{
return this.geotext;
}-*/;
private final native String latitude() /*-{
return this.lat;
}-*/;
private final native String longitude() /*-{
return this.lon;
}-*/;
public final native String getIcon() /*-{
return this.icon;
}-*/;
@Override
public double getLatitude() {
try {
return Double.parseDouble(latitude());
} catch (Exception e) {
}
return 0;
}
@Override
public double getLongitude() {
try {
return Double.parseDouble(longitude());
} catch (Exception e) {
}
return 0;
}
@Override
public BoundingBox getBoundingBox() {
if (getBBox() != null) {
BBox b = getBBox();
return new BoundingBox(b.get(0), b.get(2), b.get(1), b.get(3));
}
return null;
}
@Override
public String getName() {
String[] n = name().split(", ");
if (n != null && n.length > 2)
return n[0] + ", " + n[1] + " " + n[2];
else if (n != null && n.length > 1)
return n[0] + ", " + n[1];
return name();
}
}
class PoiCell extends AbstractCell<PoiData> {
@Override
public void render(com.google.gwt.cell.client.Cell.Context context,
PoiData value, SafeHtmlBuilder sb) {
// Value can be null, so do a null check..
if (value == null) {
return;
}
sb.appendHtmlConstant("<table>");
if (value.getIcon() != null) {
// Add the contact image.
sb.appendHtmlConstant("<tr><td rowspan='3'>");
sb.appendHtmlConstant("<img border=0 src=" + value.getIcon() + ">");
sb.appendHtmlConstant("</td>");
}
// Add the name and address.
sb.appendHtmlConstant("<td style='font-size:95%;'>");
sb.appendEscaped(value.getName());
sb.appendHtmlConstant("</td></tr>");
//sb.appendEscaped("<tr><td>" + value.getId()+ "</td></tr>");
sb.appendHtmlConstant("</table>");
sb.appendHtmlConstant("<hline>");
}
}
public SearchBox(final Map map) {
final Button searchButton = new Button("Search");
final TextBox searchField = new TextBox();
//searchField.setText("Bremen");
final PathLayer mOverlay = new PathLayer(map, 0xCC0000FF);
map.layers().add(mOverlay);
// We can add style names to widgets
searchButton.addStyleName("sendButton");
RootPanel.get("nameFieldContainer").add(searchField);
RootPanel.get("sendButtonContainer").add(searchButton);
// Focus the cursor on the name field when the app loads
searchField.setFocus(true);
searchField.selectAll();
// Create a cell to render each value in the list.
PoiCell poiCell = new PoiCell();
// Create a CellList that uses the cell.
final CellList<PoiData> cellList = new CellList<PoiData>(poiCell,
PoiData.KEY_PROVIDER);
final SingleSelectionModel<PoiData> selectionModel = new SingleSelectionModel<PoiData>(
PoiData.KEY_PROVIDER);
cellList.setSelectionModel(selectionModel);
final ScrollPanel scroller = new ScrollPanel(cellList);
RootPanel.get("listContainer").add(scroller);
scroller.setSize("350px", "300px");
RootPanel.get("search").getElement().getStyle().setVisibility(Visibility.VISIBLE);
scroller.setVisible(false);
searchField.addFocusHandler(new FocusHandler() {
@Override
public void onFocus(FocusEvent event) {
scroller.setVisible(true);
}
});
selectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
public void onSelectionChange(SelectionChangeEvent event) {
final PoiData d = selectionModel.getSelectedObject();
mOverlay.clearPath();
//log.debug("selected " + d.getName() + " " + d.getLatitude() + " "
// + d.getLongitude());
BoundingBox b = d.getBoundingBox();
if (b != null) {
if (b.maxLatitudeE6 - b.minLatitudeE6 < 100 &&
b.maxLongitudeE6 - b.minLongitudeE6 < 100)
// for small bbox use zoom=16 to get an overview
map.animator().animateTo(500, b.getCenterPoint(), 1 << 16, false);
else
map.animator().animateTo(b);
if (d instanceof NominatimData && ((NominatimData) d).getWkt() != null) {
String wkt = ((NominatimData) d).getWkt();
WKTReader r = new WKTReader();
GeometryBuffer g = new GeometryBuffer(1024, 10);
try {
r.parse(wkt, g);
} catch (Exception e) {
log.debug(wkt);
}
mOverlay.setGeom(g);
//log.debug("add polygon " + p.length());
} else {
mOverlay.addPoint(b.maxLatitudeE6, b.minLongitudeE6);
mOverlay.addPoint(b.maxLatitudeE6, b.maxLongitudeE6);
mOverlay.addPoint(b.minLatitudeE6, b.maxLongitudeE6);
mOverlay.addPoint(b.minLatitudeE6, b.minLongitudeE6);
mOverlay.addPoint(b.maxLatitudeE6, b.minLongitudeE6);
}
// hide overlay after 5 seconds
map.postDelayed(new Runnable() {
@Override
public void run() {
mOverlay.clearPath();
}
}, 5000);
} else {
MapPosition pos = new MapPosition();
map.viewport().setTilt(0);
map.viewport().setRotation(0);
pos.setZoomLevel(13);
pos.setPosition(d.getLatitude(), d.getLongitude());
map.setMapPosition(pos);
}
scroller.setVisible(false);
}
});
// Create a handler for the sendButton and nameField
class MyHandler implements ClickHandler, KeyUpHandler {
/**
* Fired when the user clicks on the sendButton.
*/
public void onClick(ClickEvent event) {
sendRequest();
}
/**
* Fired when the user types in the nameField.
*/
public void onKeyUp(KeyUpEvent event) {
if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
sendRequest();
}
}
/**
* Send the name from the nameField to the server and wait for a
* response.
*/
private void sendRequest() {
String textToServer = searchField.getText();
searchButton.setEnabled(false);
String url = URL
.encode(NOMINATIM_GLOBAL
+ textToServer);
JsonpRequestBuilder builder = new JsonpRequestBuilder();
builder.setCallbackParam("json_callback");
builder.requestObject(url, new AsyncCallback<JsArray<NominatimData>>() {
public void onFailure(Throwable caught) {
log.debug("request failed");
searchButton.setEnabled(true);
}
public void onSuccess(JsArray<NominatimData> data) {
List<PoiData> items = new ArrayList<PoiData>();
for (int i = 0, n = data.length(); i < n; i++) {
NominatimData d = data.get(i);
items.add(d);
}
cellList.setRowCount(items.size(), true);
cellList.setRowData(0, items);
scroller.setVisible(true);
searchButton.setEnabled(true);
}
});
}
}
// Add a handler to send the name to the server
MyHandler handler = new MyHandler();
searchButton.addClickHandler(handler);
searchField.addKeyUpHandler(handler);
}
}

View File

@@ -0,0 +1,240 @@
/*
* Copyright 2013 Hannes Janetzek
*
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.oscim.gdx.client;
import org.oscim.core.GeometryBuffer;
public class WKTReader {
private final static String POINT = "POINT";
private final static String LINE = "LINESTRING";
private final static String POLY = "POLYGON";
private final static String MULTI = "MULTI";
private final static int SKIP_POINT = POINT.length();
private final static int SKIP_LINE = LINE.length();
private final static int SKIP_POLY = POLY.length();
private final static int SKIP_MULTI = MULTI.length();
public void parse(String wkt, GeometryBuffer geom) throws Exception {
// return position.
int[] pos = new int[] { 0 };
int len = wkt.length();
if (wkt.startsWith(POINT, pos[0])) {
pos[0] += SKIP_POINT;
geom.startPoints();
ensure(wkt, pos, '(');
parsePoint(geom, wkt, len, pos);
ensure(wkt, pos, ')');
} else if (wkt.startsWith(LINE, pos[0])) {
pos[0] += SKIP_LINE;
geom.startLine();
parseLine(geom, wkt, len, pos);
} else if (wkt.startsWith(POLY, pos[0])) {
pos[0] += SKIP_POLY;
geom.startPolygon();
parsePoly(geom, wkt, len, pos);
} else if (wkt.startsWith(MULTI, pos[0])) {
pos[0] += SKIP_MULTI;
if (wkt.startsWith(POINT, pos[0])) {
pos[0] += SKIP_POINT;
geom.startPoints();
ensure(wkt, pos, '(');
parsePoint(geom, wkt, len, pos);
while (wkt.charAt(pos[0]) == ',') {
pos[0]++;
parsePoint(geom, wkt, len, pos);
}
ensure(wkt, pos, ')');
} else if (wkt.startsWith(LINE, pos[0])) {
pos[0] += SKIP_LINE;
geom.startLine();
ensure(wkt, pos, '(');
parseLine(geom, wkt, len, pos);
while (wkt.charAt(pos[0]) == ',') {
pos[0]++;
geom.startLine();
parseLine(geom, wkt, len, pos);
}
ensure(wkt, pos, ')');
} else if (wkt.startsWith(POLY, pos[0])) {
pos[0] += SKIP_POLY;
geom.startPolygon();
ensure(wkt, pos, '(');
parsePoly(geom, wkt, len, pos);
while (wkt.charAt(pos[0]) == ',') {
pos[0]++;
geom.startPolygon();
parsePoly(geom, wkt, len, pos);
}
ensure(wkt, pos, ')');
} else
throw new Exception("usupported geometry ");
} else
throw new Exception("usupported geometry ");
}
private static void ensure(String wkt, int[] pos, char c) throws Exception {
if (wkt.charAt(pos[0]) != c)
throw new Exception();
pos[0]++;
}
private static void parsePoly(GeometryBuffer geom, String wkt, int len, int[] adv)
throws Exception {
// outer ring
ensure(wkt, adv, '(');
parseLine(geom, wkt, len, adv);
while (wkt.charAt(adv[0]) == ',') {
adv[0]++;
geom.startHole();
parseLine(geom, wkt, len, adv);
}
ensure(wkt, adv, ')');
}
private static void parseLine(GeometryBuffer geom, String wkt, int len, int[] adv)
throws Exception {
ensure(wkt, adv, '(');
parsePoint(geom, wkt, len, adv);
while (wkt.charAt(adv[0]) == ',') {
adv[0]++;
parsePoint(geom, wkt, len, adv);
}
ensure(wkt, adv, ')');
}
private static void parsePoint(GeometryBuffer geom, String wkt, int len, int[] adv) {
float x = parseNumber(wkt, len, adv);
// skip ' '
adv[0]++;
float y = parseNumber(wkt, len, adv);
geom.addPoint(x, y);
}
static float parseNumber(String wkt, int len, int[] adv) {
int pos = adv[0];
boolean neg = false;
if (wkt.charAt(pos) == '-') {
neg = true;
pos++;
}
float val = 0;
int pre = 0;
char c = 0;
for (; pos < len; pos++, pre++) {
c = wkt.charAt(pos);
if (c < '0' || c > '9') {
if (pre == 0)
throw new NumberFormatException("s " + c);
break;
}
val = val * 10 + (int) (c - '0');
}
if (pre == 0)
throw new NumberFormatException();
if (c == '.') {
float div = 10;
for (pos++; pos < len; pos++) {
c = wkt.charAt(pos);
if (c < '0' || c > '9')
break;
val = val + ((int) (c - '0')) / div;
div *= 10;
}
}
if (c == 'e' || c == 'E') {
// advance 'e'
pos++;
// check direction
int dir = 1;
if (wkt.charAt(pos) == '-') {
dir = -1;
pos++;
}
// skip leading zeros
for (; pos < len; pos++)
if (wkt.charAt(pos) != '0')
break;
int shift = 0;
for (pre = 0; pos < len; pos++, pre++) {
c = wkt.charAt(pos);
if (c < '0' || c > '9') {
// nothing after 'e'
if (pre == 0)
throw new NumberFormatException("e " + c);
break;
}
shift = shift * 10 + (int) (c - '0');
}
// guess it's ok for sane values of E
if (dir > 0) {
while (shift-- > 0)
val *= 10;
} else {
while (shift-- > 0)
val /= 10;
}
}
adv[0] = pos;
return neg ? -val : val;
}
// public static void main(String[] args) {
// WKTReader r = new WKTReader();
// GeometryBuffer geom = new GeometryBuffer(10, 10);
// try {
// String wkt = "MULTIPOINT(0 0,1 0)";
// r.parse(wkt, geom);
// for (int i = 0; i < geom.index.length; i++) {
// int len = geom.index[i];
// if (len < 0)
// break;
// for (int p = 0; p < len; p += 2)
// System.out.println(len + ": " + geom.points[p] + "," + geom.points[p + 1]);
// }
// } catch (Exception e) {
// e.printStackTrace();
// }
// }
}

View File

@@ -0,0 +1,466 @@
/*******************************************************************************
* Copyright 2011 See libgdx AUTHORS file.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package com.badlogic.gdx.backends.gwt;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.badlogic.gdx.Application;
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Audio;
import com.badlogic.gdx.Files;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Graphics;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.LifecycleListener;
import com.badlogic.gdx.Net;
import com.badlogic.gdx.Preferences;
import com.badlogic.gdx.backends.gwt.preloader.Preloader;
import com.badlogic.gdx.backends.gwt.preloader.Preloader.PreloaderCallback;
import com.badlogic.gdx.backends.gwt.preloader.Preloader.PreloaderState;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Clipboard;
import com.badlogic.gdx.utils.ObjectMap;
import com.badlogic.gdx.utils.TimeUtils;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Style;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.InlineHTML;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.VerticalPanel;
/**
* Implementation of an {@link Application} based on GWT. Clients have to
* override {@link #getConfig()} and {@link #getApplicationListener()}. Clients
* can override the default loading screen via {@link #getPreloaderCallback()}
* and implement any loading screen drawing via GWT widgets.
*
* @author mzechner
*/
public abstract class GwtApplication implements EntryPoint, Application {
private final static Logger log = LoggerFactory.getLogger(GwtApplication.class);
private ApplicationListener listener;
private GwtApplicationConfiguration config;
private GwtGraphics graphics;
private GwtInput input;
private GwtNet net;
private Panel root = null;
private Array<Runnable> runnables = new Array<Runnable>();
private Array<Runnable> runnablesHelper = new Array<Runnable>();
private Array<LifecycleListener> lifecycleListeners = new Array<LifecycleListener>();
private int lastWidth;
private int lastHeight;
Preloader preloader;
private static AgentInfo agentInfo;
private ObjectMap<String, Preferences> prefs = new ObjectMap<String, Preferences>();
/** @return the configuration for the {@link GwtApplication}. */
public abstract GwtApplicationConfiguration getConfig();
public String getPreloaderBaseURL() {
return GWT.getHostPageBaseURL() + "assets/";
}
@Override
public void onModuleLoad() {
GwtApplication.agentInfo = computeAgentInfo();
this.listener = getApplicationListener();
this.config = getConfig();
if (config.rootPanel != null) {
this.root = config.rootPanel;
} else {
Element element = Document.get().getElementById("embed-" + GWT.getModuleName());
if (element == null) {
VerticalPanel panel = new VerticalPanel();
panel.setWidth("" + config.width + "px");
panel.setHeight("" + config.height + "px");
panel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
panel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
RootPanel.get().add(panel);
RootPanel.get().setWidth("" + config.width + "px");
RootPanel.get().setHeight("" + config.height + "px");
this.root = panel;
} else {
VerticalPanel panel = new VerticalPanel();
panel.setWidth("" + config.width + "px");
panel.setHeight("" + config.height + "px");
panel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
panel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
element.appendChild(panel.getElement());
root = panel;
}
}
final PreloaderCallback callback = getPreloaderCallback();
preloader = createPreloader();
preloader.preload("assets.txt", new PreloaderCallback() {
@Override
public void error(String file) {
callback.error(file);
}
@Override
public void update(PreloaderState state) {
callback.update(state);
if (state.hasEnded()) {
getRootPanel().clear();
setupLoop();
}
}
});
}
void setupLoop() {
Gdx.app = this;
// setup modules
try {
graphics = new GwtGraphics(root, config);
} catch (Throwable e) {
root.clear();
root.add(new Label("Sorry, your browser doesn't seem to support WebGL"));
return;
}
lastWidth = graphics.getWidth();
lastHeight = graphics.getHeight();
//Gdx.audio = new GwtAudio();
Gdx.graphics = graphics;
Gdx.gl20 = graphics.getGL20();
Gdx.gl = Gdx.gl20;
Gdx.files = new GwtFiles(preloader);
this.input = new GwtInput(graphics.canvas);
Gdx.input = this.input;
this.net = new GwtNet();
Gdx.net = this.net;
// tell listener about app creation
try {
listener.create();
listener.resize(graphics.getWidth(), graphics.getHeight());
} catch (Throwable t) {
error("GwtApplication", "exception: " + t.getMessage(), t);
t.printStackTrace();
throw new RuntimeException(t);
}
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
final int frameTime = (int) ((1f / config.fps) * 1000);
// setup rendering timer
new Timer() {
@Override
public void run() {
try {
mainLoop(this, frameTime);
} catch (Throwable t) {
error("GwtApplication", "exception: " + t.getMessage(), t);
throw new RuntimeException(t);
}
}
//}.scheduleRepeating((int) ((1f / config.fps) * 1000));
}.schedule(1);
}
void mainLoop(Timer timer, int frameTime) {
graphics.update();
if (Gdx.graphics.getWidth() != lastWidth || Gdx.graphics.getHeight() != lastHeight) {
GwtApplication.this.listener.resize(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
lastWidth = graphics.getWidth();
lastHeight = graphics.getHeight();
Gdx.gl.glViewport(0, 0, lastWidth, lastHeight);
}
runnablesHelper.addAll(runnables);
runnables.clear();
for (int i = 0; i < runnablesHelper.size; i++) {
runnablesHelper.get(i).run();
}
runnablesHelper.clear();
listener.render();
input.justTouched = false;
long now = System.currentTimeMillis();
int diff = (int) (now - graphics.lastTimeStamp);
diff = frameTime - diff;
timer.schedule(diff > 5 ? diff : 5);
}
public Panel getRootPanel() {
return root;
}
long loadStart = TimeUtils.nanoTime();
public Preloader createPreloader() {
return new Preloader(getPreloaderBaseURL());
}
public PreloaderCallback getPreloaderCallback() {
final Panel preloaderPanel = new VerticalPanel();
preloaderPanel.setStyleName("gdx-preloader");
final Image logo = new Image(GWT.getModuleBaseURL() + "logo.png");
logo.setStyleName("logo");
preloaderPanel.add(logo);
final Panel meterPanel = new SimplePanel();
meterPanel.setStyleName("gdx-meter");
meterPanel.addStyleName("red");
final InlineHTML meter = new InlineHTML();
final Style meterStyle = meter.getElement().getStyle();
meterStyle.setWidth(0, Unit.PCT);
meterPanel.add(meter);
preloaderPanel.add(meterPanel);
getRootPanel().add(preloaderPanel);
return new PreloaderCallback() {
@Override
public void error(String file) {
System.out.println("error: " + file);
}
@Override
public void update(PreloaderState state) {
meterStyle.setWidth(100f * state.getProgress(), Unit.PCT);
}
};
}
@Override
public Graphics getGraphics() {
return graphics;
}
@Override
public Audio getAudio() {
return Gdx.audio;
}
@Override
public Input getInput() {
return Gdx.input;
}
@Override
public Files getFiles() {
return Gdx.files;
}
@Override
public Net getNet() {
return Gdx.net;
}
@Override
public void log(String tag, String message) {
log.info("{} : {}", tag, message);
}
@Override
public void log(String tag, String message, Throwable exception) {
log.info("{} : {}\n{}", tag, exception, getStackTrace(exception));
}
@Override
public void error(String tag, String message) {
log.error("{} : {}", tag, message);
}
@Override
public void error(String tag, String message, Throwable exception) {
log.error("{} : {}\n{}", tag, message, getStackTrace(exception));
}
@Override
public void debug(String tag, String message) {
log.debug("{} : {}", tag, message);
}
@Override
public void debug(String tag, String message, Throwable exception) {
log.debug("{} : {}\n{}", tag, message, getStackTrace(exception));
}
private String getStackTrace(Throwable e) {
StringBuffer buffer = new StringBuffer();
for (StackTraceElement trace : e.getStackTrace()) {
buffer.append(trace.toString() + "\n");
}
return buffer.toString();
}
@Override
public void setLogLevel(int logLevel) {
}
@Override
public int getLogLevel() {
return LOG_DEBUG;
}
@Override
public ApplicationType getType() {
return ApplicationType.WebGL;
}
@Override
public int getVersion() {
return 0;
}
@Override
public long getJavaHeap() {
return 0;
}
@Override
public long getNativeHeap() {
return 0;
}
@Override
public Preferences getPreferences(String name) {
Preferences pref = prefs.get(name);
if (pref == null) {
pref = new GwtPreferences(name);
prefs.put(name, pref);
}
return pref;
}
@Override
public Clipboard getClipboard() {
return new Clipboard() {
@Override
public String getContents() {
return null;
}
@Override
public void setContents(String content) {
}
};
}
@Override
public void postRunnable(Runnable runnable) {
runnables.add(runnable);
}
@Override
public void exit() {
}
/**
* Contains precomputed information on the user-agent. Useful for dealing
* with browser and OS behavioral differences. Kindly
* borrowed from PlayN
*/
public static AgentInfo agentInfo() {
return agentInfo;
}
/** kindly borrowed from PlayN **/
private static native AgentInfo computeAgentInfo() /*-{
var userAgent = navigator.userAgent.toLowerCase();
return {
// browser type flags
isFirefox : userAgent.indexOf("firefox") != -1,
isChrome : userAgent.indexOf("chrome") != -1,
isSafari : userAgent.indexOf("safari") != -1,
isOpera : userAgent.indexOf("opera") != -1,
isIE : userAgent.indexOf("msie") != -1,
// OS type flags
isMacOS : userAgent.indexOf("mac") != -1,
isLinux : userAgent.indexOf("linux") != -1,
isWindows : userAgent.indexOf("win") != -1
};
}-*/;
/** Returned by {@link #agentInfo}. Kindly borrowed from PlayN. */
public static class AgentInfo extends JavaScriptObject {
public final native boolean isFirefox() /*-{
return this.isFirefox;
}-*/;
public final native boolean isChrome() /*-{
return this.isChrome;
}-*/;
public final native boolean isSafari() /*-{
return this.isSafari;
}-*/;
public final native boolean isOpera() /*-{
return this.isOpera;
}-*/;
public final native boolean isIE() /*-{
return this.isIE;
}-*/;
public final native boolean isMacOS() /*-{
return this.isMacOS;
}-*/;
public final native boolean isLinux() /*-{
return this.isLinux;
}-*/;
public final native boolean isWindows() /*-{
return this.isWindows;
}-*/;
protected AgentInfo() {
}
}
public String getBaseUrl() {
return preloader.baseUrl;
}
public Preloader getPreloader() {
return preloader;
}
@Override
public void addLifecycleListener(LifecycleListener listener) {
synchronized (lifecycleListeners) {
lifecycleListeners.add(listener);
}
}
@Override
public void removeLifecycleListener(LifecycleListener listener) {
synchronized (lifecycleListeners) {
lifecycleListeners.removeValue(listener, true);
}
}
}

View File

@@ -0,0 +1,342 @@
/*******************************************************************************
* Copyright 2011 See libgdx AUTHORS file.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package com.badlogic.gdx.backends.gwt;
import org.oscim.gdx.client.GwtGLAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Graphics;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.GL30;
import com.badlogic.gdx.utils.GdxRuntimeException;
import com.google.gwt.canvas.client.Canvas;
import com.google.gwt.dom.client.CanvasElement;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.webgl.client.WebGLContextAttributes;
import com.google.gwt.webgl.client.WebGLRenderingContext;
public class GwtGraphics implements Graphics {
CanvasElement canvas;
WebGLRenderingContext context;
GL20 gl;
String extensions;
float fps = 0;
long lastTimeStamp = System.currentTimeMillis();
float deltaTime = 0;
float time = 0;
int frames;
GwtApplicationConfiguration config;
boolean inFullscreenMode = false;
double pixelRatio;
public GwtGraphics(Panel root, final GwtApplicationConfiguration config) {
Canvas canvasWidget = Canvas.createIfSupported();
if (canvasWidget == null)
throw new GdxRuntimeException("Canvas not supported");
canvas = canvasWidget.getCanvasElement();
root.add(canvasWidget);
this.pixelRatio = getDevicePixelRatioJSNI();
canvas.setWidth((int) (config.width * pixelRatio));
canvas.setHeight((int) (config.height * pixelRatio));
canvas.getStyle().setWidth(config.width, Unit.PX);
canvas.getStyle().setHeight(config.height, Unit.PX);
this.config = config;
WebGLContextAttributes attributes = WebGLContextAttributes.create();
attributes.setAntialias(config.antialiasing);
attributes.setStencil(config.stencil);
attributes.setAlpha(false);
attributes.setPremultipliedAlpha(false);
context = WebGLRenderingContext.getContext(canvas, attributes);
context.viewport(0, 0, config.width, config.height);
// this actually *enables* the option to use std derivatives in shader..
if (context.getExtension("OES_standard_derivatives") == null) {
}
if (context.getExtension("WEBKIT_WEBGL_depth_texture") == null) {
}
this.gl = config.useDebugGL ? new GwtGL20Debug(context) : new GwtGLAdapter(context);
canvas.setId("gdx-canvas");
Window.addResizeHandler(new ResizeHandler() {
@Override
public void onResize(ResizeEvent event) {
int w = config.rootPanel.getOffsetWidth();
int h = config.rootPanel.getOffsetHeight();
canvas.getStyle().setWidth(w, Unit.PX);
canvas.getStyle().setHeight(h, Unit.PX);
Gdx.app.log("onResize", w + "/" + h);
canvas.setWidth((int) (w * pixelRatio));
canvas.setHeight((int) (h * pixelRatio));
}
});
}
public static native double getDevicePixelRatioJSNI() /*-{
return $wnd.devicePixelRatio || 1.0;
}-*/;
public static native int getWindowWidthJSNI() /*-{
return $wnd.innerWidth;
}-*/;
public static native int getWindowHeightJSNI() /*-{
return $wnd.innerHeight;
}-*/;
public WebGLRenderingContext getContext() {
return context;
}
@Override
public GL20 getGL20() {
return gl;
}
@Override
public int getWidth() {
return canvas.getWidth();
}
@Override
public int getHeight() {
return canvas.getHeight();
}
@Override
public float getDeltaTime() {
return deltaTime;
}
@Override
public int getFramesPerSecond() {
return (int) fps;
}
@Override
public GraphicsType getType() {
return GraphicsType.WebGL;
}
@Override
public float getPpiX() {
return 96;
}
@Override
public float getPpiY() {
return 96;
}
@Override
public float getPpcX() {
return 96 / 2.54f;
}
@Override
public float getPpcY() {
return 96 / 2.54f;
}
@Override
public boolean supportsDisplayModeChange() {
return true;
}
@Override
public DisplayMode[] getDisplayModes() {
return new DisplayMode[] { new DisplayMode(getScreenWidthJSNI(), getScreenHeightJSNI(), 60,
8) {
} };
}
private native int getScreenWidthJSNI() /*-{
return $wnd.screen.width;
}-*/;
private native int getScreenHeightJSNI() /*-{
return $wnd.screen.height;
}-*/;
private native boolean isFullscreenJSNI() /*-{
if ("webkitIsFullScreen" in $doc) {
return $doc.webkitIsFullScreen;
}
if ("mozFullScreen" in $doc) {
return $doc.mozFullScreen;
}
return false
}-*/;
private void fullscreenChanged() {
if (!isFullscreen()) {
canvas.setWidth(config.width);
canvas.setHeight(config.height);
}
}
private native boolean setFullscreenJSNI(GwtGraphics graphics, CanvasElement element) /*-{
if (element.webkitRequestFullScreen) {
element.width = $wnd.screen.width;
element.height = $wnd.screen.height;
element.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT);
$doc
.addEventListener(
"webkitfullscreenchange",
function() {
graphics.@com.badlogic.gdx.backends.gwt.GwtGraphics::fullscreenChanged()();
}, false);
return true;
}
if (element.mozRequestFullScreen) {
element.width = $wnd.screen.width;
element.height = $wnd.screen.height;
element.mozRequestFullScreen();
$doc
.addEventListener(
"mozfullscreenchange",
function() {
graphics.@com.badlogic.gdx.backends.gwt.GwtGraphics::fullscreenChanged()();
}, false);
return true;
}
return false;
}-*/;
private native void exitFullscreen() /*-{
if ($doc.webkitExitFullscreen)
$doc.webkitExitFullscreen();
if ($doc.mozExitFullscreen)
$doc.mozExitFullscreen();
}-*/;
@Override
public DisplayMode getDesktopDisplayMode() {
return new DisplayMode(getScreenWidthJSNI(), getScreenHeightJSNI(), 60, 8) {
};
}
@Override
public boolean setDisplayMode(DisplayMode displayMode) {
if (displayMode.width != getScreenWidthJSNI()
&& displayMode.height != getScreenHeightJSNI())
return false;
return setFullscreenJSNI(this, canvas);
}
@Override
public boolean setDisplayMode(int width, int height, boolean fullscreen) {
if (fullscreen) {
if (width != getScreenWidthJSNI() && height != getScreenHeightJSNI())
return false;
return setFullscreenJSNI(this, canvas);
} else {
if (isFullscreenJSNI())
exitFullscreen();
canvas.setWidth(width);
canvas.setHeight(height);
canvas.getStyle().setWidth(width, Unit.PX);
canvas.getStyle().setHeight(height, Unit.PX);
return true;
}
}
@Override
public BufferFormat getBufferFormat() {
return new BufferFormat(8, 8, 8, 0, 16, config.stencil ? 8 : 0, 0, false);
}
@Override
public boolean supportsExtension(String extension) {
if (extensions == null)
extensions = Gdx.gl.glGetString(GL20.GL_EXTENSIONS);
return extensions.contains(extension);
}
public void update() {
long currTimeStamp = System.currentTimeMillis();
deltaTime = (currTimeStamp - lastTimeStamp) / 1000.0f;
lastTimeStamp = currTimeStamp;
time += deltaTime;
frames++;
if (time > 1) {
this.fps = frames;
time = 0;
frames = 0;
}
}
@Override
public void setTitle(String title) {
}
@Override
public void setVSync(boolean vsync) {
}
@Override
public float getDensity() {
return 96.0f / 160;
}
@Override
public void setContinuousRendering(boolean isContinuous) {
}
@Override
public boolean isContinuousRendering() {
return false;
}
@Override
public void requestRendering() {
}
@Override
public float getRawDeltaTime() {
return getDeltaTime();
}
@Override
public boolean isFullscreen() {
return isFullscreenJSNI();
}
@Override
public boolean isGL30Available() {
return false;
}
@Override
public GL30 getGL30() {
return null;
}
}

View File

@@ -0,0 +1,947 @@
/*******************************************************************************
* Copyright 2011 See AUTHORS file.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package com.badlogic.gdx.backends.gwt;
import java.util.HashSet;
import java.util.Set;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.backends.gwt.widgets.TextInputDialogBox;
import com.badlogic.gdx.backends.gwt.widgets.TextInputDialogBox.TextInputDialogListener;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.utils.TimeUtils;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.dom.client.CanvasElement;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.dom.client.Touch;
import com.google.gwt.event.dom.client.KeyCodes;
public class GwtInput implements Input {
boolean justTouched = false;
private boolean[] touched = new boolean[20];
private int[] touchX = new int[20];
private int[] touchY = new int[20];
private int[] deltaX = new int[20];
private int[] deltaY = new int[20];
Set<Integer> pressedButtons = new HashSet<Integer>();
Set<Integer> pressedKeys = new HashSet<Integer>();
InputProcessor processor;
char lastKeyCharPressed;
float keyRepeatTimer;
long currentEventTimeStamp;
final CanvasElement canvas;
boolean hasFocus = true;
public GwtInput(CanvasElement canvas) {
this.canvas = canvas;
hookEvents();
}
@Override
public float getAccelerometerX() {
return 0;
}
@Override
public float getAccelerometerY() {
return 0;
}
@Override
public float getAccelerometerZ() {
return 0;
}
@Override
public int getX() {
return touchX[0];
}
@Override
public int getX(int pointer) {
return touchX[pointer];
}
@Override
public int getDeltaX() {
return deltaX[0];
}
@Override
public int getDeltaX(int pointer) {
return deltaX[pointer];
}
@Override
public int getY() {
return touchY[0];
}
@Override
public int getY(int pointer) {
return touchY[pointer];
}
@Override
public int getDeltaY() {
return deltaY[0];
}
@Override
public int getDeltaY(int pointer) {
return deltaY[pointer];
}
@Override
public boolean isTouched() {
return touched[0];
}
@Override
public boolean justTouched() {
return justTouched;
}
@Override
public boolean isTouched(int pointer) {
return touched[pointer];
}
@Override
public boolean isButtonPressed(int button) {
return button == Buttons.LEFT && touched[0];
}
@Override
public boolean isKeyPressed(int key) {
if (key == Keys.ANY_KEY)
return pressedKeys.size() > 0;
return pressedKeys.contains(key);
}
@Override
public void getTextInput(TextInputListener listener, String title, String text) {
TextInputDialogBox dialog = new TextInputDialogBox(title, text, null);
final TextInputListener capturedListener = listener;
dialog.setListener(new TextInputDialogListener() {
@Override
public void onPositive(String text) {
if (capturedListener != null) {
capturedListener.input(text);
}
}
@Override
public void onNegative() {
if (capturedListener != null) {
capturedListener.canceled();
}
}
});
}
@Override
public void getPlaceholderTextInput(TextInputListener listener, String title, String placeholder) {
TextInputDialogBox dialog = new TextInputDialogBox(title, null, placeholder);
final TextInputListener capturedListener = listener;
dialog.setListener(new TextInputDialogListener() {
@Override
public void onPositive(String text) {
if (capturedListener != null) {
capturedListener.input(text);
}
}
@Override
public void onNegative() {
if (capturedListener != null) {
capturedListener.canceled();
}
}
});
}
@Override
public void setOnscreenKeyboardVisible(boolean visible) {
}
@Override
public void vibrate(int milliseconds) {
}
@Override
public void vibrate(long[] pattern, int repeat) {
}
@Override
public void cancelVibrate() {
}
@Override
public float getAzimuth() {
return 0;
}
@Override
public float getPitch() {
return 0;
}
@Override
public float getRoll() {
return 0;
}
@Override
public void getRotationMatrix(float[] matrix) {
}
@Override
public long getCurrentEventTime() {
return currentEventTimeStamp;
}
@Override
public void setCatchBackKey(boolean catchBack) {
}
@Override
public void setCatchMenuKey(boolean catchMenu) {
}
@Override
public void setInputProcessor(InputProcessor processor) {
this.processor = processor;
}
@Override
public InputProcessor getInputProcessor() {
return processor;
}
@Override
public boolean isPeripheralAvailable(Peripheral peripheral) {
if (peripheral == Peripheral.Accelerometer)
return false;
if (peripheral == Peripheral.Compass)
return false;
if (peripheral == Peripheral.HardwareKeyboard)
return true;
if (peripheral == Peripheral.MultitouchScreen)
return isTouchScreen();
if (peripheral == Peripheral.OnscreenKeyboard)
return false;
if (peripheral == Peripheral.Vibrator)
return false;
return false;
}
@Override
public int getRotation() {
return 0;
}
@Override
public Orientation getNativeOrientation() {
return Orientation.Landscape;
}
/**
* from https://github.com/toji/game-shim/blob/master/game-shim.js
*
* @return is Cursor catched
*/
private native boolean isCursorCatchedJSNI() /*-{
if (!navigator.pointer) {
navigator.pointer = navigator.webkitPointer || navigator.mozPointer;
}
if (navigator.pointer) {
if (typeof (navigator.pointer.isLocked) === "boolean") {
// Chrome initially launched with this interface
return navigator.pointer.isLocked;
} else if (typeof (navigator.pointer.isLocked) === "function") {
// Some older builds might provide isLocked as a function
return navigator.pointer.isLocked();
} else if (typeof (navigator.pointer.islocked) === "function") {
// For compatibility with early Firefox build
return navigator.pointer.islocked();
}
}
return false;
}-*/;
/**
* from https://github.com/toji/game-shim/blob/master/game-shim.js
*
* @param element Canvas
*/
private native void setCursorCatchedJSNI(CanvasElement element) /*-{
// Navigator pointer is not the right interface according to spec.
// Here for backwards compatibility only
if (!navigator.pointer) {
navigator.pointer = navigator.webkitPointer || navigator.mozPointer;
}
// element.requestPointerLock
if (!element.requestPointerLock) {
element.requestPointerLock = (function() {
return element.webkitRequestPointerLock
|| element.mozRequestPointerLock || function() {
if (navigator.pointer) {
navigator.pointer.lock(element);
}
};
})();
}
element.requestPointerLock();
}-*/;
/** from https://github.com/toji/game-shim/blob/master/game-shim.js */
private native void exitCursorCatchedJSNI() /*-{
if (!$doc.exitPointerLock) {
$doc.exitPointerLock = (function() {
return $doc.webkitExitPointerLock || $doc.mozExitPointerLock
|| function() {
if (navigator.pointer) {
var elem = this;
navigator.pointer.unlock();
}
};
})();
}
}-*/;
/**
* from https://github.com/toji/game-shim/blob/master/game-shim.js
*
* @param event JavaScript Mouse Event
* @return movement in x direction
*/
private native float getMovementXJSNI(NativeEvent event) /*-{
return event.movementX || event.webkitMovementX || 0;
}-*/;
/**
* from https://github.com/toji/game-shim/blob/master/game-shim.js
*
* @param event JavaScript Mouse Event
* @return movement in y direction
*/
private native float getMovementYJSNI(NativeEvent event) /*-{
return event.movementY || event.webkitMovementY || 0;
}-*/;
private static native boolean isTouchScreen() /*-{
return (('ontouchstart' in window) || (navigator.msMaxTouchPoints > 0));
}-*/;
/**
* works only for Chrome > Version 18 with enabled Mouse Lock enable in
* about:flags or start Chrome with the
* --enable-pointer-lock flag
*/
@Override
public void setCursorCatched(boolean catched) {
if (catched)
setCursorCatchedJSNI(canvas);
else
exitCursorCatchedJSNI();
}
@Override
public boolean isCursorCatched() {
return isCursorCatchedJSNI();
}
@Override
public void setCursorPosition(int x, int y) {
// FIXME??
}
@Override
public void setCursorImage(Pixmap pixmap, int xHotspot, int yHotspot) {
}
// kindly borrowed from our dear playn friends...
static native void addEventListener(JavaScriptObject target, String name, GwtInput handler,
boolean capture) /*-{
target
.addEventListener(
name,
function(e) {
handler.@com.badlogic.gdx.backends.gwt.GwtInput::handleEvent(Lcom/google/gwt/dom/client/NativeEvent;)(e);
}, capture);
}-*/;
private static native float getMouseWheelVelocity(NativeEvent evt) /*-{
var delta = 0.0;
var agentInfo = @com.badlogic.gdx.backends.gwt.GwtApplication::agentInfo()();
if (agentInfo.isFirefox) {
if (agentInfo.isMacOS) {
delta = 1.0 * evt.detail;
} else {
delta = 1.0 * evt.detail / 3;
}
} else if (agentInfo.isOpera) {
if (agentInfo.isLinux) {
delta = -1.0 * evt.wheelDelta / 80;
} else {
// on mac
delta = -1.0 * evt.wheelDelta / 40;
}
} else if (agentInfo.isChrome || agentInfo.isSafari) {
delta = -1.0 * evt.wheelDelta / 120;
// handle touchpad for chrome
if (Math.abs(delta) < 1) {
if (agentInfo.isWindows) {
delta = -1.0 * evt.wheelDelta;
} else if (agentInfo.isMacOS) {
delta = -1.0 * evt.wheelDelta / 3;
}
}
}
return delta;
}-*/;
/** Kindly borrowed from PlayN. **/
protected static native String getMouseWheelEvent() /*-{
if (navigator.userAgent.toLowerCase().indexOf('firefox') != -1) {
return "DOMMouseScroll";
} else {
return "mousewheel";
}
}-*/;
/** Kindly borrowed from PlayN. **/
protected static float getRelativeX(NativeEvent e, Element target) {
return e.getClientX() - target.getAbsoluteLeft() + target.getScrollLeft()
+ target.getOwnerDocument().getScrollLeft();
}
/** Kindly borrowed from PlayN. **/
protected static float getRelativeY(NativeEvent e, Element target) {
return e.getClientY() - target.getAbsoluteTop() + target.getScrollTop()
+ target.getOwnerDocument().getScrollTop();
}
private void hookEvents() {
addEventListener(canvas, "mousedown", this, true);
// addEventListener(Document.get(), "mousedown", this, true);
addEventListener(canvas, "mouseup", this, true);
// addEventListener(Document.get(), "mouseup", this, true);
addEventListener(canvas, "mousemove", this, true);
// addEventListener(Document.get(), "mousemove", this, true);
addEventListener(canvas, getMouseWheelEvent(), this, true);
// addEventListener(Document.get(), "keydown", this, false);
// addEventListener(Document.get(), "keyup", this, false);
// addEventListener(Document.get(), "keypress", this, false);
addEventListener(canvas, "keydown", this, false);
addEventListener(canvas, "keyup", this, false);
addEventListener(canvas, "keypress", this, false);
addEventListener(canvas, "touchstart", this, true);
addEventListener(canvas, "touchmove", this, true);
addEventListener(canvas, "touchcancel", this, true);
addEventListener(canvas, "touchend", this, true);
}
private int getButton(int button) {
if (button == NativeEvent.BUTTON_LEFT)
return Buttons.LEFT;
if (button == NativeEvent.BUTTON_RIGHT)
return Buttons.RIGHT;
if (button == NativeEvent.BUTTON_MIDDLE)
return Buttons.MIDDLE;
return Buttons.LEFT;
}
private void handleEvent(NativeEvent e) {
if (e.getType().equals("mousedown")) {
if (!e.getEventTarget().equals(canvas) || touched[0]) {
float mouseX = (int) getRelativeX(e, canvas);
float mouseY = (int) getRelativeY(e, canvas);
if (mouseX < 0 || mouseX > Gdx.graphics.getWidth() || mouseY < 0
|| mouseY > Gdx.graphics.getHeight()) {
hasFocus = false;
}
return;
}
hasFocus = true;
this.justTouched = true;
this.touched[0] = true;
this.pressedButtons.add(getButton(e.getButton()));
this.deltaX[0] = 0;
this.deltaY[0] = 0;
if (isCursorCatched()) {
this.touchX[0] += getMovementXJSNI(e);
this.touchY[0] += getMovementYJSNI(e);
} else {
this.touchX[0] = (int) getRelativeX(e, canvas);
this.touchY[0] = (int) getRelativeY(e, canvas);
}
this.currentEventTimeStamp = TimeUtils.nanoTime();
if (processor != null)
processor.touchDown(touchX[0], touchY[0], 0, getButton(e.getButton()));
}
if (e.getType().equals("mousemove")) {
if (isCursorCatched()) {
this.deltaX[0] = (int) getMovementXJSNI(e);
this.deltaY[0] = (int) getMovementYJSNI(e);
this.touchX[0] += getMovementXJSNI(e);
this.touchY[0] += getMovementYJSNI(e);
} else {
this.deltaX[0] = (int) getRelativeX(e, canvas) - touchX[0];
this.deltaY[0] = (int) getRelativeY(e, canvas) - touchY[0];
this.touchX[0] = (int) getRelativeX(e, canvas);
this.touchY[0] = (int) getRelativeY(e, canvas);
}
this.currentEventTimeStamp = TimeUtils.nanoTime();
if (processor != null) {
if (touched[0])
processor.touchDragged(touchX[0], touchY[0], 0);
else
processor.mouseMoved(touchX[0], touchY[0]);
}
}
if (e.getType().equals("mouseup")) {
if (!touched[0])
return;
this.pressedButtons.remove(getButton(e.getButton()));
this.touched[0] = pressedButtons.size() > 0;
if (isCursorCatched()) {
this.deltaX[0] = (int) getMovementXJSNI(e);
this.deltaY[0] = (int) getMovementYJSNI(e);
this.touchX[0] += getMovementXJSNI(e);
this.touchY[0] += getMovementYJSNI(e);
} else {
this.deltaX[0] = (int) getRelativeX(e, canvas) - touchX[0];
this.deltaY[0] = (int) getRelativeY(e, canvas) - touchY[0];
this.touchX[0] = (int) getRelativeX(e, canvas);
this.touchY[0] = (int) getRelativeY(e, canvas);
}
this.currentEventTimeStamp = TimeUtils.nanoTime();
this.touched[0] = false;
if (processor != null)
processor.touchUp(touchX[0], touchY[0], 0, getButton(e.getButton()));
}
if (e.getType().equals(getMouseWheelEvent())) {
if (processor != null) {
processor.scrolled((int) getMouseWheelVelocity(e));
}
this.currentEventTimeStamp = TimeUtils.nanoTime();
e.preventDefault();
}
if (e.getType().equals("keydown") && hasFocus) {
//System.out.println("keydown");
int code = keyForCode(e.getKeyCode());
if (code == 67) {
e.preventDefault();
if (processor != null) {
processor.keyDown(code);
processor.keyTyped('\b');
}
} else {
if (this.pressedKeys.add(code) && processor != null) {
processor.keyDown(code);
}
}
}
if (e.getType().equals("keypress") && hasFocus) {
//System.out.println("keypress");
char c = (char) e.getCharCode();
if (processor != null)
processor.keyTyped(c);
}
if (e.getType().equals("keyup") && hasFocus) {
//System.out.println("keyup");
int code = keyForCode(e.getKeyCode());
this.pressedKeys.remove(code);
if (processor != null) {
processor.keyUp(code);
}
}
if (e.getType().equals("touchstart")) {
this.justTouched = true;
JsArray<Touch> touches = e.getChangedTouches();
for (int i = 0, j = touches.length(); i < j; i++) {
Touch touch = touches.get(i);
int touchId = touch.getIdentifier();
touched[touchId] = true;
touchX[touchId] = touch.getRelativeX(canvas);
touchY[touchId] = touch.getRelativeY(canvas);
deltaX[touchId] = 0;
deltaY[touchId] = 0;
if (processor != null) {
processor.touchDown(touchX[touchId], touchY[touchId], touchId, Buttons.LEFT);
}
}
this.currentEventTimeStamp = TimeUtils.nanoTime();
e.preventDefault();
}
if (e.getType().equals("touchmove")) {
JsArray<Touch> touches = e.getChangedTouches();
for (int i = 0, j = touches.length(); i < j; i++) {
Touch touch = touches.get(i);
int touchId = touch.getIdentifier();
deltaX[touchId] = touch.getRelativeX(canvas) - touchX[touchId];
deltaY[touchId] = touch.getRelativeY(canvas) - touchY[touchId];
touchX[touchId] = touch.getRelativeX(canvas);
touchY[touchId] = touch.getRelativeY(canvas);
if (processor != null) {
processor.touchDragged(touchX[touchId], touchY[touchId], touchId);
}
}
this.currentEventTimeStamp = TimeUtils.nanoTime();
e.preventDefault();
}
if (e.getType().equals("touchcancel")) {
JsArray<Touch> touches = e.getChangedTouches();
for (int i = 0, j = touches.length(); i < j; i++) {
Touch touch = touches.get(i);
int touchId = touch.getIdentifier();
touched[touchId] = false;
deltaX[touchId] = touch.getRelativeX(canvas) - touchX[touchId];
deltaY[touchId] = touch.getRelativeY(canvas) - touchY[touchId];
touchX[touchId] = touch.getRelativeX(canvas);
touchY[touchId] = touch.getRelativeY(canvas);
if (processor != null) {
processor.touchUp(touchX[touchId], touchY[touchId], touchId, Buttons.LEFT);
}
}
this.currentEventTimeStamp = TimeUtils.nanoTime();
e.preventDefault();
}
if (e.getType().equals("touchend")) {
JsArray<Touch> touches = e.getChangedTouches();
for (int i = 0, j = touches.length(); i < j; i++) {
Touch touch = touches.get(i);
int touchId = touch.getIdentifier();
touched[touchId] = false;
deltaX[touchId] = touch.getRelativeX(canvas) - touchX[touchId];
deltaY[touchId] = touch.getRelativeY(canvas) - touchY[touchId];
touchX[touchId] = touch.getRelativeX(canvas);
touchY[touchId] = touch.getRelativeY(canvas);
if (processor != null) {
processor.touchUp(touchX[touchId], touchY[touchId], touchId, Buttons.LEFT);
}
}
this.currentEventTimeStamp = TimeUtils.nanoTime();
e.preventDefault();
}
// if(hasFocus) e.preventDefault();
}
/** borrowed from PlayN, thanks guys **/
private static int keyForCode(int keyCode) {
switch (keyCode) {
case KeyCodes.KEY_ALT:
return Keys.ALT_LEFT;
case KeyCodes.KEY_BACKSPACE:
return Keys.BACKSPACE;
case KeyCodes.KEY_CTRL:
return Keys.CONTROL_LEFT;
case KeyCodes.KEY_DELETE:
return Keys.DEL;
case KeyCodes.KEY_DOWN:
return Keys.DOWN;
case KeyCodes.KEY_END:
return Keys.END;
case KeyCodes.KEY_ENTER:
return Keys.ENTER;
case KeyCodes.KEY_ESCAPE:
return Keys.ESCAPE;
case KeyCodes.KEY_HOME:
return Keys.HOME;
case KeyCodes.KEY_LEFT:
return Keys.LEFT;
case KeyCodes.KEY_PAGEDOWN:
return Keys.PAGE_DOWN;
case KeyCodes.KEY_PAGEUP:
return Keys.PAGE_UP;
case KeyCodes.KEY_RIGHT:
return Keys.RIGHT;
case KeyCodes.KEY_SHIFT:
return Keys.SHIFT_LEFT;
case KeyCodes.KEY_TAB:
return Keys.TAB;
case KeyCodes.KEY_UP:
return Keys.UP;
case KEY_PAUSE:
return Keys.UNKNOWN; // FIXME
case KEY_CAPS_LOCK:
return Keys.UNKNOWN; // FIXME
case KEY_SPACE:
return Keys.SPACE;
case KEY_INSERT:
return Keys.INSERT;
case KEY_0:
return Keys.NUM_0;
case KEY_1:
return Keys.NUM_1;
case KEY_2:
return Keys.NUM_2;
case KEY_3:
return Keys.NUM_3;
case KEY_4:
return Keys.NUM_4;
case KEY_5:
return Keys.NUM_5;
case KEY_6:
return Keys.NUM_6;
case KEY_7:
return Keys.NUM_7;
case KEY_8:
return Keys.NUM_8;
case KEY_9:
return Keys.NUM_9;
case KEY_A:
return Keys.A;
case KEY_B:
return Keys.B;
case KEY_C:
return Keys.C;
case KEY_D:
return Keys.D;
case KEY_E:
return Keys.E;
case KEY_F:
return Keys.F;
case KEY_G:
return Keys.G;
case KEY_H:
return Keys.H;
case KEY_I:
return Keys.I;
case KEY_J:
return Keys.J;
case KEY_K:
return Keys.K;
case KEY_L:
return Keys.L;
case KEY_M:
return Keys.M;
case KEY_N:
return Keys.N;
case KEY_O:
return Keys.O;
case KEY_P:
return Keys.P;
case KEY_Q:
return Keys.Q;
case KEY_R:
return Keys.R;
case KEY_S:
return Keys.S;
case KEY_T:
return Keys.T;
case KEY_U:
return Keys.U;
case KEY_V:
return Keys.V;
case KEY_W:
return Keys.W;
case KEY_X:
return Keys.X;
case KEY_Y:
return Keys.Y;
case KEY_Z:
return Keys.Z;
case KEY_LEFT_WINDOW_KEY:
return Keys.UNKNOWN; // FIXME
case KEY_RIGHT_WINDOW_KEY:
return Keys.UNKNOWN; // FIXME
// case KEY_SELECT_KEY: return Keys.SELECT_KEY;
case KEY_NUMPAD0:
return Keys.NUMPAD_0;
case KEY_NUMPAD1:
return Keys.NUMPAD_1;
case KEY_NUMPAD2:
return Keys.NUMPAD_2;
case KEY_NUMPAD3:
return Keys.NUMPAD_3;
case KEY_NUMPAD4:
return Keys.NUMPAD_4;
case KEY_NUMPAD5:
return Keys.NUMPAD_5;
case KEY_NUMPAD6:
return Keys.NUMPAD_6;
case KEY_NUMPAD7:
return Keys.NUMPAD_7;
case KEY_NUMPAD8:
return Keys.NUMPAD_8;
case KEY_NUMPAD9:
return Keys.NUMPAD_9;
case KEY_MULTIPLY:
return Keys.UNKNOWN; // FIXME
case KEY_ADD:
return Keys.PLUS;
case KEY_SUBTRACT:
return Keys.MINUS;
case KEY_DECIMAL_POINT_KEY:
return Keys.PERIOD;
case KEY_DIVIDE:
return Keys.UNKNOWN; // FIXME
case KEY_F1:
return Keys.F1;
case KEY_F2:
return Keys.F2;
case KEY_F3:
return Keys.F3;
case KEY_F4:
return Keys.F4;
case KEY_F5:
return Keys.F5;
case KEY_F6:
return Keys.F6;
case KEY_F7:
return Keys.F7;
case KEY_F8:
return Keys.F8;
case KEY_F9:
return Keys.F9;
case KEY_F10:
return Keys.F10;
case KEY_F11:
return Keys.F11;
case KEY_F12:
return Keys.F12;
case KEY_NUM_LOCK:
return Keys.NUM;
case KEY_SCROLL_LOCK:
return Keys.UNKNOWN; // FIXME
case KEY_SEMICOLON:
return Keys.SEMICOLON;
case KEY_EQUALS:
return Keys.EQUALS;
case KEY_COMMA:
return Keys.COMMA;
case KEY_DASH:
return Keys.MINUS;
case KEY_PERIOD:
return Keys.PERIOD;
case KEY_FORWARD_SLASH:
return Keys.SLASH;
case KEY_GRAVE_ACCENT:
return Keys.UNKNOWN; // FIXME
case KEY_OPEN_BRACKET:
return Keys.LEFT_BRACKET;
case KEY_BACKSLASH:
return Keys.BACKSLASH;
case KEY_CLOSE_BRACKET:
return Keys.RIGHT_BRACKET;
case KEY_SINGLE_QUOTE:
return Keys.APOSTROPHE;
default:
return Keys.UNKNOWN;
}
}
// these are absent from KeyCodes; we know not why...
private static final int KEY_PAUSE = 19;
private static final int KEY_CAPS_LOCK = 20;
private static final int KEY_SPACE = 32;
private static final int KEY_INSERT = 45;
private static final int KEY_0 = 48;
private static final int KEY_1 = 49;
private static final int KEY_2 = 50;
private static final int KEY_3 = 51;
private static final int KEY_4 = 52;
private static final int KEY_5 = 53;
private static final int KEY_6 = 54;
private static final int KEY_7 = 55;
private static final int KEY_8 = 56;
private static final int KEY_9 = 57;
private static final int KEY_A = 65;
private static final int KEY_B = 66;
private static final int KEY_C = 67;
private static final int KEY_D = 68;
private static final int KEY_E = 69;
private static final int KEY_F = 70;
private static final int KEY_G = 71;
private static final int KEY_H = 72;
private static final int KEY_I = 73;
private static final int KEY_J = 74;
private static final int KEY_K = 75;
private static final int KEY_L = 76;
private static final int KEY_M = 77;
private static final int KEY_N = 78;
private static final int KEY_O = 79;
private static final int KEY_P = 80;
private static final int KEY_Q = 81;
private static final int KEY_R = 82;
private static final int KEY_S = 83;
private static final int KEY_T = 84;
private static final int KEY_U = 85;
private static final int KEY_V = 86;
private static final int KEY_W = 87;
private static final int KEY_X = 88;
private static final int KEY_Y = 89;
private static final int KEY_Z = 90;
private static final int KEY_LEFT_WINDOW_KEY = 91;
private static final int KEY_RIGHT_WINDOW_KEY = 92;
private static final int KEY_SELECT_KEY = 93;
private static final int KEY_NUMPAD0 = 96;
private static final int KEY_NUMPAD1 = 97;
private static final int KEY_NUMPAD2 = 98;
private static final int KEY_NUMPAD3 = 99;
private static final int KEY_NUMPAD4 = 100;
private static final int KEY_NUMPAD5 = 101;
private static final int KEY_NUMPAD6 = 102;
private static final int KEY_NUMPAD7 = 103;
private static final int KEY_NUMPAD8 = 104;
private static final int KEY_NUMPAD9 = 105;
private static final int KEY_MULTIPLY = 106;
private static final int KEY_ADD = 107;
private static final int KEY_SUBTRACT = 109;
private static final int KEY_DECIMAL_POINT_KEY = 110;
private static final int KEY_DIVIDE = 111;
private static final int KEY_F1 = 112;
private static final int KEY_F2 = 113;
private static final int KEY_F3 = 114;
private static final int KEY_F4 = 115;
private static final int KEY_F5 = 116;
private static final int KEY_F6 = 117;
private static final int KEY_F7 = 118;
private static final int KEY_F8 = 119;
private static final int KEY_F9 = 120;
private static final int KEY_F10 = 121;
private static final int KEY_F11 = 122;
private static final int KEY_F12 = 123;
private static final int KEY_NUM_LOCK = 144;
private static final int KEY_SCROLL_LOCK = 145;
private static final int KEY_SEMICOLON = 186;
private static final int KEY_EQUALS = 187;
private static final int KEY_COMMA = 188;
private static final int KEY_DASH = 189;
private static final int KEY_PERIOD = 190;
private static final int KEY_FORWARD_SLASH = 191;
private static final int KEY_GRAVE_ACCENT = 192;
private static final int KEY_OPEN_BRACKET = 219;
private static final int KEY_BACKSLASH = 220;
private static final int KEY_CLOSE_BRACKET = 221;
private static final int KEY_SINGLE_QUOTE = 222;
}

View File

@@ -0,0 +1,377 @@
/*******************************************************************************
* Copyright 2011 See libgdx AUTHORS file.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package com.badlogic.gdx.graphics;
import java.nio.Buffer;
import java.nio.IntBuffer;
import java.util.HashMap;
import java.util.Map;
import com.badlogic.gdx.backends.gwt.GwtFileHandle;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.utils.BufferUtils;
import com.badlogic.gdx.utils.Disposable;
import com.badlogic.gdx.utils.GdxRuntimeException;
import com.google.gwt.canvas.client.Canvas;
import com.google.gwt.canvas.dom.client.CanvasPixelArray;
import com.google.gwt.canvas.dom.client.Context2d;
import com.google.gwt.canvas.dom.client.Context2d.Composite;
import com.google.gwt.dom.client.CanvasElement;
import com.google.gwt.dom.client.ImageElement;
public class Pixmap implements Disposable {
public static Map<Integer, Pixmap> pixmaps = new HashMap<Integer, Pixmap>();
static int nextId = 0;
/** Different pixel formats.
*
* @author mzechner */
public enum Format {
Alpha, Intensity, LuminanceAlpha, RGB565, RGBA4444, RGB888, RGBA8888;
}
/** Blending functions to be set with {@link Pixmap#setBlending}.
* @author mzechner */
public enum Blending {
None, SourceOver
}
/** Filters to be used with {@link Pixmap#drawPixmap(Pixmap, int, int, int, int, int, int, int, int)}.
*
* @author mzechner */
public enum Filter {
NearestNeighbour, BiLinear
}
int width;
int height;
Format format;
Canvas canvas;
Context2d context;
int id;
IntBuffer buffer;
int r = 255, g = 255, b = 255;
float a;
String color = make(r, g, b, a);
static Blending blending;
CanvasPixelArray pixels;
public Context2d getContext(){
return context;
}
public Pixmap (FileHandle file) {
GwtFileHandle gwtFile = (GwtFileHandle)file;
ImageElement img = gwtFile.preloader.images.get(file.path());
if (img == null) throw new GdxRuntimeException("Couldn't load image '" + file.path() + "', file does not exist");
create(img.getWidth(), img.getHeight(), Format.RGBA8888);
context.setGlobalCompositeOperation(Composite.COPY);
context.drawImage(img, 0, 0);
context.setGlobalCompositeOperation(getComposite());
}
private static Composite getComposite () {
return blending == Blending.None ? Composite.COPY : Composite.SOURCE_OVER;
}
public Pixmap (ImageElement img) {
create(img.getWidth(), img.getHeight(), Format.RGBA8888);
context.drawImage(img, 0, 0);
}
public Pixmap (int width, int height, Format format) {
create(width, height, format);
}
private void create (int width, int height, Format format2) {
this.width = width;
this.height = height;
this.format = Format.RGBA8888;
canvas = Canvas.createIfSupported();
canvas.getCanvasElement().setWidth(width);
canvas.getCanvasElement().setHeight(height);
context = canvas.getContext2d();
context.setGlobalCompositeOperation(getComposite());
buffer = BufferUtils.newIntBuffer(1);
id = nextId++;
buffer.put(0, id);
pixmaps.put(id, this);
}
public static String make (int r2, int g2, int b2, float a2) {
return "rgba(" + r2 + "," + g2 + "," + b2 + "," + a2 + ")";
}
/** Sets the type of {@link Blending} to be used for all operations. Default is {@link Blending#SourceOver}.
* @param blending the blending type */
public static void setBlending (Blending blending) {
Pixmap.blending = blending;
Composite composite = getComposite();
for (Pixmap pixmap : pixmaps.values()) {
pixmap.context.setGlobalCompositeOperation(composite);
}
}
/** @return the currently set {@link Blending} */
public static Blending getBlending () {
return blending;
}
/** Sets the type of interpolation {@link Filter} to be used in conjunction with
* {@link Pixmap#drawPixmap(Pixmap, int, int, int, int, int, int, int, int)}.
* @param filter the filter. */
public static void setFilter (Filter filter) {
}
public Format getFormat () {
return format;
}
public int getGLInternalFormat () {
return GL20.GL_RGBA;
}
public int getGLFormat () {
return GL20.GL_RGBA;
}
public int getGLType () {
return GL20.GL_UNSIGNED_BYTE;
}
public int getWidth () {
return width;
}
public int getHeight () {
return height;
}
public Buffer getPixels () {
return buffer;
}
@Override
public void dispose () {
pixmaps.remove(id);
}
public CanvasElement getCanvasElement () {
return canvas.getCanvasElement();
}
/** Sets the color for the following drawing operations
* @param color the color, encoded as RGBA8888 */
public void setColor (int color) {
r = (color >>> 24) & 0xff;
g = (color >>> 16) & 0xff;
b = (color >>> 8) & 0xff;
a = (color & 0xff) / 255f;
this.color = make(r, g, b, a);
context.setFillStyle(this.color);
context.setStrokeStyle(this.color);
}
/** Sets the color for the following drawing operations.
*
* @param r The red component.
* @param g The green component.
* @param b The blue component.
* @param a The alpha component. */
public void setColor (float r, float g, float b, float a) {
this.r = (int)(r * 255);
this.g = (int)(g * 255);
this.b = (int)(b * 255);
this.a = a;
color = make(this.r, this.g, this.b, this.a);
context.setFillStyle(color);
context.setStrokeStyle(this.color);
}
/** Sets the color for the following drawing operations.
* @param color The color. */
public void setColor (Color color) {
setColor(color.r, color.g, color.b, color.a);
}
/** Fills the complete bitmap with the currently set color. */
public void fill () {
context.fillRect(0, 0, getWidth(), getHeight());
}
// /**
// * Sets the width in pixels of strokes.
// *
// * @param width The stroke width in pixels.
// */
// public void setStrokeWidth (int width);
/** Draws a line between the given coordinates using the currently set color.
*
* @param x The x-coodinate of the first point
* @param y The y-coordinate of the first point
* @param x2 The x-coordinate of the first point
* @param y2 The y-coordinate of the first point */
public void drawLine (int x, int y, int x2, int y2) {
context.beginPath();
context.moveTo(x, y);
context.lineTo(x2, y2);
context.stroke();
context.closePath();
}
/** Draws a rectangle outline starting at x, y extending by width to the right and by height downwards (y-axis points downwards)
* using the current color.
*
* @param x The x coordinate
* @param y The y coordinate
* @param width The width in pixels
* @param height The height in pixels */
public void drawRectangle (int x, int y, int width, int height) {
context.beginPath();
context.rect(x, y, width, height);
context.stroke();
context.closePath();
}
/** Draws an area form another Pixmap to this Pixmap.
*
* @param pixmap The other Pixmap
* @param x The target x-coordinate (top left corner)
* @param y The target y-coordinate (top left corner) */
public void drawPixmap (Pixmap pixmap, int x, int y) {
context.drawImage(pixmap.getCanvasElement(), x, y);
}
/** Draws an area form another Pixmap to this Pixmap.
*
* @param pixmap The other Pixmap
* @param x The target x-coordinate (top left corner)
* @param y The target y-coordinate (top left corner)
* @param srcx The source x-coordinate (top left corner)
* @param srcy The source y-coordinate (top left corner);
* @param srcWidth The width of the area form the other Pixmap in pixels
* @param srcHeight The height of the area form the other Pixmap in pixles */
public void drawPixmap (Pixmap pixmap, int x, int y, int srcx, int srcy, int srcWidth, int srcHeight) {
context.drawImage(pixmap.getCanvasElement(), srcx, srcy, srcWidth, srcHeight, x, y, srcWidth, srcHeight);
}
/** Draws an area form another Pixmap to this Pixmap. This will automatically scale and stretch the source image to the
* specified target rectangle. Use {@link Pixmap#setFilter(Filter)} to specify the type of filtering to be used (nearest
* neighbour or bilinear).
*
* @param pixmap The other Pixmap
* @param srcx The source x-coordinate (top left corner)
* @param srcy The source y-coordinate (top left corner);
* @param srcWidth The width of the area form the other Pixmap in pixels
* @param srcHeight The height of the area form the other Pixmap in pixles
* @param dstx The target x-coordinate (top left corner)
* @param dsty The target y-coordinate (top left corner)
* @param dstWidth The target width
* @param dstHeight the target height */
public void drawPixmap (Pixmap pixmap, int srcx, int srcy, int srcWidth, int srcHeight, int dstx, int dsty, int dstWidth,
int dstHeight) {
context.drawImage(pixmap.getCanvasElement(), srcx, srcy, srcWidth, srcHeight, dstx, dsty, dstWidth, dstHeight);
}
/** Fills a rectangle starting at x, y extending by width to the right and by height downwards (y-axis points downwards) using
* the current color.
*
* @param x The x coordinate
* @param y The y coordinate
* @param width The width in pixels
* @param height The height in pixels */
public void fillRectangle (int x, int y, int width, int height) {
context.fillRect(x, y, width, height);
}
/** Draws a circle outline with the center at x,y and a radius using the current color and stroke width.
*
* @param x The x-coordinate of the center
* @param y The y-coordinate of the center
* @param radius The radius in pixels */
public void drawCircle (int x, int y, int radius) {
context.beginPath();
context.arc(x, y, radius, 0, 2 * Math.PI, false);
context.stroke();
context.closePath();
}
/** Fills a circle with the center at x,y and a radius using the current color.
*
* @param x The x-coordinate of the center
* @param y The y-coordinate of the center
* @param radius The radius in pixels */
public void fillCircle (int x, int y, int radius) {
context.beginPath();
context.arc(x, y, radius, 0, 2 * Math.PI, false);
context.fill();
context.closePath();
}
/** Fills a triangle with vertices at x1,y1 and x2,y2 and x3,y3 using the current color.
*
* @param x1 The x-coordinate of vertex 1
* @param y1 The y-coordinate of vertex 1
* @param x2 The x-coordinate of vertex 2
* @param y2 The y-coordinate of vertex 2
* @param x3 The x-coordinate of vertex 3
* @param y3 The y-coordinate of vertex 3 */
public void fillTriangle (int x1, int y1, int x2, int y2, int x3, int y3) {
context.beginPath();
context.moveTo(x1,y1);
context.lineTo(x2,y2);
context.lineTo(x3,y3);
context.lineTo(x1,y1);
context.fill();
context.closePath();
}
/** Returns the 32-bit RGBA8888 value of the pixel at x, y. For Alpha formats the RGB components will be one.
*
* @param x The x-coordinate
* @param y The y-coordinate
* @return The pixel color in RGBA8888 format. */
public int getPixel (int x, int y) {
if (pixels == null) pixels = context.getImageData(0, 0, width, height).getData();
int i = x * 4 + y * width * 4;
int r = pixels.get(i + 0) & 0xff;
int g = pixels.get(i + 1) & 0xff;
int b = pixels.get(i + 2) & 0xff;
int a = pixels.get(i + 3) & 0xff;
return (r << 24) | (g << 16) | (b << 8) | (a);
}
/** Draws a pixel at the given location with the current color.
*
* @param x the x-coordinate
* @param y the y-coordinate */
public void drawPixel (int x, int y) {
context.fillRect(x, y, 1, 1);
}
/** Draws a pixel at the given location with the given color.
*
* @param x the x-coordinate
* @param y the y-coordinate
* @param color the color in RGBA8888 format. */
public void drawPixel (int x, int y, int color) {
setColor(color);
drawPixel(x, y);
}
}

View File

@@ -0,0 +1,10 @@
package java.net;
public class MalformedURLException extends Exception {
/**
*
*/
private static final long serialVersionUID = 1L;
}

View File

@@ -0,0 +1,22 @@
package java.net;
public class URL {
@Override
public String toString() {
return mPath;
}
String mProtocol;
String mHostname;
int mPort;
String mPath;
public URL(String protocol, String hostName, int port, String path) {
//mPath = "http://" +hostName +"/" + path;
mPath = path;
}
public URL(String path) throws MalformedURLException {
mPath = path;
}
}

View File

@@ -0,0 +1,10 @@
package java.util.concurrent;
public class CancellationException extends IllegalStateException {
/**
*
*/
private static final long serialVersionUID = 1L;
}

View File

@@ -0,0 +1,12 @@
package java.util.concurrent;
import java.util.ArrayList;
public class CopyOnWriteArrayList<E> extends ArrayList<E> {
/**
*
*/
private static final long serialVersionUID = 1L;
}

View File

@@ -0,0 +1,75 @@
package org.oscim.backend;
import org.xml.sax.Attributes;
import com.google.gwt.xml.client.NamedNodeMap;
import com.google.gwt.xml.client.Node;
public class MyAttributes implements Attributes {
private NamedNodeMap map;
public MyAttributes(Node n) {
map = n.getAttributes();
}
public String getValue(int i) {
return map.item(i).getNodeValue();
}
public int getLength() {
return map.getLength();
}
public String getLocalName(int i) {
return map.item(i).getNodeName();
}
public String getValue(String string) {
Node n = map.getNamedItem(string);
if (n == null)
return null;
return n.getNodeValue();
}
@Override
public String getURI(int paramInt) {
return null;
}
@Override
public String getQName(int paramInt) {
return null;
}
@Override
public String getType(int paramInt) {
return null;
}
@Override
public int getIndex(String paramString1, String paramString2) {
return 0;
}
@Override
public int getIndex(String paramString) {
return 0;
}
@Override
public String getType(String paramString1, String paramString2) {
return null;
}
@Override
public String getType(String paramString) {
return null;
}
@Override
public String getValue(String paramString1, String paramString2) {
return null;
}
}

View File

@@ -0,0 +1,61 @@
package org.oscim.backend;
import java.io.IOException;
import java.io.InputStream;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import com.google.gwt.xml.client.Document;
import com.google.gwt.xml.client.Node;
import com.google.gwt.xml.client.NodeList;
import com.google.gwt.xml.client.XMLParser;
public class MyXMLReader {
public void parse(InputStream is) throws SAXException {
StringBuilder sb = new StringBuilder();
byte[] buf = new byte[8192];
int read;
try {
while ((read = is.read(buf)) >= 0) {
if (read > 0)
sb.append(new String(buf, 0, read));
}
} catch (IOException e) {
e.printStackTrace();
}
Document d = XMLParser.parse(sb.toString());
handleElement(d.getFirstChild());
mHandler.endDocument();
}
int level = 0;
void handleElement(Node n) throws SAXException {
if (n == null) {
return;
}
if (n.getNodeType() == Node.ELEMENT_NODE) {
String localName = n.getNodeName();
mHandler.startElement(null, localName, null, new MyAttributes(n));
if (n.hasChildNodes()) {
NodeList l = n.getChildNodes();
for (int i = 0, len = l.getLength(); i < len; i++) {
handleElement(l.item(i));
}
}
mHandler.endElement(null, localName, null);
}
}
private DefaultHandler mHandler;
public void setContentHandler(DefaultHandler handler) {
mHandler = handler;
}
}

View File

@@ -0,0 +1,16 @@
package org.oscim.backend;
import java.io.IOException;
import java.io.InputStream;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class XMLReaderAdapter {
public void parse(DefaultHandler handler, InputStream is) throws IOException, SAXException {
MyXMLReader xmlReader = new MyXMLReader();
xmlReader.setContentHandler(handler);
xmlReader.parse(is);
}
}

View File

@@ -0,0 +1,19 @@
package org.oscim.layers.tile;
import org.oscim.renderer.MapRenderer;
import com.badlogic.gdx.Gdx;
public abstract class LoadDelayTask implements Runnable {
@Override
public void run() {
if (MapRenderer.frametime == TileLoader.lastLoadTime) {
Gdx.app.postRunnable(this);
return;
}
continueLoading();
}
public abstract void continueLoading();
}

View File

@@ -0,0 +1,155 @@
/*
* Copyright 2013 Hannes Janetzek
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.oscim.layers.tile;
import static org.oscim.tiling.ITileDataSink.QueryResult.FAILED;
import static org.oscim.tiling.ITileDataSink.QueryResult.SUCCESS;
import org.oscim.backend.canvas.Bitmap;
import org.oscim.core.MapElement;
import org.oscim.renderer.MapRenderer;
import org.oscim.tiling.ITileDataSink;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.utils.Timer;
public abstract class TileLoader implements ITileDataSink {
final static Logger log = LoggerFactory.getLogger(TileLoader.class);
private final TileManager mTileManager;
private Timer mTimer;
public TileLoader(TileManager tileManager) {
if (mTimer == null)
mTimer = new Timer();
mTileManager = tileManager;
}
public abstract void cleanup();
protected abstract boolean loadTile(MapTile tile);
boolean isInterrupted;
public void interrupt() {
isInterrupted = true;
// cancel loading
}
boolean mPausing;
public boolean isCanceled() {
return mPausing;
}
public boolean isPausing() {
return mPausing;
}
public void pause() {
mPausing = true;
}
public void proceed() {
mPausing = false;
// FIXME
mWorking = false;
if (mTileManager.hasTileJobs())
go();
}
public void awaitPausing() {
}
public void start() {
mPausing = false;
}
protected boolean mWorking;
protected MapTile mTile;
public void go() {
if (mWorking)
return;
mTile = mTileManager.getTileJob();
if (mTile == null)
return;
try {
loadTile(mTile);
mWorking = true;
} catch (Exception e) {
e.printStackTrace();
completed(FAILED);
}
}
public static long lastLoadTime;
/**
* Callback to be called by TileDataSource when finished
* loading or on failure. MUST BE CALLED IN ANY CASE!
*/
@Override
public void completed(QueryResult result) {
boolean success = (result == SUCCESS) && !isInterrupted;
long now = MapRenderer.frametime;
log.debug("completed {} diff time:{}", mTile, (now - lastLoadTime));
lastLoadTime = now;
mTileManager.jobCompleted(mTile, success);
mTile = null;
mWorking = false;
if (mPausing || !mTileManager.hasTileJobs())
return;
Gdx.app.postRunnable(new Runnable() {
@Override
public void run() {
go();
}
});
}
/**
* Called by TileDataSource
*/
@Override
public void process(MapElement element) {
}
/**
* Called by TileDataSource
*/
@Override
public void setTileImage(Bitmap bitmap) {
}
public static void postLoadDelay(LoadDelayTask task) {
Gdx.app.postRunnable(task);
}
}

View File

@@ -0,0 +1,620 @@
/*******************************************************************************
* Copyright 2011 See libgdx AUTHORS file.
* Copyright 2013 Hannes Janetzek
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package org.oscim.renderer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
public class GLMatrix {
public static final int M00 = 0;// 0;
public static final int M01 = 4;// 1;
public static final int M02 = 8;// 2;
public static final int M03 = 12;// 3;
public static final int M10 = 1;// 4;
public static final int M11 = 5;// 5;
public static final int M12 = 9;// 6;
public static final int M13 = 13;// 7;
public static final int M20 = 2;// 8;
public static final int M21 = 6;// 9;
public static final int M22 = 10;// 10;
public static final int M23 = 14;// 11;
public static final int M30 = 3;// 12;
public static final int M31 = 7;// 13;
public static final int M32 = 11;// 14;
public static final int M33 = 15;// 15;
private final FloatBuffer buffer = ByteBuffer.allocateDirect(16 * 4)
.order(ByteOrder.nativeOrder())
.asFloatBuffer();
private final static String INVALID_INPUT = "Bad Array!";
public final float tmp[] = new float[16];
public final float val[] = new float[16];
/**
* Sets the matrix to the given matrix as a float array. The float array
* must have at least 16 elements; the first 16 will be
* copied.
*
* @param values The matrix, in float form, that is to be copied. Remember
* that this matrix is in <a
* href="http://en.wikipedia.org/wiki/Row-major_order">column
* major</a> order.
* @return This matrix for the purpose of chaining methods together.
*/
public void set(float[] values) {
val[M00] = values[M00];
val[M10] = values[M10];
val[M20] = values[M20];
val[M30] = values[M30];
val[M01] = values[M01];
val[M11] = values[M11];
val[M21] = values[M21];
val[M31] = values[M31];
val[M02] = values[M02];
val[M12] = values[M12];
val[M22] = values[M22];
val[M32] = values[M32];
val[M03] = values[M03];
val[M13] = values[M13];
val[M23] = values[M23];
val[M33] = values[M33];
}
/**
* Get the Matrix as float array
*
* @param m float array to store Matrix
*/
public void get(float[] m) {
if (m == null || m.length != 16)
throw new IllegalArgumentException(INVALID_INPUT);
System.arraycopy(val, 0, m, 0, 16);
}
/**
* Copy values from mat
*
* @param mat Matrix to copy
*/
public void copy(GLMatrix m) {
if (m == null || m.val.length != 16)
throw new IllegalArgumentException(INVALID_INPUT);
System.arraycopy(m.val, 0, val, 0, 16);
}
/**
* Project Vector with Matrix
*
* @param vec3 Vector to project
*/
public void prj(float[] vec3) {
if (vec3 == null || vec3.length < 3)
throw new IllegalArgumentException(INVALID_INPUT);
matrix4_proj(val, vec3);
}
static void matrix4_proj(float[] mat, float[] vec) {
float inv_w = 1.0f / (vec[0] * mat[M30] + vec[1] * mat[M31] + vec[2] * mat[M32] + mat[M33]);
float x = (vec[0] * mat[M00] + vec[1] * mat[M01] + vec[2] * mat[M02] + mat[M03]) * inv_w;
float y = (vec[0] * mat[M10] + vec[1] * mat[M11] + vec[2] * mat[M12] + mat[M13]) * inv_w;
float z = (vec[0] * mat[M20] + vec[1] * mat[M21] + vec[2] * mat[M22] + mat[M23]) * inv_w;
vec[0] = x;
vec[1] = y;
vec[2] = z;
}
/**
* Multiply rhs onto Matrix.
*
* @param rhs right hand side
*/
public void multiplyRhs(GLMatrix rhs) {
matrix4_mul(val, rhs.val);
}
/**
* Use this matrix as rhs, multiply it on lhs and store result.
*
* @param lhs right hand side
*/
public void multiplyLhs(GLMatrix lhs) {
System.arraycopy(lhs.val, 0, tmp, 0, 16);
matrix4_mul(tmp, val);
System.arraycopy(tmp, 0, val, 0, 16);
}
/**
* Multiply rhs onto lhs and store result in Matrix.
*
* This matrix MUST be different from lhs and rhs!
*
* As you know, when combining matrices for vector projection
* this has the same effect first as applying rhs then lhs.
*
* @param lhs left hand side
* @param rhs right hand side
*/
public void multiplyMM(GLMatrix lhs, GLMatrix rhs) {
System.arraycopy(lhs.val, 0, tmp, 0, 16);
matrix4_mul(tmp, rhs.val);
System.arraycopy(tmp, 0, val, 0, 16);
}
/**
* Transpose mat and store result in Matrix
*
* @param mat to transpose
*/
public void transposeM(GLMatrix mat) {
val[M00] = mat.val[M00];
val[M01] = mat.val[M10];
val[M02] = mat.val[M20];
val[M03] = mat.val[M30];
val[M10] = mat.val[M01];
val[M11] = mat.val[M11];
val[M12] = mat.val[M21];
val[M13] = mat.val[M31];
val[M20] = mat.val[M02];
val[M21] = mat.val[M12];
val[M22] = mat.val[M22];
val[M23] = mat.val[M32];
val[M30] = mat.val[M03];
val[M31] = mat.val[M13];
val[M32] = mat.val[M23];
val[M33] = mat.val[M33];
}
/**
* Set rotation
*
* @param a angle in degree
* @param x around x-axis
* @param y around y-axis
* @param z around z-axis
*/
public void setRotation(float a, float x, float y, float z) {
setRotateM(val, 0, a, x, y, z);
}
/**
* Set translation
*
* @param x along x-axis
* @param y along y-axis
* @param z along z-axis
*/
public void setTranslation(float x, float y, float z) {
setIdentity();
val[M03] = x;
val[M13] = y;
val[M23] = z;
}
/**
* Set scale factor
*
* @param x axis
* @param y axis
* @param z axis
*/
public void setScale(float x, float y, float z) {
setIdentity();
val[M00] = x;
val[M11] = y;
val[M22] = z;
}
/**
* Set translation and x,y scale
*
* @param tx translate x
* @param ty translate y
* @param scale factor x,y
*/
public void setTransScale(float tx, float ty, float scale) {
setIdentity();
val[M03] = tx;
val[M13] = ty;
val[M00] = scale;
val[M11] = scale;
}
/**
* Set Matrix with glUniformMatrix
*
* @param location GL location id
*/
public void setAsUniform(int location) {
buffer.clear();
buffer.put(val, 0, 16);
buffer.position(0);
MapRenderer.GL.glUniformMatrix4fv(location, 1, false, buffer);
}
/**
* Set single value
*
* @param pos at position
* @param value value to set
*/
public void setValue(int pos, float value) {
val[pos] = value;
}
static float PiTimesThumb = 1.0f / (1 << 11);
/**
* add some offset (similar to glDepthOffset)
*
* @param delta offset
*/
public void addDepthOffset(int delta) {
val[10] *= 1.0f + PiTimesThumb * delta;
}
/**
* Set identity matrix
*/
public void setIdentity() {
val[M00] = 1;
val[M01] = 0;
val[M02] = 0;
val[M03] = 0;
val[M10] = 0;
val[M11] = 1;
val[M12] = 0;
val[M13] = 0;
val[M20] = 0;
val[M21] = 0;
val[M22] = 1;
val[M23] = 0;
val[M30] = 0;
val[M31] = 0;
val[M32] = 0;
val[M33] = 1;
}
static void matrix4_mul(float[] mata, float[] matb) {
float tmp[] = new float[16];
tmp[M00] = mata[M00] * matb[M00] + mata[M01] * matb[M10] + mata[M02] * matb[M20]
+ mata[M03] * matb[M30];
tmp[M01] = mata[M00] * matb[M01] + mata[M01] * matb[M11] + mata[M02] * matb[M21]
+ mata[M03] * matb[M31];
tmp[M02] = mata[M00] * matb[M02] + mata[M01] * matb[M12] + mata[M02] * matb[M22]
+ mata[M03] * matb[M32];
tmp[M03] = mata[M00] * matb[M03] + mata[M01] * matb[M13] + mata[M02] * matb[M23]
+ mata[M03] * matb[M33];
tmp[M10] = mata[M10] * matb[M00] + mata[M11] * matb[M10] + mata[M12] * matb[M20]
+ mata[M13] * matb[M30];
tmp[M11] = mata[M10] * matb[M01] + mata[M11] * matb[M11] + mata[M12] * matb[M21]
+ mata[M13] * matb[M31];
tmp[M12] = mata[M10] * matb[M02] + mata[M11] * matb[M12] + mata[M12] * matb[M22]
+ mata[M13] * matb[M32];
tmp[M13] = mata[M10] * matb[M03] + mata[M11] * matb[M13] + mata[M12] * matb[M23]
+ mata[M13] * matb[M33];
tmp[M20] = mata[M20] * matb[M00] + mata[M21] * matb[M10] + mata[M22] * matb[M20]
+ mata[M23] * matb[M30];
tmp[M21] = mata[M20] * matb[M01] + mata[M21] * matb[M11] + mata[M22] * matb[M21]
+ mata[M23] * matb[M31];
tmp[M22] = mata[M20] * matb[M02] + mata[M21] * matb[M12] + mata[M22] * matb[M22]
+ mata[M23] * matb[M32];
tmp[M23] = mata[M20] * matb[M03] + mata[M21] * matb[M13] + mata[M22] * matb[M23]
+ mata[M23] * matb[M33];
tmp[M30] = mata[M30] * matb[M00] + mata[M31] * matb[M10] + mata[M32] * matb[M20]
+ mata[M33] * matb[M30];
tmp[M31] = mata[M30] * matb[M01] + mata[M31] * matb[M11] + mata[M32] * matb[M21]
+ mata[M33] * matb[M31];
tmp[M32] = mata[M30] * matb[M02] + mata[M31] * matb[M12] + mata[M32] * matb[M22]
+ mata[M33] * matb[M32];
tmp[M33] = mata[M30] * matb[M03] + mata[M31] * matb[M13] + mata[M32] * matb[M23]
+ mata[M33] * matb[M33];
System.arraycopy(tmp, 0, mata, 0, 16);
}
// @Override
// public void finalize() {
// if (pointer != 0)
// delete(pointer);
// }
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Define a projection matrix in terms of six clip planes
*
* @param m the float array that holds the perspective matrix
* @param offset the offset into float array m where the perspective
* matrix data is written
*/
public static void frustumM(float[] m, int offset,
float left, float right, float bottom, float top,
float near, float far) {
if (left == right) {
throw new IllegalArgumentException("left == right");
}
if (top == bottom) {
throw new IllegalArgumentException("top == bottom");
}
if (near == far) {
throw new IllegalArgumentException("near == far");
}
if (near <= 0.0f) {
throw new IllegalArgumentException("near <= 0.0f");
}
if (far <= 0.0f) {
throw new IllegalArgumentException("far <= 0.0f");
}
final float r_width = 1.0f / (right - left);
final float r_height = 1.0f / (top - bottom);
final float r_depth = 1.0f / (near - far);
final float x = 2.0f * (near * r_width);
final float y = 2.0f * (near * r_height);
final float A = (right + left) * r_width;
final float B = (top + bottom) * r_height;
final float C = (far + near) * r_depth;
final float D = 2.0f * (far * near * r_depth);
m[offset + 0] = x;
m[offset + 5] = y;
m[offset + 8] = A;
m[offset + 9] = B;
m[offset + 10] = C;
m[offset + 14] = D;
m[offset + 11] = -1.0f;
m[offset + 1] = 0.0f;
m[offset + 2] = 0.0f;
m[offset + 3] = 0.0f;
m[offset + 4] = 0.0f;
m[offset + 6] = 0.0f;
m[offset + 7] = 0.0f;
m[offset + 12] = 0.0f;
m[offset + 13] = 0.0f;
m[offset + 15] = 0.0f;
}
/**
* Inverts a 4 x 4 matrix.
*
* @param mInv the array that holds the output inverted matrix
* @param mInvOffset an offset into mInv where the inverted matrix is
* stored.
* @param m the input array
* @param mOffset an offset into m where the matrix is stored.
* @return true if the matrix could be inverted, false if it could not.
*/
public static boolean invertM(float[] mInv, int mInvOffset, float[] m,
int mOffset) {
// Invert a 4 x 4 matrix using Cramer's Rule
// transpose matrix
final float src0 = m[mOffset + 0];
final float src4 = m[mOffset + 1];
final float src8 = m[mOffset + 2];
final float src12 = m[mOffset + 3];
final float src1 = m[mOffset + 4];
final float src5 = m[mOffset + 5];
final float src9 = m[mOffset + 6];
final float src13 = m[mOffset + 7];
final float src2 = m[mOffset + 8];
final float src6 = m[mOffset + 9];
final float src10 = m[mOffset + 10];
final float src14 = m[mOffset + 11];
final float src3 = m[mOffset + 12];
final float src7 = m[mOffset + 13];
final float src11 = m[mOffset + 14];
final float src15 = m[mOffset + 15];
// calculate pairs for first 8 elements (cofactors)
final float atmp0 = src10 * src15;
final float atmp1 = src11 * src14;
final float atmp2 = src9 * src15;
final float atmp3 = src11 * src13;
final float atmp4 = src9 * src14;
final float atmp5 = src10 * src13;
final float atmp6 = src8 * src15;
final float atmp7 = src11 * src12;
final float atmp8 = src8 * src14;
final float atmp9 = src10 * src12;
final float atmp10 = src8 * src13;
final float atmp11 = src9 * src12;
// calculate first 8 elements (cofactors)
final float dst0 = (atmp0 * src5 + atmp3 * src6 + atmp4 * src7)
- (atmp1 * src5 + atmp2 * src6 + atmp5 * src7);
final float dst1 = (atmp1 * src4 + atmp6 * src6 + atmp9 * src7)
- (atmp0 * src4 + atmp7 * src6 + atmp8 * src7);
final float dst2 = (atmp2 * src4 + atmp7 * src5 + atmp10 * src7)
- (atmp3 * src4 + atmp6 * src5 + atmp11 * src7);
final float dst3 = (atmp5 * src4 + atmp8 * src5 + atmp11 * src6)
- (atmp4 * src4 + atmp9 * src5 + atmp10 * src6);
final float dst4 = (atmp1 * src1 + atmp2 * src2 + atmp5 * src3)
- (atmp0 * src1 + atmp3 * src2 + atmp4 * src3);
final float dst5 = (atmp0 * src0 + atmp7 * src2 + atmp8 * src3)
- (atmp1 * src0 + atmp6 * src2 + atmp9 * src3);
final float dst6 = (atmp3 * src0 + atmp6 * src1 + atmp11 * src3)
- (atmp2 * src0 + atmp7 * src1 + atmp10 * src3);
final float dst7 = (atmp4 * src0 + atmp9 * src1 + atmp10 * src2)
- (atmp5 * src0 + atmp8 * src1 + atmp11 * src2);
// calculate pairs for second 8 elements (cofactors)
final float btmp0 = src2 * src7;
final float btmp1 = src3 * src6;
final float btmp2 = src1 * src7;
final float btmp3 = src3 * src5;
final float btmp4 = src1 * src6;
final float btmp5 = src2 * src5;
final float btmp6 = src0 * src7;
final float btmp7 = src3 * src4;
final float btmp8 = src0 * src6;
final float btmp9 = src2 * src4;
final float btmp10 = src0 * src5;
final float btmp11 = src1 * src4;
// calculate second 8 elements (cofactors)
final float dst8 = (btmp0 * src13 + btmp3 * src14 + btmp4 * src15)
- (btmp1 * src13 + btmp2 * src14 + btmp5 * src15);
final float dst9 = (btmp1 * src12 + btmp6 * src14 + btmp9 * src15)
- (btmp0 * src12 + btmp7 * src14 + btmp8 * src15);
final float dst10 = (btmp2 * src12 + btmp7 * src13 + btmp10 * src15)
- (btmp3 * src12 + btmp6 * src13 + btmp11 * src15);
final float dst11 = (btmp5 * src12 + btmp8 * src13 + btmp11 * src14)
- (btmp4 * src12 + btmp9 * src13 + btmp10 * src14);
final float dst12 = (btmp2 * src10 + btmp5 * src11 + btmp1 * src9)
- (btmp4 * src11 + btmp0 * src9 + btmp3 * src10);
final float dst13 = (btmp8 * src11 + btmp0 * src8 + btmp7 * src10)
- (btmp6 * src10 + btmp9 * src11 + btmp1 * src8);
final float dst14 = (btmp6 * src9 + btmp11 * src11 + btmp3 * src8)
- (btmp10 * src11 + btmp2 * src8 + btmp7 * src9);
final float dst15 = (btmp10 * src10 + btmp4 * src8 + btmp9 * src9)
- (btmp8 * src9 + btmp11 * src10 + btmp5 * src8);
// calculate determinant
final float det =
src0 * dst0 + src1 * dst1 + src2 * dst2 + src3 * dst3;
if (det == 0.0f) {
return false;
}
// calculate matrix inverse
final float invdet = 1.0f / det;
mInv[mInvOffset] = dst0 * invdet;
mInv[1 + mInvOffset] = dst1 * invdet;
mInv[2 + mInvOffset] = dst2 * invdet;
mInv[3 + mInvOffset] = dst3 * invdet;
mInv[4 + mInvOffset] = dst4 * invdet;
mInv[5 + mInvOffset] = dst5 * invdet;
mInv[6 + mInvOffset] = dst6 * invdet;
mInv[7 + mInvOffset] = dst7 * invdet;
mInv[8 + mInvOffset] = dst8 * invdet;
mInv[9 + mInvOffset] = dst9 * invdet;
mInv[10 + mInvOffset] = dst10 * invdet;
mInv[11 + mInvOffset] = dst11 * invdet;
mInv[12 + mInvOffset] = dst12 * invdet;
mInv[13 + mInvOffset] = dst13 * invdet;
mInv[14 + mInvOffset] = dst14 * invdet;
mInv[15 + mInvOffset] = dst15 * invdet;
return true;
}
void setRotateM(float[] rm, int rmOffset, float a, float x, float y, float z)
{
rm[rmOffset + 3] = 0;
rm[rmOffset + 7] = 0;
rm[rmOffset + 11] = 0;
rm[rmOffset + 12] = 0;
rm[rmOffset + 13] = 0;
rm[rmOffset + 14] = 0;
rm[rmOffset + 15] = 1;
a *= (float) (Math.PI / 180.0f);
float s = (float) Math.sin(a);
float c = (float) Math.cos(a);
if (1.0f == x && 0.0f == y && 0.0f == z)
{
rm[rmOffset + 5] = c;
rm[rmOffset + 10] = c;
rm[rmOffset + 6] = s;
rm[rmOffset + 9] = -s;
rm[rmOffset + 1] = 0;
rm[rmOffset + 2] = 0;
rm[rmOffset + 4] = 0;
rm[rmOffset + 8] = 0;
rm[rmOffset + 0] = 1;
}
else if (0.0f == x && 1.0f == y && 0.0f == z)
{
rm[rmOffset + 0] = c;
rm[rmOffset + 10] = c;
rm[rmOffset + 8] = s;
rm[rmOffset + 2] = -s;
rm[rmOffset + 1] = 0;
rm[rmOffset + 4] = 0;
rm[rmOffset + 6] = 0;
rm[rmOffset + 9] = 0;
rm[rmOffset + 5] = 1;
}
else if (0.0f == x && 0.0f == y && 1.0f == z)
{
rm[rmOffset + 0] = c;
rm[rmOffset + 5] = c;
rm[rmOffset + 1] = s;
rm[rmOffset + 4] = -s;
rm[rmOffset + 2] = 0;
rm[rmOffset + 6] = 0;
rm[rmOffset + 8] = 0;
rm[rmOffset + 9] = 0;
rm[rmOffset + 10] = 1;
}
else
{
float len = (float) Math.sqrt(x * x + y * y + z * z);
if (1.0f != len)
{
float recipLen = 1.0f / len;
x *= recipLen;
y *= recipLen;
z *= recipLen;
}
float nc = 1.0f - c;
float xy = x * y;
float yz = y * z;
float zx = z * x;
float xs = x * s;
float ys = y * s;
float zs = z * s;
rm[rmOffset + 0] = x * x * nc + c;
rm[rmOffset + 4] = xy * nc - zs;
rm[rmOffset + 8] = zx * nc + ys;
rm[rmOffset + 1] = xy * nc + zs;
rm[rmOffset + 5] = y * y * nc + c;
rm[rmOffset + 9] = yz * nc - xs;
rm[rmOffset + 2] = zx * nc - ys;
rm[rmOffset + 6] = yz * nc + xs;
rm[rmOffset + 10] = z * z * nc + c;
}
}
}

View File

@@ -0,0 +1,155 @@
/*
* Copyright 2013 Hannes Janetzek
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.oscim.tiling.source;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import org.oscim.core.Tile;
import org.oscim.tiling.source.UrlTileDataSource;
import com.google.gwt.typedarrays.client.Uint8ArrayNative;
import com.google.gwt.typedarrays.shared.Uint8Array;
import com.google.gwt.xhr.client.ReadyStateChangeHandler;
import com.google.gwt.xhr.client.XMLHttpRequest;
import com.google.gwt.xhr.client.XMLHttpRequest.ResponseType;
public class LwHttp {
//static final Logger log = LoggerFactory.getLogger(LwHttp.class);
private final String mUrlPath;
private final byte[] mRequestBuffer;
private int mContentLength = -1;
private XMLHttpRequest mHttpRequest;
private ReadyStateChangeHandler mResponseHandler;
public LwHttp(URL url) {
mUrlPath = url.toString();
mRequestBuffer = new byte[1024];
}
static class Buffer extends InputStream {
Uint8Array mBuffer;
int mPos;
int mEnd;
public Buffer(Uint8Array buf) {
mBuffer = buf;
mPos = 0;
mEnd = buf.byteLength();
}
@Override
public synchronized int read() throws IOException {
if (mPos < mEnd)
return mBuffer.get(mPos++);
return -1;
}
}
public void close() {
if (mHttpRequest != null)
mHttpRequest.abort();
}
private UrlTileDataSource mDataSource;
public boolean sendRequest(Tile tile, UrlTileDataSource dataSource) throws IOException {
mDataSource = dataSource;
byte[] request = mRequestBuffer;
int pos = 0;
pos = dataSource.getTileSource().formatTilePath(tile, request, pos);
String url = mUrlPath + (new String(request, 0, pos));
mHttpRequest = XMLHttpRequest.create();
mHttpRequest.open("GET", url);
mHttpRequest.setResponseType(ResponseType.ArrayBuffer);
mResponseHandler = new ReadyStateChangeHandler() {
@Override
public void onReadyStateChange(XMLHttpRequest xhr) {
int state = xhr.getReadyState();
//log.debug(mCurrentUrl + "response " + status + "/" + state);
if (state == XMLHttpRequest.DONE) {
int status = xhr.getStatus();
if (status == 200) {
Uint8Array buf = Uint8ArrayNative.create(xhr.getResponseArrayBuffer());
mDataSource.process(new Buffer(buf));
} else {
mDataSource.process(null);
}
}
}
};
mHttpRequest.setOnReadyStateChange(mResponseHandler);
mHttpRequest.send();
return true;
}
// write (positive) integer to byte array
protected static int writeInt(int val, int pos, byte[] buf) {
if (val == 0) {
buf[pos] = '0';
return pos + 1;
}
int i = 0;
for (int n = val; n > 0; n = n / 10, i++)
buf[pos + i] = (byte) ('0' + n % 10);
// reverse bytes
for (int j = pos, end = pos + i - 1, mid = pos + i / 2; j < mid; j++, end--) {
byte tmp = buf[j];
buf[j] = buf[end];
buf[end] = tmp;
}
return pos + i;
}
// parse (positive) integer from byte array
protected static int parseInt(byte[] buf, int pos, int end) {
int val = 0;
for (; pos < end; pos++)
val = val * 10 + (buf[pos]) - '0';
return val;
}
public void requestCompleted() {
mHttpRequest.clearOnReadyStateChange();
mHttpRequest = null;
}
public int getContentLength() {
return mContentLength;
}
}

View File

@@ -0,0 +1,100 @@
/*
* Copyright 2012 Hannes Janetzek
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.oscim.tiling.source;
import static org.oscim.tiling.ITileDataSink.QueryResult.FAILED;
import static org.oscim.tiling.ITileDataSink.QueryResult.SUCCESS;
import java.io.IOException;
import java.io.InputStream;
import org.oscim.layers.tile.MapTile;
import org.oscim.layers.tile.TileLoader;
import org.oscim.tiling.ITileDataSink;
import org.oscim.tiling.ITileDataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class UrlTileDataSource implements ITileDataSource {
static final Logger log = LoggerFactory.getLogger(UrlTileDataSource.class);
protected final LwHttp mConn;
protected final ITileDecoder mTileDecoder;
protected final UrlTileSource mTileSource;
public UrlTileDataSource(UrlTileSource tileSource, ITileDecoder tileDecoder, LwHttp conn) {
mTileSource = tileSource;
mTileDecoder = tileDecoder;
mConn = conn;
}
UrlTileSource getTileSource() {
return mTileSource;
}
private ITileDataSink mSink;
private MapTile mTile;
@Override
public void query(MapTile tile, ITileDataSink sink) {
mTile = tile;
mSink = sink;
try {
mConn.sendRequest(tile, this);
} catch (Exception e) {
///e.printStackTrace();
log.error("{} {}", mTile, e.getMessage());
sink.completed(FAILED);
}
}
public void process(final InputStream is) {
TileLoader.postLoadDelay(new org.oscim.layers.tile.LoadDelayTask() {
@Override
public void continueLoading() {
if (!mTile.state(MapTile.State.LOADING)) {
mConn.requestCompleted();
mSink.completed(FAILED);
mTile = null;
mSink = null;
}
boolean win = false;
if (is != null) {
try {
win = mTileDecoder.decode(mTile, mSink, is);
} catch (IOException e) {
e.printStackTrace();
}
}
if (!win)
log.debug("{} failed", mTile);
mConn.requestCompleted();
mSink.completed(win ? SUCCESS : FAILED);
mTile = null;
mSink = null;
}
});
}
@Override
public void destroy() {
mConn.close();
}
}

View File

@@ -0,0 +1,109 @@
package org.oscim.tiling.source.bitmap;
import static org.oscim.tiling.ITileDataSink.QueryResult.FAILED;
import static org.oscim.tiling.ITileDataSink.QueryResult.SUCCESS;
import org.oscim.gdx.client.GwtBitmap;
import org.oscim.layers.tile.MapTile;
import org.oscim.layers.tile.TileLoader;
import org.oscim.tiling.ITileDataSink;
import org.oscim.tiling.ITileDataSource;
import org.oscim.tiling.source.LwHttp;
import org.oscim.tiling.source.UrlTileSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gwt.event.dom.client.ErrorEvent;
import com.google.gwt.event.dom.client.ErrorHandler;
import com.google.gwt.event.dom.client.LoadEvent;
import com.google.gwt.event.dom.client.LoadHandler;
import com.google.gwt.safehtml.shared.SafeUri;
import com.google.gwt.safehtml.shared.UriUtils;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.RootPanel;
public abstract class BitmapTileSource extends UrlTileSource {
static final Logger log = LoggerFactory.getLogger(LwHttp.class);
/**
* Create BitmapTileSource for 'url'
*
* By default path will be formatted as: url/z/x/y.png
* Use e.g. setExtension(".jpg") to overide ending or
* implement getUrlString() for custom formatting.
*/
public BitmapTileSource(String url, int zoomMin, int zoomMax) {
super(url, zoomMin, zoomMax);
setExtension(".png");
}
@Override
public ITileDataSource getDataSource() {
return new BitmapTileDataSource(this);
}
public static class BitmapTileDataSource implements ITileDataSource {
protected final UrlTileSource mTileSource;
private final byte[] mRequestBuffer = new byte[1024];
public BitmapTileDataSource(BitmapTileSource bitmapTileSource) {
mTileSource = bitmapTileSource;
}
@Override
public void query(final MapTile tile, final ITileDataSink sink) {
int pos = mTileSource.formatTilePath(tile, mRequestBuffer, 0);
String url = mTileSource.getUrl()
+ (new String(mRequestBuffer, 0, pos));
SafeUri uri = UriUtils.fromTrustedString(url);
final Image img = new Image();
img.setVisible(false);
/* As if researching CORS issues doesnt result in
* enough headache...
*
* Here are some more special Chrome/Webkit quirks:
* MUST SET CORS BEFORE URL! */
img.getElement().setAttribute("crossorigin", "anonymous");
img.setUrl(uri);
RootPanel.get().add(img);
img.addLoadHandler(new LoadHandler() {
public void onLoad(LoadEvent event) {
TileLoader.postLoadDelay(new org.oscim.layers.tile.LoadDelayTask() {
@Override
public void continueLoading() {
if (!tile.state(MapTile.State.LOADING)) {
sink.completed(FAILED);
RootPanel.get().remove(img);
} else {
sink.setTileImage(new GwtBitmap(img));
sink.completed(SUCCESS);
}
}
});
}
});
img.addErrorHandler(new ErrorHandler() {
@Override
public void onError(ErrorEvent event) {
sink.completed(FAILED);
RootPanel.get().remove(img);
}
});
}
@Override
public void destroy() {
}
}
}

View File

@@ -0,0 +1,58 @@
/*
* Copyright 2010, 2011, 2012 mapsforge.org
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.oscim.utils;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.logging.Level;
/**
* A utility class with IO-specific helper methods.
*/
public final class IOUtils {
/**
* Invokes the {@link Closeable#close()} method on the given object. If an
* {@link IOException} occurs during the
* method call, it will be caught and logged on level {@link Level#WARNING}.
*
* @param closeable
* the data source which should be closed (may be null).
*/
public static void closeQuietly(OutputStream closeable) {
try {
if (closeable != null) {
closeable.close();
}
} catch (IOException e) {
//log.debug(e.getMessage() + " " + e);
}
}
public static void closeQuietly(InputStream closeable) {
try {
if (closeable != null) {
closeable.close();
}
} catch (IOException e) {
//log.debug(e.getMessage() + " " + e);
}
}
private IOUtils() {
}
}

View File

@@ -0,0 +1,200 @@
package org.oscim.utils;
import org.oscim.core.GeometryBuffer;
import org.oscim.renderer.elements.VertexItem;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gwt.core.client.JavaScriptException;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JsArrayInteger;
import com.google.gwt.core.client.JsArrayNumber;
import com.google.gwt.core.client.JsArrayUtils;
import com.google.gwt.typedarrays.shared.Float32Array;
import com.google.gwt.typedarrays.shared.Int32Array;
public class Tessellator {
static final Logger log = LoggerFactory.getLogger(Tessellator.class);
public static int tessellate(GeometryBuffer geom, float scale,
VertexItem outPoints, VertexItem outTris, int vertexOffset) {
int numIndices = 0;
int indexPos = 0;
int pointPos = 0;
int indexEnd = geom.index.length;
JsArrayNumber jspoints = JsArrayUtils.readOnlyJsArray(geom.points);
JsArrayInteger jsindex = JsArrayUtils.readOnlyJsArray(geom.index);
for (int idx = 0; idx < indexEnd && geom.index[idx] > 0; idx++) {
indexPos = idx;
int numRings = 1;
int numPoints = geom.index[idx++];
for (; idx < indexEnd && geom.index[idx] > 0; idx++) {
numRings++;
numPoints += geom.index[idx];
}
if (numPoints <= 0 && numRings == 1){
log.debug("tessellation skip empty");
pointPos += numPoints;
continue;
}
TessResult res;
try {
res = tessellate2(jspoints, pointPos, numPoints,
jsindex, indexPos, numRings);
} catch (JavaScriptException e) {
e.printStackTrace();
return 0;
}
pointPos += numPoints;
if (res == null) {
log.debug("tessellation failed");
continue;
}
Int32Array io = res.getIndices(res);
int resIndices = io.length();
numIndices += resIndices;
for (int k = 0, cnt = 0; k < resIndices; k += cnt) {
if (outTris.used == VertexItem.SIZE) {
outTris.next = VertexItem.pool.get();
outTris = outTris.next;
}
cnt = VertexItem.SIZE - outTris.used;
if (k + cnt > resIndices)
cnt = resIndices - k;
for (int i = 0; i < cnt; i++)
outTris.vertices[outTris.used + i] =
(short) (vertexOffset + io.get(k + i));
outTris.used += cnt;
}
Float32Array po = res.getPoints(res);
int resPoints = po.length();
vertexOffset += (resPoints >> 1);
for (int k = 0, cnt = 0; k < resPoints; k += cnt) {
if (outPoints.used == VertexItem.SIZE) {
outPoints.next = VertexItem.pool.get();
outPoints = outPoints.next;
}
cnt = VertexItem.SIZE - outPoints.used;
if (k + cnt > resPoints)
cnt = resPoints - k;
for (int i = 0; i < cnt; i++)
outPoints.vertices[outPoints.used + i] =
(short) (po.get(k + i) * scale);
outPoints.used += cnt;
}
if (idx >= indexEnd || geom.index[idx] < 0)
break;
}
return numIndices;
}
public static int tessellate(float[] points, int ppos, int plen, short[] index,
int ipos, int rings, int vertexOffset, VertexItem outTris) {
Int32Array io;
try {
io = tessellate(JsArrayUtils.readOnlyJsArray(points), ppos, plen,
JsArrayUtils.readOnlyJsArray(index), ipos, rings);
} catch (JavaScriptException e) {
e.printStackTrace();
return 0;
}
if (io == null) {
//log.debug("building tessellation failed");
return 0;
}
// if (vo.length() != plen) {
// // TODO handle different output points
// log.debug(" + io.length());
//
// //for (int i = 0; i < vo.length(); i += 2)
// // log.debug(vo.get(i) + " " + vo.get(i + 1));
// //for (int i = ppos; i < ppos + plen; i += 2)
// // log.debug( points[i]+ " " + points[i + 1]);
//
// return 0;
// }
int numIndices = io.length();
for (int k = 0, cnt = 0; k < numIndices; k += cnt) {
if (outTris.used == VertexItem.SIZE) {
outTris.next = VertexItem.pool.get();
outTris = outTris.next;
}
cnt = VertexItem.SIZE - outTris.used;
if (k + cnt > numIndices)
cnt = numIndices - k;
for (int i = 0; i < cnt; i++) {
int idx = (vertexOffset + io.get(k + i));
outTris.vertices[outTris.used + i] = (short) idx;
}
outTris.used += cnt;
}
return numIndices;
}
public static int tessellate(GeometryBuffer geom, GeometryBuffer out) {
return 0;
}
static native Int32Array tessellate(JsArrayNumber points, int pOffset, int pLength,
JsArrayInteger bounds, int bOffset, int bLength)/*-{
return $wnd.tessellate(points, pOffset, pOffset + pLength, bounds,
bOffset, bOffset + bLength, false);
}-*/;
static native TessResult tessellate2(JsArrayNumber points, int pOffset, int pLength,
JsArrayInteger bounds, int bOffset, int bLength)
/*-{
return $wnd.tessellate(points, pOffset, pOffset + pLength, bounds,
bOffset, bOffset + bLength, true);
}-*/;
static final class TessResult extends JavaScriptObject {
protected TessResult() {
}
native Float32Array getPoints(JavaScriptObject result)/*-{
return result.vertices;
}-*/;
native Int32Array getIndices(JavaScriptObject result)/*-{
return result.triangles;
}-*/;
}
}

View File

@@ -0,0 +1,68 @@
package org.oscim.utils.async;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.utils.Disposable;
/**
* GWT emulation of AsynchExecutor, will call tasks immediately :D
*
* @author badlogic
*
*/
public class AsyncExecutor implements Disposable {
/**
* Creates a new AsynchExecutor that allows maxConcurrent {@link Runnable}
* instances to run in parallel.
*
* @param maxConcurrent
*/
public AsyncExecutor(int maxConcurrent) {
}
// FIXME TODO add wrap into 'FakeFuture' and run via Gdx.app.post()
/**
* Submits a {@link Runnable} to be executed asynchronously. If
* maxConcurrent runnables are already running, the runnable
* will be queued.
*
* @param task the task to execute asynchronously
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public <T> AsyncResult<T> submit(final AsyncTask<T> task) {
T result = null;
boolean error = false;
try {
task.run();
result = task.getResult();
} catch (Throwable t) {
error = true;
}
if (error)
return null;
return new AsyncResult(result);
}
/**
* Submits a {@link Runnable} to be executed asynchronously. If
* maxConcurrent runnables are already running, the runnable
* will be queued.
*
* @param task the task to execute asynchronously
*/
public boolean post(Runnable task) {
Gdx.app.postRunnable(task);
return true;
}
/**
* Waits for running {@link AsyncTask} instances to finish,
* then destroys any resources like threads. Can not be used
* after this method is called.
*/
@Override
public void dispose() {
}
}

View File

@@ -0,0 +1,50 @@
/*******************************************************************************
* Copyright 2013 See libgdx AUTHORS file.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package org.oscim.utils.async;
//import java.util.concurrent.ExecutionException;
//import java.util.concurrent.Future;
/**
* Returned by {@link AsyncExecutor#submit(AsyncTask)}, allows to poll
* for the result of the asynch workload.
*
* @author badlogic
*
*/
public class AsyncResult<T> {
private final T result;
AsyncResult(T result) {
this.result = result;
}
/**
* @return whether the {@link AsyncTask} is done
*/
public boolean isDone() {
return true;
}
/**
* @return the result, or null if there was an error, no result, or the task
* is still running
*/
public T get() {
return result;
}
}

View File

@@ -0,0 +1,30 @@
/*******************************************************************************
* Copyright 2013 See libgdx AUTHORS file.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package org.oscim.utils.async;
/**
* Task to be submitted to an {@link AsyncExecutor}, returning a result of type
* T.
*
* @author badlogic
*
*/
public interface AsyncTask<T> extends Runnable {
public boolean cancel();
public T getResult() throws Exception;
}

View File

@@ -0,0 +1,28 @@
/*******************************************************************************
* Copyright 2013 See libgdx AUTHORS file.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package org.oscim.utils.async;
/**
* GWT emulation of ThreadUtils, does nothing.
*
* @author badlogic
*
*/
public class ThreadUtils {
public static void yield() {
}
}

View File

@@ -0,0 +1,27 @@
package org.xml.sax;
public abstract interface Attributes {
public abstract int getLength();
public abstract String getURI(int paramInt);
public abstract String getLocalName(int paramInt);
public abstract String getQName(int paramInt);
public abstract String getType(int paramInt);
public abstract String getValue(int paramInt);
public abstract int getIndex(String paramString1, String paramString2);
public abstract int getIndex(String paramString);
public abstract String getType(String paramString1, String paramString2);
public abstract String getType(String paramString);
public abstract String getValue(String paramString1, String paramString2);
public abstract String getValue(String paramString);
}

View File

@@ -0,0 +1,20 @@
package org.xml.sax;
import java.io.IOException;
public class SAXException extends IOException {
/**
*
*/
private static final long serialVersionUID = 1L;
public SAXException(String str) {
super(str);
}
public SAXException(String str, Throwable throwable)
{
super(str);
}
}

View File

@@ -0,0 +1,19 @@
package org.xml.sax;
public class SAXParseException extends SAXException {
/**
*
*/
private static final long serialVersionUID = 1L;
public SAXParseException(String str) {
super(str);
}
public SAXParseException(String str, Throwable throwable)
{
super(str);
}
}

View File

@@ -0,0 +1,29 @@
package org.xml.sax.helpers;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
public class DefaultHandler {
public void endDocument() {
}
public void error(SAXParseException exception) {
}
public void warning(SAXParseException exception) {
}
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
}
public void endElement(String uri, String localName, String qName) {
}
}