/* * Copyright (c) 2014 tabletoptool.com team. * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Public License v3.0 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/gpl.html * * Contributors: * rptools.com team - initial implementation * tabletoptool.com team - further development */ package com.t3.client.ui.zone; import java.awt.AlphaComposite; import java.awt.Color; import java.awt.Composite; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.RenderingHints; import java.awt.Transparency; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; import java.util.List; import com.t3.model.drawing.Drawable; import com.t3.model.drawing.DrawnElement; import com.t3.model.drawing.Pen; /** */ public class BackBufferDrawableRenderer implements DrawableRenderer { private BufferedImage backBuffer; private Rectangle lastViewport; private double lastScale; private int lastDrawableListSize; @Override public void flush() { backBuffer = null; lastViewport = null; } @Override public void renderDrawables(Graphics g, List<DrawnElement> drawableList, Rectangle viewport, double scale) { // NOTHING TO DO if (drawableList == null || drawableList.size() == 0) { flush(); return; } boolean newBackbuffer = false; // CREATE BACKBUFFER if (backBuffer == null || (lastViewport == null || (lastViewport.width != viewport.width || lastViewport.height != viewport.height))) { backBuffer = new BufferedImage(viewport.width, viewport.height, Transparency.TRANSLUCENT); newBackbuffer = true; } // SCENERY CHANGE if (newBackbuffer || lastDrawableListSize != drawableList.size() || lastViewport.x != viewport.x || lastViewport.y != viewport.y || lastScale != scale) { if (!newBackbuffer) { clearBackbuffer(); } drawDrawables(drawableList, viewport, scale); } // RENDER g.drawImage(backBuffer, 0, 0, null); // REMEMBER lastViewport = viewport; lastScale = scale; lastDrawableListSize = drawableList.size(); } private void clearBackbuffer() { Graphics2D g2d = backBuffer.createGraphics(); g2d.setBackground(new Color(0, 0, 0, 0) ); g2d.clearRect(0, 0, backBuffer.getWidth(), backBuffer.getHeight()); g2d.dispose(); } private void drawDrawables(List<DrawnElement> drawableList, Rectangle viewport, double scale) { Graphics2D g = backBuffer.createGraphics(); g.setClip(0, 0, backBuffer.getWidth(), backBuffer.getHeight()); g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); AffineTransform af = new AffineTransform(); af.scale(scale, scale); af.translate(viewport.x/scale, viewport.y/scale); g.setTransform(af); Composite oldComposite = g.getComposite(); for (DrawnElement element : drawableList) { Drawable drawable = element.getDrawable(); // if (!drawable.getBounds().intersects(viewport)) { // // Not onscreen // continue; // } Pen pen = element.getPen(); if (pen.getOpacity() != 1 && pen.getOpacity() != 0 /* handle legacy pens, besides, it doesn't make sense to have a non visible pen*/) { g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, pen.getOpacity())); } drawable.draw(g, pen); g.setComposite(oldComposite); } g.dispose(); } }