package org.oscim.tiling.source.bitmap; import org.oscim.gdx.client.GwtBitmap; import org.oscim.layers.tile.LoadDelayTask; import org.oscim.layers.tile.MapTile; import org.oscim.layers.tile.TileLoader; import org.oscim.tiling.ITileDataSink; import org.oscim.tiling.ITileDataSink.QueryResult; 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 class BitmapTileSource extends UrlTileSource { static final Logger log = LoggerFactory.getLogger(LwHttp.class); public static class Builder<T extends Builder<T>> extends UrlTileSource.Builder<T> { public Builder() { super(null, "/{Z}/{X}/{Y}.png", 0, 17); } public BitmapTileSource build() { return new BitmapTileSource(this); } } protected BitmapTileSource(Builder<?> builder) { super(builder); } @SuppressWarnings("rawtypes") public static Builder<?> builder() { return new Builder(); } /** * 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, "/{Z}/{X}/{Y}.png", zoomMin, zoomMax); } public BitmapTileSource(String url, int zoomMin, int zoomMax, String extension) { super(url, "/{Z}/{X}/{Y}" + extension, zoomMin, zoomMax); } public BitmapTileSource(String url, String tilePath, int zoomMin, int zoomMax) { super(url, tilePath, zoomMin, zoomMax); } @Override public ITileDataSource getDataSource() { return new BitmapTileDataSource(this); } public class BitmapTileDataSource implements ITileDataSource { protected final UrlTileSource mTileSource; public BitmapTileDataSource(BitmapTileSource bitmapTileSource) { mTileSource = bitmapTileSource; } @Override public void query(final MapTile tile, final ITileDataSink sink) { String url = mTileSource.getTileUrl(tile); 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 LoadDelayTask<Image>(tile, sink, img) { @Override public void continueLoading() { if (!tile.state(MapTile.State.LOADING)) { sink.completed(QueryResult.FAILED); RootPanel.get().remove(data); } else { sink.setTileImage(new GwtBitmap(data)); sink.completed(QueryResult.SUCCESS); } } }); } }); img.addErrorHandler(new ErrorHandler() { @Override public void onError(ErrorEvent event) { sink.completed(QueryResult.FAILED); RootPanel.get().remove(img); } }); } @Override public void dispose() { } @Override public void cancel() { } } }