All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.geomajas.gwt2.client.gfx.CanvasContainerImpl Maven / Gradle / Ivy

/*
 * This is part of Geomajas, a GIS framework, http://www.geomajas.org/.
 *
 * Copyright 2008-2015 Geosparc nv, http://www.geosparc.com/, Belgium.
 *
 * The program is available in open source according to the GNU Affero
 * General Public License. All contributions in this program are covered
 * by the Geomajas Contributors License Agreement. For full licensing
 * details, see LICENSE.txt in the project root.
 */
package org.geomajas.gwt2.client.gfx;

import java.util.ArrayList;
import java.util.List;

import org.geomajas.geometry.Bbox;
import org.geomajas.geometry.Matrix;
import org.geomajas.geometry.service.BboxService;

import com.google.gwt.canvas.client.Canvas;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.Widget;

/**
 * Default implementation of {@link CanvasContainer}.
 * 
 * @author Jan De Moerloose
 * 
 */
public class CanvasContainerImpl implements CanvasContainer {

	/** off-screen buffer to improve rendering performance **/
	private Canvas buffer;

	/** buffer world bounds **/
	private Bbox bufferBounds;

	/** actual canvas **/
	private Canvas canvas;

	/** canvas world bounds **/
	private Bbox canvasBounds;

	private List shapes = new ArrayList();

	private Matrix matrix;

	private double bufferFactor = 3.0;

	public CanvasContainerImpl(int width, int height) {
		matrix = new Matrix(1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
		// create a canvas
		canvas = Canvas.createIfSupported();
		if (canvas != null) {
			// create an off-screen buffer with bufferFactor x the size
			buffer = Canvas.createIfSupported();
			buffer.setVisible(false);
			RootPanel.get().add(buffer);
			setPixelSize(width, height);
		} else {
			throw new RuntimeException("canvas unsupported");
		}
	}

	@Override
	public void setTranslation(double deltaX, double deltaY) {
		matrix = new Matrix(matrix.getXx(), 0.0, 0.0, matrix.getYy(), deltaX, deltaY);
		updateTransform();
		if (!BboxService.contains(bufferBounds, canvasBounds)) {
			repaintBuffer();
		}
		copyBufferToCanvas();
	}

	@Override
	public void setScale(double scaleX, double scaleY) {
		matrix = new Matrix(scaleX, 0.0, 0.0, scaleY, matrix.getDx(), matrix.getDy());
		updateTransform();
		repaint();
	}
	
	public void setBufferFactor(double bufferFactor) {
		this.bufferFactor = bufferFactor;
	}

	private void updateTransform() {
		canvasBounds = toWorld(new Bbox(0, 0, canvas.getCoordinateSpaceWidth(), canvas.getCoordinateSpaceHeight()));
	}

	private void copyBufferToCanvas() {
		clearCanvas(canvas);
		double dx = (bufferBounds.getX() - canvasBounds.getX()) * matrix.getXx();
		double dy = -(bufferFactor - 1) * canvas.getCoordinateSpaceHeight()
				+ (bufferBounds.getY() - canvasBounds.getY()) * matrix.getYy();
		canvas.getContext2d().drawImage(buffer.getCanvasElement(), dx, dy);
	}

	@Override
	public void setFixedSize(boolean fixedSize) {
	}

	@Override
	public boolean isFixedSize() {
		return false;
	}

	@Override
	public Widget asWidget() {
		return canvas;
	}

	@Override
	public void addShape(CanvasShape shape) {
		shapes.add(shape);
		repaint();
	}

	@Override
	public void addAll(List all) {
		shapes.addAll(all);
		repaint();
	}

	@Override
	public void removeShape(CanvasShape shape) {
		shapes.remove(shape);
		repaint();
	}

	@Override
	public void clear() {
		shapes.clear();
		repaint();
	}

	@Override
	public void repaint() {
		repaintBuffer();
		copyBufferToCanvas();
	}

	@Override
	public void setOpacity(double opacity) {
		canvas.getContext2d().setGlobalAlpha(opacity);
		copyBufferToCanvas();
	}

	@Override
	public void setPixelSize(int width, int height) {
		canvas.setWidth(width + "px");
		canvas.setCoordinateSpaceWidth(width);
		canvas.setHeight(height + "px");
		canvas.setCoordinateSpaceHeight(height);
		buffer.setWidth(bufferFactor * width + "px");
		buffer.setCoordinateSpaceWidth((int) (bufferFactor * width));
		buffer.setHeight(bufferFactor * height + "px");
		buffer.setCoordinateSpaceHeight((int) (bufferFactor * height));
		repaintBuffer();
	}

	protected void repaintBuffer() {
		clearCanvas(buffer);
		double bufferDx = matrix.getDx() + (bufferFactor - 1) * 0.5 * canvas.getCoordinateSpaceWidth();
		double bufferDy = matrix.getDy() + (bufferFactor - 1) * 0.5 * canvas.getCoordinateSpaceHeight();
		Matrix bufferMatrix = new Matrix(matrix.getXx(), 0, 0, matrix.getYy(), bufferDx, bufferDy);
		buffer.getContext2d().setTransform(matrix.getXx(), 0, 0, matrix.getYy(), bufferDx, bufferDy);
		double width = canvas.getCoordinateSpaceWidth();
		double height = canvas.getCoordinateSpaceHeight();
		bufferBounds = toWorld(new Bbox(-0.5 * (bufferFactor - 1) * width, -0.5 * (bufferFactor - 1) * height,
				bufferFactor * width, bufferFactor * height));
		for (CanvasShape shape : shapes) {
			shape.paint(buffer, bufferMatrix);
		}
	}

	private Bbox toWorld(Bbox bbox) {
		double x1 = (bbox.getX() - matrix.getDx()) / matrix.getXx();
		double y1 = (bbox.getY() - matrix.getDy()) / matrix.getYy();
		double x2 = (bbox.getMaxX() - matrix.getDx()) / matrix.getXx();
		double y2 = (bbox.getMaxY() - matrix.getDy()) / matrix.getYy();
		double x = Math.min(x1, x2);
		double y = Math.min(y1, y2);
		return new Bbox(x, y, Math.abs(x1 - x2), Math.abs(y1 - y2));
	}

	private void clearCanvas(Canvas canvas) {
		canvas.getContext2d().save();
		canvas.getContext2d().setTransform(1, 0, 0, 1, 0, 0);
		canvas.getContext2d().clearRect(0, 0, canvas.getCoordinateSpaceWidth(), canvas.getCoordinateSpaceHeight());
		canvas.getContext2d().restore();
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy