/* * JAME 6.2.1 * http://jame.sourceforge.net * * Copyright 2001, 2016 Andrea Medeghini * * This file is part of JAME. * * JAME is an application for creating fractals and other graphics artifacts. * * JAME is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * JAME 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with JAME. If not, see <http://www.gnu.org/licenses/>. * */ package net.sf.jame.contextfree.renderer.support; import java.awt.Color; import java.awt.Composite; import java.awt.Graphics2D; import java.awt.Shape; import java.awt.geom.AffineTransform; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.util.ArrayList; import java.util.List; public class TiledShapeRenderer implements CFShapeRenderer { private List<Point2D.Double> tiles = new ArrayList<Point2D.Double>(); private Graphics2D g2d; private Rectangle2D.Double canvas; private AffineTransform scale; private AffineTransform tess; private CFContext context; private Point2D.Double ptSrc = new Point2D.Double(0, 0); private Point2D.Double ptDst = new Point2D.Double(0, 0); public TiledShapeRenderer(Graphics2D g2d, CFContext context) { this.g2d = g2d; this.context = context; tess = AffineTransform.getScaleInstance(context.getTileX(), context.getTileY()); scale = AffineTransform.getScaleInstance(1 / context.getTileX(), 1 / context.getTileY()); canvas = new Rectangle2D.Double(-0.5 * context.getSizeX(), -0.5 * context.getSizeY(), context.getSizeX(), context.getSizeY()); } private void transform(Rectangle2D bounds, double px, double py) { tiles.clear(); tiles.add(new Point2D.Double(px, py)); // System.out.println("[] " + bounds); if (context.isTiled()) { if (px + bounds.getMinX() > canvas.getMinX() && py + bounds.getMinY() > canvas.getMinY() && px + bounds.getMaxX() < canvas.getMaxX() && py + bounds.getMaxY() < canvas.getMaxY()) { return; } for (int ring = 1; ; ring++) { boolean hit = false; for (int y = -ring; y <= ring; y++) { for (int x = -ring; x <= ring; x++) { if (Math.abs(x) < ring && Math.abs(y) < ring) continue; ptSrc.setLocation(x, y); tess.transform(ptSrc, ptDst); Rectangle2D.Double tile = new Rectangle2D.Double(ptDst.getX() + bounds.getMinX() + px, ptDst.getY() + bounds.getMinY() + py, bounds.getWidth(), bounds.getHeight()); if (tile.intersects(canvas)) { // System.out.println(" " + canvas + " <> " + tile); Point2D.Double point = new Point2D.Double(ptDst.getX() + px, ptDst.getY() + py); tiles.add(point); hit = true; } } } if (!hit) break; } } } public void render(CFPath path, CFPathAttribute attribute) { AffineTransform tmpTransform = g2d.getTransform(); Composite tmpComposite = g2d.getComposite(); Color tmpColor = g2d.getColor(); Shape tmpClip = g2d.getClip(); double mx = context.getOffsetX() - Math.floor(context.getOffsetX() / context.getSizeX()) * context.getSizeX(); double my = context.getOffsetY() - Math.floor(context.getOffsetY() / context.getSizeY()) * context.getSizeY(); AffineTransform t = attribute.getModification().getTransform(); double tx = mx * scale.getScaleX(); double ty = my * scale.getScaleY(); double px = tx - Math.floor(tx); double py = ty - Math.floor(ty); if (px < 0) px += 1; if (py < 0) py += 1; px = px / scale.getScaleX(); py = py / scale.getScaleY(); transform(path.getBounds(t, 1), px, py); // if (context.isTiled()) { g2d.setClip(canvas); // } for (Point2D.Double point : tiles) { // System.out.println(point); path.render(g2d, attribute, point); } g2d.setTransform(tmpTransform); g2d.setComposite(tmpComposite); g2d.setColor(tmpColor); g2d.setClip(tmpClip); } }