/*
* 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;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.sf.jame.contextfree.figure.FigureRuntimeElement;
import net.sf.jame.contextfree.renderer.support.CFBuilder;
import net.sf.jame.contextfree.renderer.support.CFColor;
import net.sf.jame.contextfree.renderer.support.CFContext;
import net.sf.jame.contextfree.renderer.support.CFModification;
import net.sf.jame.contextfree.renderer.support.CFRenderer;
import net.sf.jame.contextfree.renderer.support.CFShape;
import net.sf.jame.core.util.Color32bit;
/**
* @author Andrea Medeghini
*/
public class DefaultContextFreeRenderer extends AbstractContextFreeRenderer {
private static final Logger logger = Logger.getLogger(DefaultContextFreeRenderer.class.getName());
/**
*
*/
public DefaultContextFreeRenderer(final int threadPriority) {
super(threadPriority);
}
@Override
protected void doRender(boolean dynamicZoom) {
long totalTime = System.nanoTime();
long time = totalTime;
float border = 10f;
updateTransform();
float offsetX = (getBufferWidth() - getTile().getImageSize().getX()) / 2;
float offsetY = (getBufferHeight() - getTile().getImageSize().getY()) / 2;
int width = getTile().getImageSize().getX();
int height = getTile().getImageSize().getY();
Color32bit background = cfdgRuntime.getBackground();
String startshape = cfdgRuntime.getStartshape();
String variation = cfdgRuntime.getVariation();
CFContext context = new CFContext();
AffineTransform tileTransform = new AffineTransform();
if (cfdgRuntime.isUseTile() || cfdgRuntime.isUseSize()) {
tileTransform.translate(cfdgRuntime.getX(), cfdgRuntime.getY());
tileTransform.scale(cfdgRuntime.getWidth(), cfdgRuntime.getHeight());
context.setTiled(tileTransform, cfdgRuntime.getTileWidth(), cfdgRuntime.getTileHeight(), cfdgRuntime.isUseTile(), cfdgRuntime.isUseSize());
}
CFBuilder builder = new CFBuilder(context);
for (int i = 0; i < cfdgRuntime.getFigureElementCount(); i++) {
FigureRuntimeElement figure = cfdgRuntime.getFigureElement(i);
figure.process(builder);
}
context.reloadRules();
int initialShapeType = context.encodeShapeName(startshape);
CFRenderer renderer = new CFRenderer(context, variation.hashCode(), width, height, border, 0.03f);
CFModification worldState = new CFModification();
boolean partialDraw = true;
int reportAt = 10000;
CFShape shape = new CFShape(initialShapeType, worldState);
shape.getModification().getColorTarget().setAlpha(1);
shape.getModification().getColor().setAlpha(1);
context.setBackground(new CFColor(background.getARGB()));
renderer.processShape(shape);
if (logger.isLoggable(Level.FINE)) {
long elapsed = (System.nanoTime() - time) / 1000000;
logger.fine("Build time " + elapsed + "ms");
}
percent = 20;
for (;;) {
if (isInterrupted()) {
break;
}
if (renderer.getUnfinishedCount() == 0) {
break;
}
if ((renderer.getFinishedCount() + renderer.getUnfinishedCount()) > CFRenderer.MAX_SHAPES) {
break;
}
CFShape s = renderer.nextUnfinishedShape();
renderer.executeShape(s);
if (renderer.getFinishedCount() > reportAt) {
if (partialDraw) {
render(renderer, offsetX, offsetY, true);
}
reportAt = 2 * renderer.getFinishedCount();
}
}
renderer.sortShapes();
percent = 70;
if (logger.isLoggable(Level.FINE)) {
logger.fine("Total shapes " + renderer.getFinishedCount());
}
time = System.nanoTime();
render(renderer, offsetX, offsetY, false);
if (logger.isLoggable(Level.FINE)) {
long elapsed = (System.nanoTime() - time) / 1000000;
logger.fine("Render time " + elapsed + "ms");
}
percent = 100;
if (logger.isLoggable(Level.FINE)) {
logger.fine("Total time " + (System.nanoTime() - totalTime) / 1000000 + "ms");
}
}
private void render(CFRenderer renderer, float offsetX, float offsetY, boolean partial) {
Graphics2D g2d = getGraphics();
configure(g2d);
AffineTransform tmpTransform = g2d.getTransform();
g2d.translate(offsetX, offsetY);
renderer.render(g2d, partial);
g2d.setTransform(tmpTransform);
swapImages();
}
protected void configure(Graphics2D g2d) {
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_SPEED);
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
}
}