Revision: 97e4068bb6
Author: dom...@sashimi.telesystem.com
Date: Sun Aug 9 01:45:08 2009
Log: * moved pens into layers...
http://code.google.com/p/menya/source/detail?r=97e4068bb6
Revision: 6fa91d1d44
Author: dom...@sashimi.telesystem.com
Date: Sun Aug 9 01:48:06 2009
Log: asdf
http://code.google.com/p/menya/source/detail?r=6fa91d1d44
==============================================================================
Revision: 97e4068bb6
Author: dom...@sashimi.telesystem.com
Date: Sun Aug 9 01:45:08 2009
Log: * moved pens into layers
* layers know how and if they are editable with certain working tools (pens)
http://code.google.com/p/menya/source/detail?r=97e4068bb6
Modified:
/src/main/java/menya/core/document/ILayer.java
/src/main/java/menya/core/document/IPage.java
/src/main/java/menya/core/document/layers/ALayer.java
/src/main/java/menya/core/document/layers/CurveLayer.java
/src/main/java/menya/core/document/layers/PDFLayer.java
/src/main/java/menya/core/model/Curve.java
/src/main/java/menya/core/model/Document.java
/src/main/java/menya/core/model/IWorkingTool.java
/src/main/java/menya/core/model/Page.java
/src/main/java/menya/core/model/tools/AWorkingTool.java
/src/main/java/menya/gui/SketchPane.java
=======================================
--- /src/main/java/menya/core/document/ILayer.java Wed Aug 5 15:01:06 2009
+++ /src/main/java/menya/core/document/ILayer.java Sun Aug 9 01:45:08 2009
@@ -19,8 +19,10 @@
package menya.core.document;
import java.io.IOException;
+import java.util.List;
import menya.core.model.GraphicalData;
+import menya.core.model.IWorkingTool;
import org.apache.pdfbox.pdmodel.edit.PDPageContentStream;
@@ -35,33 +37,100 @@
* @version $Revision$
*/
public interface ILayer {
- /**
- * retrieves the graphical data provided by this layer.
- *
- * @return A Set of graphical data.
- */
- Iterable<GraphicalData> getGraphicalData();
-
- /**
- * Simple check if this layer has changed since {@link
#getGraphicalData()}
- * was last called.
- * <p>
- * If getGraphicalData was never called the result is undefined.
- *
- * @return false only if the data has not changed.
- */
- boolean hasChanged();
-
- /**
- * Serialize this layer to the given PDF content stream.
- *
- * @param contentStream
- * PDF Content stream.
- * @param page
- * the current page this layer originate of.
- * @throws IOException
- * if the layer cannot be written to the content stream.
- */
- void toPdf(PDPageContentStream contentStream, IPage page)
- throws IOException;
-}
+ /**
+ * retrieves the graphical data provided by this layer.
+ *
+ * @return A Set of graphical data.
+ */
+ Iterable<GraphicalData> getGraphicalData();
+
+ /**
+ * Simple check if this layer has changed since {@link
#getGraphicalData()}
+ * was last called.
+ * <p>
+ * If getGraphicalData was never called the result is undefined.
+ *
+ * @return false only if the data has not changed.
+ */
+ boolean hasChanged();
+
+ /**
+ * Serialize this layer to the given PDF content stream.
+ *
+ * @param contentStream
+ * PDF Content stream.
+ * @param page
+ * the current page this layer originate of.
+ * @throws IOException
+ * if the layer cannot be written to the content stream.
+ */
+ void toPdf(PDPageContentStream contentStream, IPage page)
+ throws IOException;
+
+ /**
+ * retrieves all available pens for this specific layer.
+ * <p>
+ * <b>NOTE:</b> a layer that has no pens IS NOT EDITABLE
+ * </p>
+ *
+ * @return
+ */
+ public List<IWorkingTool> getAllPens();
+
+ /**
+ * retrieves the currently active pen for this layer. If it was not
changed
+ * it is the default pen.
+ * <p>
+ * <b>NOTE:</b> a layer that has no pens IS NOT EDITABLE and this method
+ * will always return null
+ * </p>
+ *
+ * @return
+ */
+ public IWorkingTool getActivePen();
+
+ /**
+ * retrieves if a layers has pens and hence if it is editable.
+ *
+ * @return
+ */
+ public boolean isEditable();
+
+ /**
+ * sets the currently active pen if the pen passed as argument is a valid
+ * pen for this layer. Otherwise a {@link IllegalArgumentException} will
be
+ * thrown.
+ *
+ * @param pen
+ * @throws IllegalArgumentException
+ */
+ public void setActivePen(IWorkingTool pen) throws
IllegalArgumentException;
+
+ /**
+ * retrieves the default pen for this layer. This is always the one, that
+ * was added as first.
+ * <p>
+ * <b>NOTE:</b> a layer that has no pens IS NOT EDITABLE and this method
+ * will return null
+ * </p>
+ *
+ * @return
+ */
+ public IWorkingTool getDefaultPen();
+
+ /**
+ * is a utility method to add a pen, as the method {@link #getAllPens()}
+ * returns a unmodifiable list.
+ *
+ * @param pen
+ */
+ public void addPen(IWorkingTool pen);
+
+ /**
+ * is a utility method to remove a pen, as the method {@link
#getAllPens()}
+ * returns a unmodifiable list.
+ *
+ * @param pen
+ */
+ public void removePen(IWorkingTool pen);
+}
=======================================
--- /src/main/java/menya/core/document/IPage.java Wed Aug 5 15:01:06 2009
+++ /src/main/java/menya/core/document/IPage.java Sun Aug 9 01:45:08 2009
@@ -20,8 +20,10 @@
import java.awt.geom.Dimension2D;
import java.util.Deque;
+import java.util.List;
import menya.core.document.layers.CurveLayer;
+import menya.core.model.IWorkingTool;
/**
* This interfaces represents a page in a MENYA Document.
@@ -32,32 +34,46 @@
*/
public interface IPage {
- /**
- * @return the size of the page in Point.
- */
- Dimension2D getPageSize();
-
- /**
- * retrieves the background layer of this page. Basically would it be
the
- * lowest (=first) layer. Thus it is the same as if we would call
- * getLayers().peekFirst().
- *
- * @return the background of this document or null if no layers are
present.
- */
- ILayer getBackground();
-
- /**
- * retrieves all layers of this document.
- *
- * @return the document layers as stack
- */
- Deque<ILayer> getLayers();
-
- /**
- * Retrieves an active curve layer. This method never returns null -
if no
- * curve layer is present, a new one must be created.
- *
- * @return the active curve layer.
- */
- CurveLayer getActiveLayer();
-}
+ /**
+ * @return the size of the page in Point.
+ */
+ Dimension2D getPageSize();
+
+ /**
+ * retrieves the background layer of this page. Basically would it be the
+ * lowest (=first) layer. Thus it is the same as if we would call
+ * getLayers().peekFirst().
+ *
+ * @return the background of this document or null if no layers are
present.
+ */
+ ILayer getBackground();
+
+ /**
+ * retrieves all layers of this document.
+ *
+ * @return the document layers as stack
+ */
+ Deque<ILayer> getLayers();
+
+ /**
+ * Retrieves an active curve layer. This method never returns null - if no
+ * curve layer is present, a new one must be created.
+ *
+ * @return the active curve layer.
+ */
+ CurveLayer getActiveLayer();
+
+ /**
+ * @return
+ */
+ public IWorkingTool getDefaultPen();
+
+ public IWorkingTool getActivePen();
+
+ public void setActivePen(IWorkingTool pen) throws
IllegalArgumentException;
+
+ /**
+ * @return
+ */
+ public List<IWorkingTool> getAllPens();
+}
=======================================
--- /src/main/java/menya/core/document/layers/ALayer.java Wed Aug 5
15:01:06 2009
+++ /src/main/java/menya/core/document/layers/ALayer.java Sun Aug 9
01:45:08 2009
@@ -18,7 +18,12 @@
package menya.core.document.layers;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
import menya.core.document.ILayer;
+import menya.core.model.IWorkingTool;
/**
* is the abstract super class of all layers.
@@ -28,4 +33,72 @@
*/
public abstract class ALayer implements ILayer {
-}
+ private List<IWorkingTool> pens = new LinkedList<IWorkingTool>();
+ private IWorkingTool activePen;
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final List<IWorkingTool> getAllPens() {
+ return Collections.unmodifiableList(pens);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final void addPen(IWorkingTool pen) {
+ pens.add(pen);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final void removePen(IWorkingTool pen) {
+ pens.remove(pen);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final boolean isEditable() {
+ return getAllPens().size() > 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public IWorkingTool getDefaultPen() {
+ return getAllPens().get(0);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final IWorkingTool getActivePen() {
+ if (activePen != null) {
+ return activePen;
+ } else {
+ return getDefaultPen();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final void setActivePen(IWorkingTool pen)
+ throws IllegalArgumentException {
+ if (getAllPens().contains(pen)) {
+ activePen = pen;
+ } else {
+ throw new IllegalArgumentException("The specified pen " + pen
+ + " is not part of this layer.");
+ }
+ }
+}
=======================================
--- /src/main/java/menya/core/document/layers/CurveLayer.java Wed Aug 5
15:01:06 2009
+++ /src/main/java/menya/core/document/layers/CurveLayer.java Sun Aug 9
01:45:08 2009
@@ -26,6 +26,7 @@
import menya.core.document.IPage;
import menya.core.model.Curve;
import menya.core.model.GraphicalData;
+import menya.core.model.tools.StandardPen;
import org.apache.pdfbox.pdmodel.edit.PDPageContentStream;
@@ -37,52 +38,52 @@
*/
public class CurveLayer extends ALayer implements Serializable {
- private static final long serialVersionUID = 1L;
-
- private final List<Curve> curves = new ArrayList<Curve>();
-
- private transient boolean hasChanged;
-
- /**
- * Default constructor.
- */
- public CurveLayer() {
- // empty on purpose.
- }
-
- /** {@inheritDoc} */
- @SuppressWarnings("unchecked")
- public Iterable<GraphicalData> getGraphicalData() {
- final Iterable<Curve> i = this.curves;
- final Iterable d = i;
- this.hasChanged = false;
- return d;
- }
-
- /**
- * Adds a new curve to the layer.
- *
- * @param curve
- * the curve to add.
- */
- public void addCurve(final Curve curve) {
- this.hasChanged = true;
- this.curves.add(curve);
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean hasChanged() {
- return this.hasChanged;
- }
-
- /** {@inheritDoc} */
- @Override
- public void toPdf(final PDPageContentStream contentStream, final IPage
page)
- throws IOException {
- for (final Curve curve : this.curves) {
- curve.toPdf(contentStream, page);
- }
- }
-
-}
+ private static final long serialVersionUID = 1L;
+
+ private final List<Curve> curves = new ArrayList<Curve>();
+
+ private transient boolean hasChanged;
+
+ /**
+ * Default constructor.
+ */
+ public CurveLayer() {
+ // this is a editable layer, hence add a pen
+ addPen(new StandardPen());
+ }
+
+ /** {@inheritDoc} */
+ @SuppressWarnings("unchecked")
+ public Iterable<GraphicalData> getGraphicalData() {
+ final Iterable<Curve> i = this.curves;
+ final Iterable d = i;
+ this.hasChanged = false;
+ return d;
+ }
+
+ /**
+ * Adds a new curve to the layer.
+ *
+ * @param curve
+ * the curve to add.
+ */
+ public void addCurve(final Curve curve) {
+ this.hasChanged = true;
+ this.curves.add(curve);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean hasChanged() {
+ return this.hasChanged;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void toPdf(final PDPageContentStream contentStream, final IPage
page)
+ throws IOException {
+ for (final Curve curve : this.curves) {
+ curve.toPdf(contentStream, page);
+ }
+ }
+}
=======================================
--- /src/main/java/menya/core/document/layers/PDFLayer.java Wed Aug 5
15:01:06 2009
+++ /src/main/java/menya/core/document/layers/PDFLayer.java Sun Aug 9
01:45:08 2009
@@ -25,6 +25,7 @@
import menya.core.document.IPage;
import menya.core.model.GraphicalData;
+import menya.core.model.tools.StandardPen;
import org.apache.pdfbox.pdfviewer.PageDrawer;
import org.apache.pdfbox.pdmodel.PDPage;
@@ -38,80 +39,83 @@
*/
public class PDFLayer extends ALayer {
- /**
- * Logger for this class.
- */
- private static final Logger LOGGER = Logger.getLogger(PDFLayer.class
- .toString());
-
- private final PageDrawer drawer;
- private final PDPage page;
- private final Dimension dimension;
-
- /**
- * Create a new PDF based layer.
- *
- * @param pgdrawer
- * page drawer object
- * @param pdpage
- * page object
- * @param pageDimension
- * page dimensions
- */
- public PDFLayer(final PageDrawer pgdrawer, final PDPage pdpage,
- final Dimension pageDimension) {
- this.drawer = pgdrawer;
- this.page = pdpage;
- this.dimension = pageDimension;
- }
-
- private class PDFGraphics implements GraphicalData {
-
- protected PDFGraphics() {
- // Empty on purpose.
- }
-
- /** {@inheritDoc} */
- @Override
- public void draw(final Graphics2D g2d) {
- try {
- PDFLayer.this.drawer.drawPage(g2d, PDFLayer.this.page,
- PDFLayer.this.dimension);
- } catch (final IOException io) {
- PDFLayer.LOGGER.log(Level.WARNING, "Failed to render
page", io);
- }
- }
- }
-
- /** {@inheritDoc} */
- @SuppressWarnings("unchecked")
- @Override
- public Iterable<GraphicalData> getGraphicalData() {
- final List l = Collections.singletonList(new PDFGraphics());
- final List<GraphicalData> g = l;
- return g;
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean hasChanged() {
- return false;
- }
-
- /**
- * Getter for PDF page object.
- *
- * @return the page.
- */
- public PDPage getPage() {
- return this.page;
- }
-
- /** {@inheritDoc} */
- @Override
- public void toPdf(final PDPageContentStream contentStream, final IPage
ipage)
- throws IOException {
- throw new IOException("Unsupported Operation: toPDF on PDFLayer");
- }
+ /**
+ * Logger for this class.
+ */
+ private static final Logger LOGGER = Logger.getLogger(PDFLayer.class
+ .toString());
+
+ private final PageDrawer drawer;
+ private final PDPage page;
+ private final Dimension dimension;
+
+ /**
+ * Create a new PDF based layer.
+ *
+ * @param pgdrawer
+ * page drawer object
+ * @param pdpage
+ * page object
+ * @param pageDimension
+ * page dimensions
+ */
+ public PDFLayer(final PageDrawer pgdrawer, final PDPage pdpage,
+ final Dimension pageDimension) {
+ this.drawer = pgdrawer;
+ this.page = pdpage;
+ this.dimension = pageDimension;
+
+ // FIXME is this correct for all pdf layers?
+ addPen(new StandardPen());
+ }
+
+ private class PDFGraphics implements GraphicalData {
+
+ protected PDFGraphics() {
+ // Empty on purpose.
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void draw(final Graphics2D g2d) {
+ try {
+ PDFLayer.this.drawer.drawPage(g2d, PDFLayer.this.page,
+ PDFLayer.this.dimension);
+ } catch (final IOException io) {
+ PDFLayer.LOGGER.log(Level.WARNING, "Failed to render page", io);
+ }
+ }
+ }
+
+ /** {@inheritDoc} */
+ @SuppressWarnings("unchecked")
+ @Override
+ public Iterable<GraphicalData> getGraphicalData() {
+ final List l = Collections.singletonList(new PDFGraphics());
+ final List<GraphicalData> g = l;
+ return g;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean hasChanged() {
+ return false;
+ }
+
+ /**
+ * Getter for PDF page object.
+ *
+ * @return the page.
+ */
+ public PDPage getPage() {
+ return this.page;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void toPdf(final PDPageContentStream contentStream, final IPage
ipage)
+ throws IOException {
+ throw new IOException("Unsupported Operation: toPDF on PDFLayer");
+ }
}
=======================================
--- /src/main/java/menya/core/model/Curve.java Thu Aug 6 02:45:34 2009
+++ /src/main/java/menya/core/model/Curve.java Sun Aug 9 01:45:08 2009
@@ -53,8 +53,6 @@
private static final int THREE_DATA_POINTS = 6;
- private static final float DISTANCE_THRESHOLD = 3.5f;
-
private final List<Point> path = new ArrayList<Point>();
/**
@@ -155,27 +153,4 @@
}
return bos.toByteArray();
}
-
- /**
- * This method reduces the number of points in the curve.
- * <p>
- * TODO: extract functionality and provide external <a
- *
href="http://en.wikipedia.org/wiki/Smooth_Operator">smooth-operators</a>.
- * <p>
- * TODO: This is a very basic smoothing algorithm.
- */
- public void smoothPath() {
- Point prev = this.path.get(0);
- // Never smooth first or last point!
- for (int i = 1; i < this.path.size() - 1; i++) {
- Point cur = this.path.get(i);
- while (cur.distanceTo(prev) < Curve.DISTANCE_THRESHOLD
- && i < this.path.size() - 1) {
- this.path.remove(i);
- cur = this.path.get(i);
- System.out.println("Removing " + i);
- }
- prev = cur;
- }
- }
-}
+}
=======================================
--- /src/main/java/menya/core/model/Document.java Wed Aug 5 15:01:06 2009
+++ /src/main/java/menya/core/model/Document.java Sun Aug 9 01:45:08 2009
@@ -62,437 +62,437 @@
*/
public final class Document implements IDocument {
- /**
+ /**
*
*/
- private static final String PDF_PIECE_INFO = "PieceInfo";
-
- /**
+ private static final String PDF_PIECE_INFO = "PieceInfo";
+
+ /**
*
*/
- private static final String PDF_LAYER_PREFIX = "Layer";
-
- /**
+ private static final String PDF_LAYER_PREFIX = "Layer";
+
+ /**
*
*/
- private static final String PDF_PRIVATE = "Private";
-
- /**
+ private static final String PDF_PRIVATE = "Private";
+
+ /**
*
*/
- private static final String PDF_MENYA_DICT = "Menya";
-
- /**
+ private static final String PDF_MENYA_DICT = "Menya";
+
+ /**
*
*/
- private static final String PDF_LAST_MODIFIED = "LastModified";
-
- /**
- * Rotated left (or right?).
- */
- private static final int LANDSCAPE_1 = 90;
-
- /**
- * Rotated right (or left?).
- */
- private static final int LANDSCAPE_2 = 270;
-
- /**
- * Logger for this class.
- */
- private static final Logger LOGGER = Logger.getLogger(Document.class
- .toString());
-
- private final List<IPage> pages;
-
- private final PDDocument pdfDocument;
-
- private final PageDrawer pageDrawer;
-
- /**
- * Default Constructor.
- *
- * @param underlayingDocument
- * Document this document is based on.
- * @param pgDrawer
- * a PageDrawer object.
- */
- private Document(final PDDocument underlayingDocument,
- final PageDrawer pgDrawer) {
- this.pages = new ArrayList<IPage>();
- this.pdfDocument = underlayingDocument;
- this.pageDrawer = pgDrawer;
- }
-
- /** {@inheritDoc} */
- public List<IPage> getPages() {
- return Collections.unmodifiableList(this.pages);
- }
-
- /**
- * Create an empty document.
- *
- * @return an empty Document with one page.
- */
- public static Document emptyDocument() {
- PDDocument pddoc;
- PageDrawer pgDrawer;
- try {
- pddoc = new PDDocument();
- pgDrawer = new PageDrawer();
- } catch (final IOException io) {
- Document.LOGGER.log(Level.WARNING,
- "Failed to base Document on PDF", io);
- pddoc = null;
- pgDrawer = null;
- }
- final Document d = new Document(pddoc, pgDrawer);
- d.addEmptyPage();
- return d;
- }
-
- /**
- * Add an empty page to the document.
- */
- private void addEmptyPage() {
- final Page p = new Page();
- if (this.pdfDocument != null) {
- final Dimension2D pgDimension = p.getPageSize();
- final Dimension pageDimension = new Dimension((int) pgDimension
- .getWidth(), (int) pgDimension.getHeight());
- final PDPage pdPage = new PDPage();
- this.pdfDocument.addPage(pdPage);
- final ILayer pdfLayer = new PDFLayer(this.pageDrawer, pdPage,
- pageDimension);
- p.addLayer(pdfLayer);
- }
- this.pages.add(p);
- }
-
- /**
- * Create a new Document from a given PDF file.
- *
- * @param filename
- * file to open
- * @return a Document instance.
- * @throws IOException
- * if the document could not be loaded.
- */
- public static Document fromPDF(final String filename) throws
IOException {
- final PDDocument pddoc = PDDocument.load(filename);
- final PageDrawer drawer = new PageDrawer();
- final Document d = new Document(pddoc, drawer);
-
- final List<?> pages = pddoc.getDocumentCatalog().getAllPages();
-
- for (final Object pg : pages) {
- if (pg instanceof PDPage) {
- final PDPage pdpage = (PDPage) pg;
- Document.removeMenyaLayers(pdpage, pddoc);
- Document.createMenyaPage(drawer, d, pdpage);
- } else {
- Document.LOGGER.warning("Unknown Class in PageList: "
- + pg.getClass());
- }
- }
- return d;
- }
-
- /**
- * @param pdpage
- */
- private static void removeMenyaLayers(final PDPage pdpage,
- final PDDocument pddoc) throws IOException {
- try {
- final List<?> tokens = pdpage.getContents().getStream()
- .getStreamTokens();
- final Deque<COSBase> arguments = new LinkedList<COSBase>();
- final PDStream pds = new PDStream(pddoc);
- pds.addCompression();
- final OutputStream os = pds.createOutputStream();
- final COSWriter writer = new COSWriter(os);
-
- boolean invisa = false;
- for (final Object t : tokens) {
- if (t instanceof COSBase) {
- arguments.addLast((COSBase) t);
- } else if (t instanceof PDFOperator) {
- final PDFOperator o = (PDFOperator) t;
- if ("BDC".equals(o.getOperation())) {
- // TODO: This filters ALL Layers, but it should
only
- // filter menya layers.
- arguments.clear();
- invisa = true;
- }
- if (!invisa) {
- while (!arguments.isEmpty()) {
- final COSBase b = arguments.removeFirst();
- b.accept(writer);
- os.write(COSWriter.SPACE);
- }
- os.write(o.getOperation().getBytes());
- os.write(COSWriter.SPACE);
- }
- if ("EMC".equals(o.getOperation())) {
- invisa = false;
- }
- } else {
- Document.LOGGER.warning("Unsupported Token: "
- + t.getClass());
- }
- }
- writer.close();
- pdpage.setContents(pds);
- } catch (final COSVisitorException e) {
- throw new IOException("Error filtering ContentStream", e);
- }
- }
-
- /**
- * @param drawer
- * @param d
- * @param pdpage
- */
- private static void createMenyaPage(final PageDrawer drawer,
- final Document d, final PDPage pdpage) throws IOException {
- final PDRectangle pageSize = pdpage.findMediaBox();
- final int rotation = pdpage.findRotation();
- Dimension pageDimension = pageSize.createDimension();
- if (rotation == Document.LANDSCAPE_1
- || rotation == Document.LANDSCAPE_2) {
- pageDimension = new Dimension(pageDimension.height,
- pageDimension.width);
- // TODO : check rotation = 0 || 180
- }
- final Page menyaPage = new Page();
- menyaPage.setPageSize(pageDimension);
- final ILayer pdfLayer = new PDFLayer(drawer, pdpage,
pageDimension);
- menyaPage.addLayer(pdfLayer);
- Document.extractSerializedLayers(pdpage, menyaPage);
- d.pages.add(menyaPage);
- }
-
- /**
- * @param pdpage
- * @param menyaPage
- */
- private static void extractSerializedLayers(final PDPage pdpage,
- final Page menyaPage) throws IOException {
- // TODO: Check LastModified to ensure menya metadata is still
current.
- try {
- final COSDictionary pieceInfo = Document.getPieceInfo(pdpage);
- final COSDictionary menyaDict = Document.getAndCreateDict(
- pieceInfo, Document.PDF_MENYA_DICT);
- final COSDictionary privateDict = Document.getAndCreateDict(
- menyaDict, Document.PDF_PRIVATE);
- int i = 0;
- COSBase cb = privateDict.getDictionaryObject(Document
- .getLayerName(i));
- while (cb instanceof COSString) {
- final COSString cs = (COSString) cb;
- final byte[] buf = cs.getBytes();
- final ByteArrayInputStream bis = new
ByteArrayInputStream(buf);
- final ObjectInputStream ois = new ObjectInputStream(bis);
- final ILayer layer = (ILayer) ois.readObject();
- menyaPage.addLayer(layer);
- i++;
- cb =
privateDict.getDictionaryObject(Document.getLayerName(i));
- }
- } catch (final ClassNotFoundException e) {
- throw new IOException("Failed to read embedded Menya Layer",
e);
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public void close() {
- if (this.pdfDocument != null) {
- try {
- this.pdfDocument.close();
- } catch (final IOException e) {
- Document.LOGGER.log(Level.WARNING,
- "Failed to close PDFDocument", e);
- }
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public void toPDF(final String filename) throws IOException {
- if (this.pdfDocument == null) {
- throw new IOException("Document is not based on a PDF");
- }
- try {
- final Calendar now = Calendar.getInstance();
- for (final IPage page : this.pages) {
- final List<ILayer> menyaLayers = new ArrayList<ILayer>();
- final PDFLayer pdfLayer = this.findPDFLayer(page,
menyaLayers);
- if (pdfLayer == null) {
- throw new IOException(
- "Failed to find PDF Layer in all pages");
- }
- Document.storeMenyaLayers(now, menyaLayers, pdfLayer,
- this.pdfDocument, page);
- }
- this.pdfDocument.save(filename);
- } catch (final COSVisitorException e) {
- throw new IOException("Failure during save as PDF", e);
- }
- }
-
- /**
- * @param now
- * @param menyaLayers
- * @param pdfLayer
- * @throws IOException
- */
- private static void storeMenyaLayers(final Calendar now,
- final List<ILayer> menyaLayers, final PDFLayer pdfLayer,
- final PDDocument pddoc, final IPage page) throws IOException {
- final PDPage pdpage = pdfLayer.getPage();
- Document.storeGraphicalMenyaData(menyaLayers, pdpage, pddoc, page);
- Document.storeSerializedMenyaData(now, menyaLayers, pdpage);
- }
-
- /**
- * @param menyaLayers
- * @param pdpage
- * @throws IOException
- */
- private static void storeGraphicalMenyaData(final List<ILayer>
menyaLayers,
- final PDPage pdpage, final PDDocument pddoc, final IPage page)
- throws IOException {
- final COSDictionary ocg = Document.createMenyaPDFLayers(pddoc);
- if (pdpage.getResources() == null) {
- pdpage.setResources(new PDResources());
- }
- final COSDictionary properties = Document.getAndCreateDict(pdpage
- .getResources().getCOSDictionary(), "Properties");
- properties.setItem("MC0", ocg);
-
- final PDPageContentStream contentStream;
- if (pdpage.getContents() == null) {
- contentStream = new PDPageContentStream(pddoc, pdpage, false,
true);
- } else {
- contentStream = new PDPageContentStream(pddoc, pdpage, true,
true);
- }
- contentStream.appendRawCommands("/OC /MC0 BDC ");
-
- // TODO: One layer for each menya layer.
- for (final ILayer layer : menyaLayers) {
- layer.toPdf(contentStream, page);
- }
-
- contentStream.appendRawCommands(" EMC");
- contentStream.close();
-
- }
-
- /**
- * @param pddoc
- */
- private static COSDictionary createMenyaPDFLayers(final PDDocument
pddoc) {
- final COSArray intentArray = new COSArray();
- intentArray.add(COSName.getPDFName("View"));
- intentArray.add(COSName.getPDFName("Design"));
- final COSDictionary ocg = new COSDictionary();
- ocg.setName("Type", "OCG");
- ocg.setString("Name", "Layer 1");
- ocg.setItem("Intent", intentArray);
-
- final COSDictionary ocp = Document.getAndCreateDict(pddoc
- .getDocumentCatalog().getCOSDictionary(), "OCProperties");
- final COSDictionary d = Document.getAndCreateDict(ocp, "D");
- final COSArray order = Document.getAndCreateArray(d, "Order");
- order.add(ocg);
- final COSArray on = Document.getAndCreateArray(d, "ON");
- on.add(ocg);
- final COSArray ocgs = Document.getAndCreateArray(ocp, "OCGs");
- ocgs.add(ocg);
- return ocg;
- }
-
- /**
- * @param now
- * @param menyaLayers
- * @param pdpage
- * @throws IOException
- */
- private static void storeSerializedMenyaData(final Calendar now,
- final List<ILayer> menyaLayers, final PDPage pdpage)
- throws IOException {
- final COSDictionary pieceInfo = Document.getPieceInfo(pdpage);
- final COSDictionary menyaDict =
Document.getAndCreateDict(pieceInfo,
- Document.PDF_MENYA_DICT);
- pdpage.getCOSDictionary().setDate(Document.PDF_LAST_MODIFIED, now);
- menyaDict.setDate(Document.PDF_LAST_MODIFIED, now);
- final COSDictionary privateDict =
Document.getAndCreateDict(menyaDict,
- Document.PDF_PRIVATE);
-
- privateDict.clear();
- for (int i = 0; i < menyaLayers.size(); i++) {
- final String name = Document.getLayerName(i);
- final ByteArrayOutputStream bos = new ByteArrayOutputStream();
- final ObjectOutputStream oos = new ObjectOutputStream(bos);
- oos.writeObject(menyaLayers.get(i));
- oos.close();
- privateDict.setItem(name, new COSString(bos.toByteArray()));
- }
- }
-
- /**
- * @param index
- * @return
- */
- private static String getLayerName(final int index) {
- return new StringBuilder(Document.PDF_LAYER_PREFIX).append(index)
- .toString();
- }
-
- /**
- * @param page
- * @param menyaLayers
- * @return
- * @throws IOException
- */
- private PDFLayer findPDFLayer(final IPage page,
- final List<ILayer> menyaLayers) throws IOException {
- PDFLayer pdfLayer = null;
- for (final ILayer layer : page.getLayers()) {
- if (layer instanceof PDFLayer) {
- pdfLayer = (PDFLayer) layer;
- } else if (layer instanceof Serializable) {
- menyaLayers.add(layer);
- } else {
- throw new IOException("Not all layers are Serializable");
- }
- }
- return pdfLayer;
- }
-
- private static COSDictionary getAndCreateDict(final COSDictionary
parent,
- final String name) {
- COSDictionary dict = (COSDictionary)
parent.getDictionaryObject(name);
- if (dict == null) {
- dict = new COSDictionary();
- parent.setItem(name, dict);
- }
- return dict;
- }
-
- private static COSArray getAndCreateArray(final COSDictionary parent,
- final String name) {
- COSArray a = (COSArray) parent.getItem(COSName.getPDFName(name));
- if (a == null) {
- a = new COSArray();
- parent.setItem(name, a);
- }
- return a;
- }
-
- private static COSDictionary getPieceInfo(final PDPage page) {
- return Document.getAndCreateDict(page.getCOSDictionary(),
- Document.PDF_PIECE_INFO);
- }
+ private static final String PDF_LAST_MODIFIED = "LastModified";
+
+ /**
+ * Rotated left (or right?).
+ */
+ private static final int LANDSCAPE_1 = 90;
+
+ /**
+ * Rotated right (or left?).
+ */
+ private static final int LANDSCAPE_2 = 270;
+
+ /**
+ * Logger for this class.
+ */
+ private static final Logger LOGGER = Logger.getLogger(Document.class
+ .toString());
+
+ private final List<IPage> pages;
+
+ private final PDDocument pdfDocument;
+
+ private final PageDrawer pageDrawer;
+
+ /**
+ * Default Constructor.
+ *
+ * @param underlayingDocument
+ * Document this document is based on.
+ * @param pgDrawer
+ * a PageDrawer object.
+ */
+ private Document(final PDDocument underlayingDocument,
+ final PageDrawer pgDrawer) {
+ this.pages = new ArrayList<IPage>();
+ this.pdfDocument = underlayingDocument;
+ this.pageDrawer = pgDrawer;
+ }
+
+ /** {@inheritDoc} */
+ public List<IPage> getPages() {
+ return Collections.unmodifiableList(this.pages);
+ }
+
+ /**
+ * Create an empty document.
+ *
+ * @return an empty Document with one page.
+ */
+ public static Document emptyDocument() {
+ PDDocument pddoc;
+ PageDrawer pgDrawer;
+ try {
+ pddoc = new PDDocument();
+ pgDrawer = new PageDrawer();
+ } catch (final IOException io) {
+ Document.LOGGER.log(Level.WARNING,
+ "Failed to base Document on PDF", io);
+ pddoc = null;
+ pgDrawer = null;
+ }
+ final Document d = new Document(pddoc, pgDrawer);
+ d.addEmptyPage();
+ return d;
+ }
+
+ /**
+ * Add an empty page to the document.
+ */
+ private void addEmptyPage() {
+ final Page p = new Page();
+ if (this.pdfDocument != null) {
+ final Dimension2D pgDimension = p.getPageSize();
+ final Dimension pageDimension = new Dimension((int) pgDimension
+ .getWidth(), (int) pgDimension.getHeight());
+ final PDPage pdPage = new PDPage();
+ this.pdfDocument.addPage(pdPage);
+ final ILayer pdfLayer = new PDFLayer(this.pageDrawer, pdPage,
+ pageDimension);
+ p.addLayer(pdfLayer);
+ }
+ this.pages.add(p);
+ }
+
+ /**
+ * Create a new Document from a given PDF file.
+ *
+ * @param filename
+ * file to open
+ * @return a Document instance.
+ * @throws IOException
+ * if the document could not be loaded.
+ */
+ public static Document fromPDF(final String filename) throws IOException {
+ final PDDocument pddoc = PDDocument.load(filename);
+ final PageDrawer drawer = new PageDrawer();
+ final Document d = new Document(pddoc, drawer);
+
+ final List<?> pages = pddoc.getDocumentCatalog().getAllPages();
+
+ for (final Object pg : pages) {
+ if (pg instanceof PDPage) {
+ final PDPage pdpage = (PDPage) pg;
+ Document.removeMenyaLayers(pdpage, pddoc);
+ Document.createMenyaPage(drawer, d, pdpage);
+ } else {
+ Document.LOGGER.warning("Unknown Class in PageList: "
+ + pg.getClass());
+ }
+ }
+ return d;
+ }
+
+ /**
+ * @param pdpage
+ */
+ private static void removeMenyaLayers(final PDPage pdpage,
+ final PDDocument pddoc) throws IOException {
+ try {
+ final List<?> tokens = pdpage.getContents().getStream()
+ .getStreamTokens();
+ final Deque<COSBase> arguments = new LinkedList<COSBase>();
+ final PDStream pds = new PDStream(pddoc);
+ pds.addCompression();
+ final OutputStream os = pds.createOutputStream();
+ final COSWriter writer = new COSWriter(os);
+
+ boolean invisa = false;
+ for (final Object t : tokens) {
+ if (t instanceof COSBase) {
+ arguments.addLast((COSBase) t);
+ } else if (t instanceof PDFOperator) {
+ final PDFOperator o = (PDFOperator) t;
+ if ("BDC".equals(o.getOperation())) {
+ // TODO: This filters ALL Layers, but it should only
+ // filter menya layers.
+ arguments.clear();
+ invisa = true;
+ }
+ if (!invisa) {
+ while (!arguments.isEmpty()) {
+ final COSBase b = arguments.removeFirst();
+ b.accept(writer);
+ os.write(COSWriter.SPACE);
+ }
+ os.write(o.getOperation().getBytes());
+ os.write(COSWriter.SPACE);
+ }
+ if ("EMC".equals(o.getOperation())) {
+ invisa = false;
+ }
+ } else {
+ Document.LOGGER.warning("Unsupported Token: "
+ + t.getClass());
+ }
+ }
+ writer.close();
+ pdpage.setContents(pds);
+ } catch (final COSVisitorException e) {
+ throw new IOException("Error filtering ContentStream", e);
+ }
+ }
+
+ /**
+ * @param drawer
+ * @param d
+ * @param pdpage
+ */
+ private static void createMenyaPage(final PageDrawer drawer,
+ final Document d, final PDPage pdpage) throws IOException {
+ final PDRectangle pageSize = pdpage.findMediaBox();
+ final int rotation = pdpage.findRotation();
+ Dimension pageDimension = pageSize.createDimension();
+ if (rotation == Document.LANDSCAPE_1
+ || rotation == Document.LANDSCAPE_2) {
+ pageDimension = new Dimension(pageDimension.height,
+ pageDimension.width);
+ // TODO : check rotation = 0 || 180
+ }
+ final Page menyaPage = new Page();
+ menyaPage.setPageSize(pageDimension);
+ final ILayer pdfLayer = new PDFLayer(drawer, pdpage, pageDimension);
+ menyaPage.addLayer(pdfLayer);
+ Document.extractSerializedLayers(pdpage, menyaPage);
+ d.pages.add(menyaPage);
+ }
+
+ /**
+ * @param pdpage
+ * @param menyaPage
+ */
+ private static void extractSerializedLayers(final PDPage pdpage,
+ final Page menyaPage) throws IOException {
+ // TODO: Check LastModified to ensure menya metadata is still current.
+ try {
+ final COSDictionary pieceInfo = Document.getPieceInfo(pdpage);
+ final COSDictionary menyaDict = Document.getAndCreateDict(
+ pieceInfo, Document.PDF_MENYA_DICT);
+ final COSDictionary privateDict = Document.getAndCreateDict(
+ menyaDict, Document.PDF_PRIVATE);
+ int i = 0;
+ COSBase cb = privateDict.getDictionaryObject(Document
+ .getLayerName(i));
+ while (cb instanceof COSString) {
+ final COSString cs = (COSString) cb;
+ final byte[] buf = cs.getBytes();
+ final ByteArrayInputStream bis = new ByteArrayInputStream(buf);
+ final ObjectInputStream ois = new ObjectInputStream(bis);
+ final ILayer layer = (ILayer) ois.readObject();
+ menyaPage.addLayer(layer);
+ i++;
+ cb = privateDict.getDictionaryObject(Document.getLayerName(i));
+ }
+ } catch (final ClassNotFoundException e) {
+ throw new IOException("Failed to read embedded Menya Layer", e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void close() {
+ if (this.pdfDocument != null) {
+ try {
+ this.pdfDocument.close();
+ } catch (final IOException e) {
+ Document.LOGGER.log(Level.WARNING,
+ "Failed to close PDFDocument", e);
+ }
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void toPDF(final String filename) throws IOException {
+ if (this.pdfDocument == null) {
+ throw new IOException("Document is not based on a PDF");
+ }
+ try {
+ final Calendar now = Calendar.getInstance();
+ for (final IPage page : this.pages) {
+ final List<ILayer> menyaLayers = new ArrayList<ILayer>();
+ final PDFLayer pdfLayer = this.findPDFLayer(page, menyaLayers);
+ if (pdfLayer == null) {
+ throw new IOException(
+ "Failed to find PDF Layer in all pages");
+ }
+ Document.storeMenyaLayers(now, menyaLayers, pdfLayer,
+ this.pdfDocument, page);
+ }
+ this.pdfDocument.save(filename);
+ } catch (final COSVisitorException e) {
+ throw new IOException("Failure during save as PDF", e);
+ }
+ }
+
+ /**
+ * @param now
+ * @param menyaLayers
+ * @param pdfLayer
+ * @throws IOException
+ */
+ private static void storeMenyaLayers(final Calendar now,
+ final List<ILayer> menyaLayers, final PDFLayer pdfLayer,
+ final PDDocument pddoc, final IPage page) throws IOException {
+ final PDPage pdpage = pdfLayer.getPage();
+ Document.storeGraphicalMenyaData(menyaLayers, pdpage, pddoc, page);
+ Document.storeSerializedMenyaData(now, menyaLayers, pdpage);
+ }
+
+ /**
+ * @param menyaLayers
+ * @param pdpage
+ * @throws IOException
+ */
+ private static void storeGraphicalMenyaData(final List<ILayer>
menyaLayers,
+ final PDPage pdpage, final PDDocument pddoc, final IPage page)
+ throws IOException {
+ final COSDictionary ocg = Document.createMenyaPDFLayers(pddoc);
+ if (pdpage.getResources() == null) {
+ pdpage.setResources(new PDResources());
+ }
+ final COSDictionary properties = Document.getAndCreateDict(pdpage
+ .getResources().getCOSDictionary(), "Properties");
+ properties.setItem("MC0", ocg);
+
+ final PDPageContentStream contentStream;
+ if (pdpage.getContents() == null) {
+ contentStream = new PDPageContentStream(pddoc, pdpage, false, true);
+ } else {
+ contentStream = new PDPageContentStream(pddoc, pdpage, true, true);
+ }
+ contentStream.appendRawCommands("/OC /MC0 BDC ");
+
+ // TODO: One layer for each menya layer.
+ for (final ILayer layer : menyaLayers) {
+ layer.toPdf(contentStream, page);
+ }
+
+ contentStream.appendRawCommands(" EMC");
+ contentStream.close();
+
+ }
+
+ /**
+ * @param pddoc
+ */
+ private static COSDictionary createMenyaPDFLayers(final PDDocument pddoc)
{
+ final COSArray intentArray = new COSArray();
+ intentArray.add(COSName.getPDFName("View"));
+ intentArray.add(COSName.getPDFName("Design"));
+ final COSDictionary ocg = new COSDictionary();
+ ocg.setName("Type", "OCG");
+ ocg.setString("Name", "Layer 1");
+ ocg.setItem("Intent", intentArray);
+
+ final COSDictionary ocp = Document.getAndCreateDict(pddoc
+ .getDocumentCatalog().getCOSDictionary(), "OCProperties");
+ final COSDictionary d = Document.getAndCreateDict(ocp, "D");
+ final COSArray order = Document.getAndCreateArray(d, "Order");
+ order.add(ocg);
+ final COSArray on = Document.getAndCreateArray(d, "ON");
+ on.add(ocg);
+ final COSArray ocgs = Document.getAndCreateArray(ocp, "OCGs");
+ ocgs.add(ocg);
+ return ocg;
+ }
+
+ /**
+ * @param now
+ * @param menyaLayers
+ * @param pdpage
+ * @throws IOException
+ */
+ private static void storeSerializedMenyaData(final Calendar now,
+ final List<ILayer> menyaLayers, final PDPage pdpage)
+ throws IOException {
+ final COSDictionary pieceInfo = Document.getPieceInfo(pdpage);
+ final COSDictionary menyaDict = Document.getAndCreateDict(pieceInfo,
+ Document.PDF_MENYA_DICT);
+ pdpage.getCOSDictionary().setDate(Document.PDF_LAST_MODIFIED, now);
+ menyaDict.setDate(Document.PDF_LAST_MODIFIED, now);
+ final COSDictionary privateDict = Document.getAndCreateDict(menyaDict,
+ Document.PDF_PRIVATE);
+
+ privateDict.clear();
+ for (int i = 0; i < menyaLayers.size(); i++) {
+ final String name = Document.getLayerName(i);
+ final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ final ObjectOutputStream oos = new ObjectOutputStream(bos);
+ oos.writeObject(menyaLayers.get(i));
+ oos.close();
+ privateDict.setItem(name, new COSString(bos.toByteArray()));
+ }
+ }
+
+ /**
+ * @param index
+ * @return
+ */
+ private static String getLayerName(final int index) {
+ return new StringBuilder(Document.PDF_LAYER_PREFIX).append(index)
+ .toString();
+ }
+
+ /**
+ * @param page
+ * @param menyaLayers
+ * @return
+ * @throws IOException
+ */
+ private PDFLayer findPDFLayer(final IPage page,
+ final List<ILayer> menyaLayers) throws IOException {
+ PDFLayer pdfLayer = null;
+ for (final ILayer layer : page.getLayers()) {
+ if (layer instanceof PDFLayer) {
+ pdfLayer = (PDFLayer) layer;
+ } else if (layer instanceof Serializable) {
+ menyaLayers.add(layer);
+ } else {
+ throw new IOException("Not all layers are Serializable");
+ }
+ }
+ return pdfLayer;
+ }
+
+ private static COSDictionary getAndCreateDict(final COSDictionary parent,
+ final String name) {
+ COSDictionary dict = (COSDictionary) parent.getDictionaryObject(name);
+ if (dict == null) {
+ dict = new COSDictionary();
+ parent.setItem(name, dict);
+ }
+ return dict;
+ }
+
+ private static COSArray getAndCreateArray(final COSDictionary parent,
+ final String name) {
+ COSArray a = (COSArray) parent.getItem(COSName.getPDFName(name));
+ if (a == null) {
+ a = new COSArray();
+ parent.setItem(name, a);
+ }
+ return a;
+ }
+
+ private static COSDictionary getPieceInfo(final PDPage page) {
+ return Document.getAndCreateDict(page.getCOSDictionary(),
+ Document.PDF_PIECE_INFO);
+ }
}
=======================================
--- /src/main/java/menya/core/model/IWorkingTool.java Wed Aug 5 15:32:38
2009
+++ /src/main/java/menya/core/model/IWorkingTool.java Sun Aug 9 01:45:08
2009
@@ -28,17 +28,27 @@
public interface IWorkingTool {
/**
- * retrieve all properties of this working tool.
+ * retrieves all processors of this working tool.
*
- * @return a set of properties
+ * @see IProcessor
+ * @return
*/
- public Set<IWorkingToolProperty<?>> getProperties();
+ public Set<IProcessor> getProcessors();
/**
- * retrieves all processors of this working tool.
+ * should implement a pressure function denoted as:
*
- * @see IProcessor
+ * <pre>
+ * f : [0..1] -> [0..1]
+ * </pre>
+ *
+ * @param levelValue
* @return
*/
- public Set<IProcessor> getProcessors();
-}
+ public float applyPressureFunction(float levelValue);
+
+ /**
+ * @return
+ */
+ public float getMaxWidth();
+}
=======================================
--- /src/main/java/menya/core/model/Page.java Wed Aug 5 15:01:06 2009
+++ /src/main/java/menya/core/model/Page.java Sun Aug 9 01:45:08 2009
@@ -19,6 +19,8 @@
import java.awt.geom.Dimension2D;
import java.util.ArrayDeque;
import java.util.Deque;
+import java.util.LinkedList;
+import java.util.List;
import menya.core.Constants;
import menya.core.document.ILayer;
@@ -33,74 +35,114 @@
*/
public class Page implements IPage {
- /**
+ /**
*
*/
- private static final double A4_HEIGHT = 29.7;
-
- /**
+ private static final double A4_HEIGHT = 29.7;
+
+ /**
*
*/
- private static final double A4_WIDTH = 21.0;
-
- private final ArrayDeque<ILayer> layers;
-
- // 210 mm x 297 mm is A4
- private Dimension2D size = new Dimension(
- (int) (Page.A4_WIDTH * Constants.CM_TO_PT),
- (int) (Page.A4_HEIGHT * Constants.CM_TO_PT));
-
- /**
- * Default Constructor.
- */
- public Page() {
- this.layers = new ArrayDeque<ILayer>();
- }
-
- /** {@inheritDoc} */
- public ILayer getBackground() {
- return this.layers.peekFirst();
- }
-
- /** {@inheritDoc} */
- public Deque<ILayer> getLayers() {
- return this.layers.clone();
- }
-
- /** {@inheritDoc} */
- public CurveLayer getActiveLayer() {
- final ILayer top = this.layers.peekLast();
- if (top instanceof CurveLayer) {
- return (CurveLayer) top;
- } else {
- final CurveLayer c = new CurveLayer();
- this.layers.add(c);
- return c;
- }
- }
-
- /** {@inheritDoc} */
- public Dimension2D getPageSize() {
- return this.size;
- }
-
- /**
- * Setter for page size.
- *
- * @param newSize
- * the new Page size.
- */
- public void setPageSize(final Dimension2D newSize) {
- this.size = (Dimension2D) newSize.clone();
- }
-
- /**
- * Add a new layer on top of this page.
- *
- * @param layer
- * the new layer.
- */
- public void addLayer(final ILayer layer) {
- this.layers.add(layer);
- }
-}
+ private static final double A4_WIDTH = 21.0;
+
+ private final ArrayDeque<ILayer> layers;
+
+ // 210 mm x 297 mm is A4
+ private Dimension2D size = new Dimension(
+ (int) (Page.A4_WIDTH * Constants.CM_TO_PT),
+ (int) (Page.A4_HEIGHT * Constants.CM_TO_PT));
+
+ /**
+ * Default Constructor.
+ */
+ public Page() {
+ this.layers = new ArrayDeque<ILayer>();
+ }
+
+ /** {@inheritDoc} */
+ public ILayer getBackground() {
+ return this.layers.peekFirst();
+ }
+
+ /** {@inheritDoc} */
+ public Deque<ILayer> getLayers() {
+ return this.layers.clone();
+ }
+
+ /** {@inheritDoc} */
+ public CurveLayer getActiveLayer() {
+ final ILayer top = this.layers.peekLast();
+ if (top instanceof CurveLayer) {
+ return (CurveLayer) top;
+ } else {
+ final CurveLayer c = new CurveLayer();
+ this.layers.add(c);
+ return c;
+ }
+ }
+
+ /** {@inheritDoc} */
+ public Dimension2D getPageSize() {
+ return this.size;
+ }
+
+ /**
+ * Setter for page size.
+ *
+ * @param newSize
+ * the new Page size.
+ */
+ public void setPageSize(final Dimension2D newSize) {
+ this.size = (Dimension2D) newSize.clone();
+ }
+
+ /**
+ * Add a new layer on top of this page.
+ *
+ * @param layer
+ * the new layer.
+ */
+ public void addLayer(final ILayer layer) {
+ this.layers.add(layer);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see menya.core.document.IPage#getAllPens()
+ */
+ @Override
+ public final List<IWorkingTool> getAllPens() {
+ List<IWorkingTool> pens = new LinkedList<IWorkingTool>();
+ for (ILayer l : getLayers()) {
+ pens.addAll(l.getAllPens());
+ }
+ return pens;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see menya.core.document.IPage#getDefaultPen()
+ */
+ @Override
+ public final IWorkingTool getDefaultPen() {
+ return getActiveLayer().getDefaultPen();
+ }
+
+ @Override
+ public final IWorkingTool getActivePen() {
+ return getActiveLayer().getActivePen();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * menya.core.document.IPage#setActivePen(menya.core.model.IWorkingTool)
+ */
+ @Override
+ public void setActivePen(IWorkingTool pen) throws
IllegalArgumentException {
+ getActiveLayer().setActivePen(pen);
+ }
+}
=======================================
--- /src/main/java/menya/core/model/tools/AWorkingTool.java Wed Aug 5
15:41:36 2009
+++ /src/main/java/menya/core/model/tools/AWorkingTool.java Sun Aug 9
01:45:08 2009
@@ -22,7 +22,6 @@
import menya.core.model.IProcessor;
import menya.core.model.IWorkingTool;
-import menya.core.model.IWorkingToolProperty;
/**
* @author dominik
@@ -32,7 +31,14 @@
private Set<IProcessor> processors = new TreeSet<IProcessor>();
- private Set<IWorkingToolProperty<?>> properties = new
TreeSet<IWorkingToolProperty<?>>();
+ private float maxWidth;
+
+ /**
+ *
+ */
+ public AWorkingTool() {
+ setupInternal();
+ }
/**
* you should setup this pens processors and properties by implementing
this
@@ -40,6 +46,24 @@
*/
protected abstract void setup();
+ private void setupInternal() {
+ loadDefaultFields();
+ loadDefaultProperties();
+ setup();
+ }
+
+ /**
+ *
+ */
+ private void loadDefaultFields() {
+ maxWidth = 5.0f;
+ // TODO add more fields
+ }
+
+ private void loadDefaultProperties() {
+ // TODO
+ }
+
/**
* replaces all prior added processors with the provided processors.
*
@@ -58,26 +82,6 @@
protected final void addProcessor(IProcessor p) {
this.processors.add(p);
}
-
- /**
- * replaces all prior added properties with the provided properties.
- *
- * @param properties
- */
- protected final void setProperties(
- Collection<IWorkingToolProperty<?>> properties) {
- this.properties.clear();
- this.properties.addAll(properties);
- }
-
- /**
- * adds a property.
- *
- * @param p
- */
- protected final void addProperty(IWorkingToolProperty<?> p) {
- this.properties.add(p);
- }
/*
* (non-Javadoc)
@@ -88,19 +92,29 @@
public final Set<IProcessor> getProcessors() {
return Collections.unmodifiableSet(processors);
}
+
+ /**
+ * is a implementation of the defined method that applies a identity
+ * function to the pressure measured.
+ *
+ * @see menya.core.model.IWorkingTool#applyPressureFunction(float)
+ */
+ @Override
+ public float applyPressureFunction(float levelValue) {
+ return levelValue;
+ }
/*
* (non-Javadoc)
*
- * @see menya.core.model.IWorkingTool#getProperties()
+ * @see menya.core.model.IWorkingTool#getMaxWidth()
*/
@Override
- public final Set<IWorkingToolProperty<?>> getProperties() {
- return Collections.unmodifiableSet(properties);
+ public float getMaxWidth() {
+ return maxWidth;
}
- public final boolean hasProperty(IWorkingToolProperty<?> p) {
- return properties.contains(p);
- }
-
-}
+ protected void setMaxWidth(float width) {
+ this.maxWidth = width;
+ }
+}
=======================================
--- /src/main/java/menya/gui/SketchPane.java Thu Aug 6 02:45:34 2009
+++ /src/main/java/menya/gui/SketchPane.java Sun Aug 9 01:45:08 2009
@@ -24,6 +24,7 @@
import java.awt.geom.Dimension2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
+import java.util.logging.Logger;
import javax.swing.JComponent;
@@ -50,174 +51,203 @@
*/
public class SketchPane extends JComponent {
- /**
+ /**
+ * Logger for this class.
+ */
+ private static final Logger LOGGER = Logger.getLogger(SketchPane.class
+ .toString());
+
+ /**
*
*/
- private static final long serialVersionUID = 1L;
-
- private static final float MAX_PEN_WIDTH = 5.0f;
-
- private static final float DEFAULT_PRESSURE = 0.5f;
-
- private final IPage currentPage;
-
- private final CurveLayer activeLayer;
-
- private Curve currentCurve;
-
- private BufferedImage cachedImage;
-
- /**
- * Default constructor.
- *
- * @param page
- * the Page to display in this pane.
- */
- public SketchPane(final IPage page) {
- this.currentPage = page;
- this.activeLayer = page.getActiveLayer();
- // this.addMouseListener(this);
- // this.addMouseMotionListener(this);
-
- final PenManager penManager = new PenManager(this);
- penManager.pen.addListener(new PenAdapter() {
- @Override
- public void penLevelEvent(final PLevelEvent ev) {
- SketchPane.this.penLevelEvent(ev);
- }
-
- @Override
- public void penButtonEvent(final PButtonEvent ev) {
- SketchPane.this.penButtonEvent(ev);
- }
- });
- this.setSize(this.getPreferredSize());
- }
-
- /** {@inheritDoc} */
- @Override
- protected void paintComponent(final Graphics g) {
- super.paintComponent(g);
-
- for (final ILayer l : this.currentPage.getLayers()) {
- if (l.hasChanged()) {
- this.cachedImage = null;
- }
- }
- if (this.cachedImage == null) {
- final Dimension2D pageSize = this.currentPage.getPageSize();
- final BufferedImage img = new BufferedImage((int) Math
- .ceil(pageSize.getWidth()), (int) Math.ceil(pageSize
- .getHeight()), BufferedImage.TYPE_INT_RGB);
-
- final Graphics2D g2dImage = img.createGraphics();
- g2dImage.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
- RenderingHints.VALUE_ANTIALIAS_ON);
- g2dImage.setColor(Color.WHITE);
- g2dImage.fill(new Rectangle2D.Double(0, 0, pageSize.getWidth(),
- pageSize.getHeight()));
-
- for (final ILayer l : this.currentPage.getLayers()) {
- for (final GraphicalData gd : l.getGraphicalData()) {
- gd.draw(g2dImage);
- }
- }
- this.cachedImage = img;
- }
-
- final Graphics2D g2dReal = (Graphics2D) g;
- g2dReal.drawImage(this.cachedImage, null, 0, 0);
- g2dReal.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
- RenderingHints.VALUE_ANTIALIAS_ON);
-
- if (this.currentCurve != null) {
- this.currentCurve.draw(g2dReal);
- }
- }
-
- private Dimension dim2DtoDim(final Dimension2D d2d) {
- return new Dimension((int) Math.ceil(d2d.getWidth()), (int) Math
- .ceil(d2d.getHeight()));
- }
-
- /** {@inheritDoc} */
- @Override
- public Dimension getMinimumSize() {
- return this.getPreferredSize();
- }
-
- /** {@inheritDoc} */
- @Override
- public Dimension getMaximumSize() {
- return this.getPreferredSize();
- }
-
- /** {@inheritDoc} */
- @Override
- public Dimension getPreferredSize() {
- return this.dim2DtoDim(this.currentPage.getPageSize());
- }
-
- /** {@inheritDoc} */
- public void penButtonEvent(final PButtonEvent ev) {
- final PButton button = ev.button;
- if (PButton.Type.LEFT.equals(button.getType())) {
- final Point p = this.toPoint(ev.pen);
-
- if (button.value) {
- this.startCurve(p);
- } else {
- this.stopCurve(p);
- }
- }
- }
-
- private void stopCurve(final Point p) {
- if (this.currentCurve == null) {
- return;
- }
- this.currentCurve.add(p);
- this.currentCurve.smoothPath();
- this.activeLayer.addCurve(this.currentCurve);
- this.currentCurve = null;
- // TODO: Maybe erase path that was drawn during drag.
- this.repaint();
- }
-
- private void startCurve(final Point p) {
- this.currentCurve = new Curve();
- this.currentCurve.add(p);
- }
-
- private Point toPoint(final Pen pen) {
- final float posx = pen.getLevelValue(Type.X);
- final float posy = pen.getLevelValue(Type.Y);
- final float pressure;
- if (PKind.Type.STYLUS.equals(pen.getKind().getType())) {
- pressure = pen.getLevelValue(Type.PRESSURE);
- } else {
- pressure = SketchPane.DEFAULT_PRESSURE;
- }
- // TODO: Improve!
- return new Point(posx, posy, pressure * SketchPane.MAX_PEN_WIDTH);
- }
-
- /** {@inheritDoc} */
- public void penLevelEvent(final PLevelEvent ev) {
- if (this.currentCurve == null) {
- return;
- }
- final Point newP = this.toPoint(ev.pen);
- // final Point old = this.currentPath.get(this.currentPath.size()
- 1);
- // if (newP.distanceTo(old) > 10.0) {
- this.currentCurve.add(newP);
- // }
- this.repaint();
- }
-
- /** {@inheritDoc} */
- public void mouseMoved(final MouseEvent arg0) {
- // ignore this event.
- }
+ private static final long serialVersionUID = 1L;
+
+ private static final float DEFAULT_PRESSURE = 0.5f;
+
+ private final IPage currentPage;
+
+ private final CurveLayer activeLayer;
+
+ private Curve currentCurve;
+
+ private BufferedImage cachedImage;
+
+ /**
+ * Default constructor.
+ *
+ * @param page
+ * the Page to display in this pane.
+ */
+ public SketchPane(final IPage page) {
+ this.currentPage = page;
+ this.activeLayer = page.getActiveLayer();
+ // this.addMouseListener(this);
+ // this.addMouseMotionListener(this);
+
+ final PenManager penManager = new PenManager(this);
+ penManager.pen.addListener(new PenAdapter() {
+ @Override
+ public void penLevelEvent(final PLevelEvent ev) {
+ SketchPane.this.penLevelEvent(ev);
+ }
+
+ @Override
+ public void penButtonEvent(final PButtonEvent ev) {
+ SketchPane.this.penButtonEvent(ev);
+ }
+ });
+ this.setSize(this.getPreferredSize());
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected void paintComponent(final Graphics g) {
+ super.paintComponent(g);
+
+ for (final ILayer l : this.currentPage.getLayers()) {
+ if (l.hasChanged()) {
+ this.cachedImage = null;
+ }
+ }
+ if (this.cachedImage == null) {
+ final Dimension2D pageSize = this.currentPage.getPageSize();
+ final BufferedImage img = new BufferedImage((int) Math
+ .ceil(pageSize.getWidth()), (int) Math.ceil(pageSize
+ .getHeight()), BufferedImage.TYPE_INT_RGB);
+
+ final Graphics2D g2dImage = img.createGraphics();
+ g2dImage.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+ RenderingHints.VALUE_ANTIALIAS_ON);
+ g2dImage.setColor(Color.WHITE);
+ g2dImage.fill(new Rectangle2D.Double(0, 0, pageSize.getWidth(),
+ pageSize.getHeight()));
+
+ for (final ILayer l : this.currentPage.getLayers()) {
+ for (final GraphicalData gd : l.getGraphicalData()) {
+ gd.draw(g2dImage);
+ }
+ }
+ this.cachedImage = img;
+ }
+
+ final Graphics2D g2dReal = (Graphics2D) g;
+ g2dReal.drawImage(this.cachedImage, null, 0, 0);
+ g2dReal.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+ RenderingHints.VALUE_ANTIALIAS_ON);
+
+ if (this.currentCurve != null) {
+ this.currentCurve.draw(g2dReal);
+ }
+ }
+
+ private Dimension dim2DtoDim(final Dimension2D d2d) {
+ return new Dimension((int) Math.ceil(d2d.getWidth()), (int) Math
+ .ceil(d2d.getHeight()));
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Dimension getMinimumSize() {
+ return this.getPreferredSize();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Dimension getMaximumSize() {
+ return this.getPreferredSize();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Dimension getPreferredSize() {
+ return this.dim2DtoDim(this.currentPage.getPageSize());
+ }
+
+ /** {@inheritDoc} */
+ public void penButtonEvent(final PButtonEvent ev) {
+ if (currentPage.getActiveLayer().isEditable()) {
+ final PButton button = ev.button;
+ if (PButton.Type.LEFT.equals(button.getType())) {
+ final Point p = this.toPoint(ev.pen);
+
+ if (button.value) {
+ this.startCurve(p);
+ } else {
+ this.stopCurve(p);
+ }
+ }
+ } else {
+ // do nothing
+ LOGGER.finer("This layer (" + currentPage.getActiveLayer()
+ + ") is not editable.");
+ }
+ }
+
+ private void stopCurve(final Point p) {
+ if (this.currentCurve == null) {
+ return;
+ }
+ this.currentCurve.add(p);
+ // TODO: Smooth Path
+ this.activeLayer.addCurve(this.currentCurve);
+ this.currentCurve = null;
+ // TODO: Maybe erase path that was drawn during drag.
+ this.repaint();
+ }
+
+ private void startCurve(final Point p) {
+ this.currentCurve = new Curve();
+ this.currentCurve.add(p);
+ }
+
+ private Point toPoint(final Pen pen) {
+ if (currentPage.getActiveLayer().isEditable()) {
+ final float posx = pen.getLevelValue(Type.X);
+ final float posy = pen.getLevelValue(Type.Y);
+ final float pressure;
+ if (PKind.Type.STYLUS.equals(pen.getKind().getType())) {
+ pressure = currentPage.getActivePen().applyPressureFunction(
+ pen.getLevelValue(Type.PRESSURE));
+ } else {
+ pressure = currentPage.getActivePen().applyPressureFunction(
+ SketchPane.DEFAULT_PRESSURE);
+ }
+ // TODO: Improve!
+ return new Point(posx, posy, pressure
+ * currentPage.getActivePen().getMaxWidth());
+ } else {
+ // XXX possible source for a nullpointerexception
+ LOGGER
+ .warning("This layer ("
+ + currentPage.getActiveLayer()
+ + ") is not editable. This case should be catched before as at this
point I can only return null (possible nullpointer exception source).");
+ return null;
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void penLevelEvent(final PLevelEvent ev) {
+ if (currentPage.getActiveLayer().isEditable()) {
+ if (this.currentCurve == null) {
+ return;
+ }
+ final Point newP = this.toPoint(ev.pen);
+ // final Point old = this.currentPath.get(this.currentPath.size() -
+ // 1);
+ // if (newP.distanceTo(old) > 10.0) {
+ this.currentCurve.add(newP);
+ // }
+ } else {
+ // do nothing
+ LOGGER.finer("This layer (" + currentPage.getActiveLayer()
+ + ") is not editable.");
+ }
+ this.repaint();
+ }
+
+ /** {@inheritDoc} */
+ public void mouseMoved(final MouseEvent arg0) {
+ // ignore this event.
+ }
}
==============================================================================
Revision: 6fa91d1d44
Author: dom...@sashimi.telesystem.com
Date: Sun Aug 9 01:48:06 2009
Log: asdf
http://code.google.com/p/menya/source/detail?r=6fa91d1d44
Added:
/src/main/java/menya/core/model/tools/StandardPen.java
Deleted:
/src/main/java/menya/core/model/tools/Pen.java
=======================================
--- /dev/null
+++ /src/main/java/menya/core/model/tools/StandardPen.java Sun Aug 9
01:48:06 2009
@@ -0,0 +1,34 @@
+/*
+ * This file is part of Menya.
+ *
+ * Menya 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.
+ *
+ * Menya 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
+ * Menya. If not, see <http://www.gnu.org/licenses/>.
+ */
+package menya.core.model.tools;
+
+/**
+ * @author dominik
+ *
+ */
+public class StandardPen extends AWorkingTool {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see menya.core.model.tools.AWorkingTool#setup()
+ */
+ @Override
+ protected void setup() {
+ // this general pen has no processors
+ }
+
+}
=======================================
--- /src/main/java/menya/core/model/tools/Pen.java Wed Aug 5 15:41:36 2009
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * This file is part of Menya.
- *
- * Menya 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.
- *
- * Menya 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
- * Menya. If not, see <http://www.gnu.org/licenses/>.
- */
-package menya.core.model.tools;
-
-import java.awt.Color;
-
-import menya.core.model.properties.ColorProperty;
-import menya.core.model.properties.PropertyConstants;
-
-/**
- * @author dominik
- *
- */
-public class Pen extends AWorkingTool {
-
- /*
- * (non-Javadoc)
- *
- * @see menya.core.model.tools.AWorkingTool#setup()
- */
- @Override
- protected void setup() {
- // this general pen has no processors
-
- // set property "default color"
- addProperty(new ColorProperty(PropertyConstants.DEFAULT_COLOR,
- Color.BLACK));
- }
-
-}