/** * Copyright 2011 The ForPlay Authors * * 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 forplay.html; import static com.google.gwt.webgl.client.WebGLRenderingContext.COLOR_BUFFER_BIT; import com.google.gwt.webgl.client.WebGLFramebuffer; import com.google.gwt.webgl.client.WebGLTexture; import forplay.core.Asserts; import forplay.core.Image; import forplay.core.Pattern; import forplay.core.Surface; import forplay.core.Transform; import java.util.ArrayList; import java.util.List; class HtmlSurfaceGL implements Surface { private final HtmlGraphicsGL gfx; private final WebGLFramebuffer fbuf; private final int width; private final int height; private final List<Transform> transformStack = new ArrayList<Transform>(); private int fillColor; private HtmlPattern fillPattern; HtmlSurfaceGL(HtmlGraphicsGL gfx, WebGLFramebuffer fbuf, int width, int height) { this.gfx = gfx; this.fbuf = fbuf; this.width = width; this.height = height; transformStack.add(new Transform(Transform.IDENTITY)); } @Override public void clear() { gfx.bindFramebuffer(fbuf, width, height); gfx.gl.clearColor(0, 0, 0, 0); gfx.gl.clear(COLOR_BUFFER_BIT); } @Override public void drawImage(Image image, float x, float y) { drawImage(image, x, y, image.width(), image.height()); } @Override public void drawImage(Image image, float x, float y, float dw, float dh) { gfx.bindFramebuffer(fbuf, width, height); Asserts.checkArgument(image instanceof HtmlImage); HtmlImage himage = (HtmlImage) image; if (himage.isReady()) { WebGLTexture tex = himage.ensureTexture(gfx, false, false); if (tex != null) { gfx.drawTexture(tex, image.width(), image.height(), topTransform(), x, y, dw, dh, false, false, 1); } } } @Override public void drawImage(Image image, float dx, float dy, float dw, float dh, float sx, float sy, float sw, float sh) { gfx.bindFramebuffer(fbuf, width, height); Asserts.checkArgument(image instanceof HtmlImage); HtmlImage himage = (HtmlImage) image; if (himage.isReady()) { WebGLTexture tex = himage.ensureTexture(gfx, false, false); if (tex != null) { gfx.drawTexture(tex, image.width(), image.height(), topTransform(), dx, dy, dw, dh, sx, sy, sw, sh, 1); } } } public void drawImageCentered(Image img, float x, float y) { drawImage(img, x - img.width()/2, y - img.height()/2); } @Override public void drawLine(float x0, float y0, float x1, float y1, float width) { gfx.bindFramebuffer(fbuf, this.width, this.height); float dx = x1 - x0, dy = y1 - y0; float len = (float) Math.sqrt(dx * dx + dy * dy); dx = dx * (width / 2) / len; dy = dy * (width / 2) / len; float[] pos = new float[8]; pos[0] = x0 - dy; pos[1] = y0 + dx; pos[2] = x1 - dy; pos[3] = y1 + dx; pos[4] = x1 + dy; pos[5] = y1 - dx; pos[6] = x0 + dy; pos[7] = y0 - dx; gfx.fillPoly(topTransform(), pos, fillColor, 1); } @Override public void fillRect(float x, float y, float width, float height) { gfx.bindFramebuffer(fbuf, this.width, this.height); if (fillPattern != null) { HtmlImage image = fillPattern.image; WebGLTexture tex = image.ensureTexture(gfx, true, true); gfx.fillRect(topTransform(), x, y, width, height, image.width(), image.height(), tex, 1); } else { gfx.fillRect(topTransform(), x, y, width, height, fillColor, 1); } } @Override public int height() { return height; } @Override public void restore() { Asserts.checkState(transformStack.size() > 1, "Unbalanced save/restore"); transformStack.remove(transformStack.size() - 1); } @Override public void rotate(float angle) { float sr = (float) Math.sin(angle); float cr = (float) Math.cos(angle); transform(cr, sr, -sr, cr, 0, 0); } @Override public void save() { transformStack.add(new Transform(topTransform())); } @Override public void scale(float sx, float sy) { topTransform().scale(sx, sy); } @Override public void setTransform(float m00, float m01, float m10, float m11, float tx, float ty) { topTransform().set(m00, m01, m10, m11, tx, ty); } public void setFillColor(int color) { // TODO: Add it to the state stack. this.fillColor = color; this.fillPattern = null; } @Override public void setFillPattern(Pattern pattern) { // TODO: Add it to the state stack. Asserts.checkArgument(pattern instanceof HtmlPattern); this.fillPattern = (HtmlPattern) pattern; } @Override public void transform(float m00, float m01, float m10, float m11, float tx, float ty) { topTransform().transform(m00, m01, m10, m11, tx, ty); } @Override public void translate(float x, float y) { topTransform().translate(x, y); } @Override public int width() { return width; } private Transform topTransform() { return transformStack.get(transformStack.size() - 1); } }