Skip to content
Snippets Groups Projects
Commit 2fe06c98 authored by Georg Graßnick's avatar Georg Graßnick :thinking:
Browse files

Merge branch 'feat/boolMat_svg-15' into 'master'

Feat/bool mat svg 15

See merge request !17
parents 3e4f8972 522564f8
No related branches found
No related tags found
1 merge request!17Feat/bool mat svg 15
......@@ -16,4 +16,7 @@ out
# Miscellaneous
*.DS_Store
*.db
\ No newline at end of file
*.db
# Exported SVG files
*.svg
......@@ -41,6 +41,9 @@ dependencies {
// CSV parsing
compile "com.opencsv:opencsv:4.6"
// SVG
compile group: 'org.jfree', name: 'jfreesvg', version: '3.4'
}
tasks.withType(Test) {
......
......@@ -22,6 +22,8 @@ import de.tudresden.inf.mci.brailleplot.datacontainers.CategoricalPointListConta
import de.tudresden.inf.mci.brailleplot.datacontainers.PointList;
import de.tudresden.inf.mci.brailleplot.diagrams.BarChart;
import de.tudresden.inf.mci.brailleplot.rendering.MasterRenderer;
import de.tudresden.inf.mci.brailleplot.svgexporter.BoolMatrixDataSvgExporter;
import de.tudresden.inf.mci.brailleplot.svgexporter.SvgExporter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -36,7 +38,7 @@ import java.util.concurrent.ConcurrentLinkedDeque;
* Main class.
* Set up the application and run it.
* @author Georg Graßnick, Andrey Ruzhanskiy
* @version 06.06.19
* @version 2019.08.16
*/
public final class App {
......@@ -170,7 +172,10 @@ public final class App {
SimpleMatrixDataImpl<Boolean> mat = (SimpleMatrixDataImpl<Boolean>) canvas.getCurrentPage();
mLogger.debug("Render preview:\n" + mat.toBoolString());
// Config Parsing
// SVG exporting
SvgExporter<RasterCanvas> svgExporter = new BoolMatrixDataSvgExporter(canvas);
svgExporter.render();
svgExporter.dump("boolMat");
// Check if some SpoolerService/Printservice exists
if (!PrintDirector.isPrintServiceOn()) {
......
......@@ -12,10 +12,11 @@ import java.util.ListIterator;
/**
* Representation of a target onto which can be drawn. It wraps a {@link PrintableData} instance and specifies the size of the drawing area (in mm).
* @author Leonard Kupper
* @version 2019.07.22
* @param <T> The type of the managed {@link PrintableData}
* @author Leonard Kupper, Georg Graßnick
* @version 2019.08.16
*/
public abstract class AbstractCanvas {
public abstract class AbstractCanvas<T extends PrintableData> {
private final Logger mLogger = LoggerFactory.getLogger(this.getClass());
......@@ -24,7 +25,7 @@ public abstract class AbstractCanvas {
Rectangle mPrintableArea;
List<PrintableData> mPageContainer;
List<T> mPageContainer;
AbstractCanvas(final Printer printer, final Format format) throws InsufficientRenderingAreaException {
......@@ -117,6 +118,14 @@ public abstract class AbstractCanvas {
return mPrintableArea.getHeight();
}
public final double getPageWidth() {
return mFormat.getProperty("page.width").toDouble();
}
public final double getPageHeight() {
return mFormat.getProperty("page.height").toDouble();
}
/**
* Get the number of pages in the canvas.
* @return The number of pages.
......@@ -126,11 +135,10 @@ public abstract class AbstractCanvas {
}
/**
* Get an Iterator for the PrintableData instances representing the canvas pages. The single instances should be
* casted to the regarding concrete type depending on the canvas implementation.
* Get an Iterator for the PrintableData instances representing the canvas pages.
* @return A {@link ListIterator}&lt;{@link PrintableData}&gt;.
*/
public ListIterator<PrintableData> getPageIterator() {
public ListIterator<T> getPageIterator() {
return mPageContainer.listIterator();
}
......
......@@ -8,6 +8,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static java.lang.Math.abs;
import static java.lang.Math.ceil;
......@@ -16,10 +18,10 @@ import static java.lang.Math.floor;
/**
* Representation of a target onto which an image can be rasterized.
* It wraps a {@link de.tudresden.inf.mci.brailleplot.printabledata.MatrixData} instance and describes the raster size and its (not necessarily equidistant) layout.
* @author Leonard Kupper
* @version 2019.07.22
* @author Leonard Kupper, georg Graßnick
* @version 2019.08.16
*/
public class RasterCanvas extends AbstractCanvas {
public class RasterCanvas extends AbstractCanvas<MatrixData<Boolean>> {
private final Logger mLogger = LoggerFactory.getLogger(this.getClass());
......@@ -83,14 +85,11 @@ public class RasterCanvas extends AbstractCanvas {
return getCurrentPage();
}
@SuppressWarnings("unchecked")
// This is allowed because the mPageContainer fields are always initialized with the correct type by the page getters,
// cannot be accessed from the outside and are never changed anywhere else.
public final MatrixData<Boolean> getCurrentPage() {
if (mPageContainer.size() < 1) {
return getNewPage();
}
return (MatrixData<Boolean>) mPageContainer.get(mPageContainer.size() - 1);
return mPageContainer.get(mPageContainer.size() - 1);
}
private void readConfig() {
......@@ -259,6 +258,22 @@ public class RasterCanvas extends AbstractCanvas {
return dotY / mCellHeight;
}
public final int getFullConstraintLeft() {
return (int) Math.round(mPrinter.getProperty("raster.constraint.left").toInt() * mCellHorizontalMM + mPrinter.getProperty("constraint.left").toDouble());
}
public final int getFullConstraintTop() {
return (int) Math.round(mPrinter.getProperty("raster.constraint.top").toInt() * mCellVerticalMM + mPrinter.getProperty("constraint.top").toDouble());
}
public final List<Double> getXPositions() {
return Collections.unmodifiableList(mXPositions);
}
public final List<Double> getYPositions() {
return Collections.unmodifiableList(mYPositions);
}
public final int quantifyX(final double unquantifiedMillimeterX) {
return findClosestValueIndex(unquantifiedMillimeterX, mXPositions);
......
package de.tudresden.inf.mci.brailleplot.svgexporter;
import de.tudresden.inf.mci.brailleplot.printabledata.PrintableData;
import de.tudresden.inf.mci.brailleplot.layout.AbstractCanvas;
import org.jfree.graphics2d.svg.SVGGraphics2D;
import org.jfree.graphics2d.svg.SVGUnits;
import org.jfree.graphics2d.svg.ViewBox;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.awt.BasicStroke;
import java.awt.Color;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
import java.util.ListIterator;
import java.util.Objects;
/**
* Abstract parent class for all SVG exporter classes.
* @param <T> The type of the Abstract Canvas that is used.
* @param <U> The type of the {@link PrintableData} that is used.
* @author Georg Graßnick
* @version 2019.08.20
*/
abstract class AbstractSvgExporter<T extends AbstractCanvas, U extends PrintableData> implements SvgExporter<T> {
protected final Logger mLogger = LoggerFactory.getLogger(getClass());
protected final T mCanvas;
protected List<SVGGraphics2D> mSvgs;
private ViewBox mViewBox;
protected static final int SCALE_FACTOR = 2;
protected static final float STROKE_WIDTH = 1f;
AbstractSvgExporter(final T canvas) {
Objects.requireNonNull(canvas);
mCanvas = canvas;
}
@Override
// As long as the implementing class uses the correct generic type,
// the cast for the first parameter of renderPage() is safe.
@SuppressWarnings("unchecked")
public void render() {
final int docWidth = (int) Math.ceil(mCanvas.getPageWidth());
final int docHeight = (int) Math.ceil(mCanvas.getPageHeight());
final int viewBoxWidth = docWidth * SCALE_FACTOR;
final int viewBoxHeight = docHeight * SCALE_FACTOR;
mViewBox = new ViewBox(0, 0, viewBoxWidth, viewBoxHeight);
ListIterator it = mCanvas.getPageIterator();
int idx = 0;
while (it.hasNext()) {
SVGGraphics2D svg = new SVGGraphics2D(docWidth, docHeight, SVGUnits.MM);
svg.setBackground(Color.WHITE);
svg.clearRect(0, 0, Integer.MAX_VALUE, Integer.MAX_VALUE);
svg.setStroke(new BasicStroke(STROKE_WIDTH));
mSvgs.add(svg);
mLogger.debug("Created SVG with StrokeWitdh {}, ScaleFactor {}, DocumentWidth {}mm, DocumentHeight {}mm, ViewPort: ({},{})", STROKE_WIDTH, SCALE_FACTOR, docWidth, docHeight, viewBoxWidth, viewBoxHeight);
renderPage((((U) it.next())), idx++);
}
}
@Override
public void dump(final OutputStream os, final int dataIndex) throws IOException {
Objects.requireNonNull(os);
final String doc = mSvgs.get(dataIndex).getSVGElement(null, true, mViewBox, null, null);
mLogger.trace("Start dumping file to stream ...");
os.write(doc.getBytes());
mLogger.trace("Finished dumping file to stream");
}
@Override
public void dump(final String filePath, final int dataIndex) throws IOException {
Objects.requireNonNull(filePath);
try (FileOutputStream fs = new FileOutputStream(filePath)) {
dump(fs, dataIndex);
}
}
@Override
public void dump(final String baseFileName) throws IOException {
Objects.requireNonNull(baseFileName);
for (int i = 0; i < mSvgs.size(); i++) {
dump(baseFileName + String.format("_%03d.svg", i), i);
}
}
protected abstract void renderPage(U mat, int dataIndex);
}
package de.tudresden.inf.mci.brailleplot.svgexporter;
import de.tudresden.inf.mci.brailleplot.printabledata.MatrixData;
import de.tudresden.inf.mci.brailleplot.layout.RasterCanvas;
import org.jfree.graphics2d.svg.SVGGraphics2D;
import java.util.ArrayList;
import java.util.List;
/**
* SVG exporter class that supports {@link RasterCanvas} as input.
* @author Georg Graßnick
* @version 2019.08.20
*/
public class BoolMatrixDataSvgExporter extends AbstractSvgExporter<RasterCanvas, MatrixData<Boolean>> {
public BoolMatrixDataSvgExporter(final RasterCanvas rasterCanvas) {
super(rasterCanvas);
mSvgs = new ArrayList<>(mCanvas.getPageCount());
}
@Override
protected void renderPage(final MatrixData<Boolean> mat, final int dataIndex) {
List<Double> xPositions = mCanvas.getXPositions();
List<Double> yPositions = mCanvas.getYPositions();
int dotDiameter = (int) mCanvas.getDotDiameter() * SCALE_FACTOR;
mLogger.trace("Dot diameter: {}", dotDiameter);
SVGGraphics2D svg = mSvgs.get(dataIndex);
for (int y = 0; y < mat.getRowCount(); y++) {
for (int x = 0; x < mat.getColumnCount(); x++) {
if (mat.getValue(y, x)) {
int xPos = (int) Math.round((xPositions.get(x) + mCanvas.getFullConstraintLeft() - dotDiameter / 2) * SCALE_FACTOR);
int yPos = (int) Math.round((yPositions.get(y) + mCanvas.getFullConstraintTop() - dotDiameter / 2) * SCALE_FACTOR);
svg.drawOval(xPos, yPos, dotDiameter, dotDiameter);
mLogger.trace("Drew dot at position ({},{})", xPos, yPos);
}
}
}
}
}
package de.tudresden.inf.mci.brailleplot.svgexporter;
import de.tudresden.inf.mci.brailleplot.layout.AbstractCanvas;
import java.io.IOException;
import java.io.OutputStream;
/**
* Interface for all classes that support exporting PrintableData to SVG files.
* @param <T> The type of the supported PrintableData.
* @author Georg Graßnick
* @version 2019.08.16
*/
public interface SvgExporter<T extends AbstractCanvas> {
/**
* Process the actual rendering of the data to SVG.
*/
void render();
/**
* Dump a specific rendered SVG to an output stream.
* @param os The stream to dump the SVG to.
* @param dataIndex The index of the {@link de.tudresden.inf.mci.brailleplot.printabledata.PrintableData} in {@link AbstractCanvas#getPageIterator()}
* @throws IOException on any IO related issues.
*/
void dump(OutputStream os, int dataIndex) throws IOException;
/**
Dump a specific rendered SVG to a file.
* @param filePath The path to dump the file at.
* @param dataIndex The index of the {@link de.tudresden.inf.mci.brailleplot.printabledata.PrintableData} in {@link AbstractCanvas#getPageIterator()}
* @throws IOException on any IO related issues.
*/
void dump(String filePath, int dataIndex) throws IOException;
/**
* Dump all rendered SVGs to separate files.
* @param baseFileName The basename of all files. Output filename format: ${basename}_${Index}.svg
* @throws IOException on any IO related issues.
*/
void dump(String baseFileName) throws IOException;
}
/**
* Provides classes used for creating SVG Documents which provide a preview function
* of the embossed document.
* @author Georg Graßnick
* @version 2019.08.16
*/
package de.tudresden.inf.mci.brailleplot.svgexporter;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment