]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.utils/src/org/simantics/utils/page/PageDesc.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.utils / src / org / simantics / utils / page / PageDesc.java
index 71ab015628f6f5b5e6477adcc09a80b2cc21c2f3..08d1f2dd169dc2ae1ef484481bfafd945ce52520 100644 (file)
-/*******************************************************************************\r
- * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
- * in Industry THTH ry.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- *     VTT Technical Research Centre of Finland - initial API and implementation\r
- *******************************************************************************/\r
-package org.simantics.utils.page;\r
-\r
-import java.awt.geom.Rectangle2D;\r
-import java.math.BigDecimal;\r
-import java.util.NoSuchElementException;\r
-import java.util.StringTokenizer;\r
-\r
-import org.simantics.utils.page.MarginUtils;\r
-import org.simantics.utils.page.MarginUtils.Margin;\r
-import org.simantics.utils.page.MarginUtils.Margins;\r
-\r
-/**\r
- * @see http://www.cl.cam.ac.uk/~mgk25/iso-paper.html for ISO paper dimensions\r
- * \r
- * TODO: use DataType 0.4 for string serialization of PageDesc\r
- */\r
-public class PageDesc {\r
-\r
-    public static int toMillimeters(double points) {\r
-        return (int) Math.round(points * (25.4/72.));\r
-    }\r
-\r
-    public static int toPoints(double millimeters) {\r
-        return (int) Math.round(millimeters* (72./25.4));\r
-    }\r
-\r
-    public static final PageDesc  INFINITE = new PageDesc("Infinite", PageOrientation.Portrait, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);\r
-    public static final PageDesc  A0                   = new PageDesc("A0", PageOrientation.Portrait, 841, 1189);\r
-    public static final PageDesc  A1                   = new PageDesc("A1", PageOrientation.Portrait, 594, 841);\r
-    public static final PageDesc  A2                   = new PageDesc("A2", PageOrientation.Portrait, 420, 594);\r
-    public static final PageDesc  A3                   = new PageDesc("A3", PageOrientation.Portrait, 297, 420);\r
-    public static final PageDesc  A4                   = new PageDesc("A4", PageOrientation.Portrait, 210, 297);\r
-    public static final PageDesc  A5                   = new PageDesc("A5", PageOrientation.Portrait, 148, 210);\r
-    public static final PageDesc  A6                   = new PageDesc("A6", PageOrientation.Portrait, 105, 148);\r
-    public static final PageDesc  A7                   = new PageDesc("A7", PageOrientation.Portrait, 74, 105);\r
-    public static final PageDesc  A8                   = new PageDesc("A8", PageOrientation.Portrait, 52, 74);\r
-    public static final PageDesc  A9                   = new PageDesc("A9", PageOrientation.Portrait, 37, 52);\r
-    public static final PageDesc  A10                  = new PageDesc("A10", PageOrientation.Portrait, 26, 37);\r
-    public static final PageDesc[]     A = { A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10 };\r
-    public static final PageDesc[]     items    = { INFINITE, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10 };\r
-    /** List of PDF usable formats. A sub-set of items. */\r
-    public static final PageDesc[]     PDF_ITEMS    = { A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10 };\r
-\r
-    public static final PageDesc  DEFAULT  = A4;\r
-\r
-    private final String          text;\r
-\r
-    private final PageOrientation orientation;\r
-\r
-    private final double          widthInMM;\r
-\r
-    private final double          heightInMM;\r
-\r
-    private final PageCentering   centering;\r
-\r
-    private final Margins         margins;\r
-\r
-\r
-    public static PageDesc[] getPredefinedDescriptions() {\r
-        return items;\r
-    }\r
-    \r
-    public static PageDesc getByName(String pageDescName) {\r
-       for (PageDesc item : items) {\r
-               if ( item.getText().equals( pageDescName ) ) return item;\r
-       }\r
-       return null;\r
-    }\r
-\r
-    public static PageDesc getDescription(String identification) {\r
-        for (PageDesc pd : getPredefinedDescriptions()) {\r
-            if (pd.getText().equals(identification))\r
-                return pd;\r
-        }\r
-        return null;\r
-    }\r
-\r
-    public static PageDesc getDescription(String identification, PageOrientation o) {\r
-        for (PageDesc pd : getPredefinedDescriptions()) {\r
-            if (pd.getText().equals(identification))\r
-                return pd.withOrientation(o);\r
-        }\r
-        return null;\r
-    }\r
-\r
-    public static PageDesc getDescription(PageOrientation o, double widthInMM, double heightInMM) {\r
-        for (PageDesc pd : getPredefinedDescriptions()) {\r
-            if (pd.widthInMM == widthInMM && pd.heightInMM == heightInMM)\r
-                return pd.withOrientation(o);\r
-        }\r
-        return new PageDesc("Custom", o, widthInMM, heightInMM);\r
-    }\r
-\r
-\r
-    public PageDesc(String text, PageOrientation o, double widthInMM, double heightInMM) {\r
-        this(text, o, PageCentering.TopLeftAtOrigin, widthInMM, heightInMM);\r
-    }\r
-\r
-    public String toRepr() {\r
-        return text + ":" + orientation + ":" + widthInMM + ":" + heightInMM\r
-                + ":" + margins.top.diagramAbsolute\r
-                + ":" + margins.bottom.diagramAbsolute\r
-                + ":" + margins.left.diagramAbsolute\r
-                + ":" + margins.right.diagramAbsolute; \r
-    }\r
-    \r
-    public static PageDesc fromRepr(String repr) {\r
-        String[] parts = repr.split(":", 8);\r
-        return new PageDesc(parts[0], PageOrientation.valueOf(parts[1]), \r
-                PageCentering.TopLeftAtOrigin,\r
-                Double.valueOf(parts[2]), Double.valueOf(parts[3]),\r
-                new Margins(\r
-                        MarginUtils.marginOf(0, 0, Double.valueOf(parts[4])),\r
-                        MarginUtils.marginOf(0, 0, Double.valueOf(parts[5])),\r
-                        MarginUtils.marginOf(0, 0, Double.valueOf(parts[6])),\r
-                        MarginUtils.marginOf(0, 0, Double.valueOf(parts[7]))\r
-                        )\r
-                );\r
-    }\r
-\r
-    public PageDesc(String text, PageOrientation o, PageCentering c, double widthInMM, double heightInMM) {\r
-        this(text, o, c, widthInMM, heightInMM, MarginUtils.NO_MARGINS);\r
-    }\r
-\r
-    public PageDesc(String text, PageOrientation o, PageCentering c, double widthInMM, double heightInMM, Margins margins) {\r
-        if (o == null)\r
-            throw new IllegalArgumentException("null orientation");\r
-\r
-        this.text = text;\r
-        this.orientation = o;\r
-        this.centering = c;\r
-        this.widthInMM = widthInMM;\r
-        this.heightInMM = heightInMM;\r
-        this.margins = margins;\r
-    }\r
-\r
-    public boolean isInfinite() {\r
-        return widthInMM == Double.POSITIVE_INFINITY || heightInMM == Double.POSITIVE_INFINITY;\r
-    }\r
-\r
-    public String getText() {\r
-        return text;\r
-    }\r
-\r
-    public PageOrientation getOrientation() {\r
-        return orientation;\r
-    }\r
-\r
-    public PageCentering getCentering() {\r
-        return centering;\r
-    }\r
-\r
-    public boolean contains(double x, double y) {\r
-        if (isInfinite())\r
-            return true;\r
-\r
-        if (x < 0 || y < 0)\r
-            return false;\r
-        double maxX = getOrientedWidth();\r
-        double maxY = getOrientedHeight();\r
-        if (x > maxX || y > maxY)\r
-            return false;\r
-        return true;\r
-    }\r
-\r
-    /**\r
-     * @return\r
-     */\r
-    public double getLeftEdgePos() {\r
-        if (centering == PageCentering.CenteredAroundOrigin)\r
-            return -getOrientedWidth() * 0.5;\r
-        return 0.0;\r
-    }\r
-\r
-    /**\r
-     * @return\r
-     */\r
-    public double getTopEdgePos() {\r
-        if (centering == PageCentering.CenteredAroundOrigin)\r
-            return -getOrientedHeight() * 0.5;\r
-        return 0.0;\r
-    }\r
-\r
-    /**\r
-     * @return width dimension in millimeters\r
-     */\r
-    public double getWidth() {\r
-        return widthInMM;\r
-    }\r
-\r
-    /**\r
-     * @return height dimension in millimeters\r
-     */\r
-    public double getHeight() {\r
-        return heightInMM;\r
-    }\r
-\r
-    /**\r
-     * @return the margins associated with this page description\r
-     */\r
-    public Margins getMargins() {\r
-        return margins;\r
-    }\r
-\r
-    /**\r
-     * @return width dimension in millimeters with respect to the selected\r
-     *         canvas orientation\r
-     */\r
-    public double getOrientedWidth() {\r
-        if (orientation == PageOrientation.Portrait)\r
-            return widthInMM;\r
-        return heightInMM;\r
-    }\r
-\r
-    /**\r
-     * @return height dimension in millimeters with respect to the selected\r
-     *         canvas orientation\r
-     */\r
-    public double getOrientedHeight() {\r
-        if (orientation == PageOrientation.Portrait)\r
-            return heightInMM;\r
-        return widthInMM;\r
-    }\r
-\r
-    public PageDesc withSizeFrom(PageDesc another) {\r
-        return new PageDesc(text, orientation, centering, another.widthInMM, another.heightInMM, margins);\r
-    }\r
-\r
-    public PageDesc withOrientation(PageOrientation o) {\r
-        if (orientation.equals(o)) {\r
-            return this;\r
-        }\r
-        return new PageDesc(text, o, centering, widthInMM, heightInMM, margins);\r
-    }\r
-\r
-    public PageDesc withCentering(PageCentering c) {\r
-        if (centering.equals(c)) {\r
-            return this;\r
-        }\r
-        return new PageDesc(text, orientation, c, widthInMM, heightInMM, margins);\r
-    }\r
-\r
-    public PageDesc withText(String text) {\r
-        if (this.text.equals(text))\r
-            return this;\r
-        return new PageDesc(text, orientation, centering, widthInMM, heightInMM, margins);\r
-    }\r
-\r
-    public PageDesc withMargins(Margins margins) {\r
-        return new PageDesc(text, orientation, centering, widthInMM, heightInMM, margins);\r
-    }\r
-\r
-    public void getPageRectangle(Rectangle2D r) {\r
-        if (r == null)\r
-            throw new IllegalArgumentException("null rectangle");\r
-        r.setFrame(getLeftEdgePos(), getTopEdgePos(), getOrientedWidth(), getOrientedHeight());\r
-    }\r
-    \r
-    public void getMarginsRectangle(Rectangle2D r) {\r
-        if (r == null)\r
-            throw new IllegalArgumentException("null rectangle");\r
-        if (margins == null)\r
-               getPageRectangle(r);\r
-        else\r
-               r.setFrame(getLeftEdgePos()+margins.left.diagramAbsolute,\r
-                                  getTopEdgePos()+margins.top.diagramAbsolute,\r
-                                  getOrientedWidth()-(margins.left.diagramAbsolute+margins.right.diagramAbsolute),\r
-                                  getOrientedHeight()-(margins.top.diagramAbsolute+margins.bottom.diagramAbsolute));\r
-    }\r
-\r
-    @Override\r
-    public int hashCode() {\r
-        final int PRIME = 31;\r
-        int result = 1;\r
-        long temp;\r
-        temp = Double.doubleToLongBits(heightInMM);\r
-        result = PRIME * result + (int) (temp ^ (temp >>> 32));\r
-        temp = Double.doubleToLongBits(widthInMM);\r
-        result = PRIME * result + (int) (temp ^ (temp >>> 32));\r
-        result = PRIME * result + orientation.hashCode();\r
-        result = PRIME * result + centering.hashCode();\r
-        result = PRIME * result + margins.hashCode();\r
-        return result;\r
-    }\r
-\r
-    @Override\r
-    public boolean equals(Object obj) {\r
-        if (this == obj)\r
-            return true;\r
-        if (obj == null)\r
-            return false;\r
-        if (getClass() != obj.getClass())\r
-            return false;\r
-        final PageDesc other = (PageDesc) obj;\r
-        if (Double.doubleToLongBits(heightInMM) != Double.doubleToLongBits(other.heightInMM))\r
-            return false;\r
-        if (Double.doubleToLongBits(widthInMM) != Double.doubleToLongBits(other.widthInMM))\r
-            return false;\r
-        if (!orientation.equals(other.orientation))\r
-            return false;\r
-        if (!centering.equals(other.centering))\r
-            return false;\r
-        if (!margins.equals(other.margins))\r
-            return false;\r
-        return true;\r
-    }\r
-\r
-    @Override\r
-    public String toString() {\r
-        return String.format("%s [%s, %s, %s, %s, %s]%s", getClass().getSimpleName(), text, orientation.toString(), widthInMM, heightInMM, centering.toString(), margins);\r
-    }\r
-\r
-    public static PageDesc deserialize(String desc, PageDesc defaultValue) {\r
-        if (desc == null)\r
-            return defaultValue;\r
-\r
-        PageDesc pd = null;\r
-        try {\r
-            StringTokenizer tok = new StringTokenizer(desc);\r
-            String w = tok.nextToken().trim();\r
-            String h = tok.nextToken().trim();\r
-            String orientation = tok.nextToken().trim();\r
-            String centering = tok.nextToken().trim();\r
-            String text = tok.nextToken("\u0001").trim();\r
-            String margins = tok.nextToken().trim();\r
-\r
-            double ww = new BigDecimal(w).doubleValue();\r
-            double hh = new BigDecimal(h).doubleValue();\r
-\r
-            PageDesc pd2 = PageDesc.getDescription(PageOrientation.valueOf(orientation), ww, hh);\r
-            pd2 = pd2.withCentering(PageCentering.valueOf(centering));\r
-            pd2 = pd2.withText(text);\r
-            pd2 = pd2.withMargins(deserializeMargins(margins, MarginUtils.NO_MARGINS));\r
-\r
-            pd = pd2;\r
-        } catch (IllegalArgumentException e) {\r
-        } catch (NoSuchElementException e) {\r
-        }\r
-        if (pd == null)\r
-            pd = defaultValue;\r
-        return pd;\r
-    }\r
-\r
-    public static String serialize(PageDesc desc) {\r
-        //return desc.getText();\r
-        return String.format("%s %s %s %s %s\u0001%s",\r
-                Double.toString(desc.getWidth()),\r
-                Double.toString(desc.getHeight()),\r
-                desc.getOrientation().toString(),\r
-                desc.getCentering().toString(),\r
-                desc.getText(),\r
-                serialize(desc.getMargins()));\r
-    }\r
-\r
-    public static String serialize(Margins margins) {\r
-        StringBuilder sb = new StringBuilder();\r
-        sb.append(serialize(margins.top));\r
-        sb.append(";");\r
-        sb.append(serialize(margins.bottom));\r
-        sb.append(";");\r
-        sb.append(serialize(margins.left));\r
-        sb.append(";");\r
-        sb.append(serialize(margins.right));\r
-        return sb.toString();\r
-    }\r
-\r
-    private static String serialize(Margin margin) {\r
-        StringBuilder sb = new StringBuilder();\r
-        sb.append(margin.controlRelative);\r
-        sb.append(" ");\r
-        sb.append(margin.controlAbsolute);\r
-        sb.append(" ");\r
-        sb.append(margin.diagramAbsolute);\r
-        return sb.toString();\r
-    }\r
-\r
-    /**\r
-     * @param margins\r
-     * @param defaultValue valid margins\r
-     * @return\r
-     */\r
-    public static Margins deserializeMargins(String margins, Margins defaultValue) {\r
-        if (defaultValue == null)\r
-            throw new NullPointerException("null default value");\r
-\r
-        String[] split = margins.split(";");\r
-        if (split.length != 4)\r
-            return defaultValue;\r
-\r
-        Margin top = deserializeMargins(split[0], defaultValue.top);\r
-        Margin bottom = deserializeMargins(split[1], defaultValue.bottom);\r
-        Margin left = deserializeMargins(split[2], defaultValue.left);\r
-        Margin right = deserializeMargins(split[3], defaultValue.right);\r
-        return new Margins(top, bottom, left, right);\r
-    }\r
-\r
-    /**\r
-     * @param margin\r
-     * @param defaultValue a valid margin\r
-     * @return\r
-     */\r
-    private static Margin deserializeMargins(String margin, Margin defaultValue) {\r
-        if (defaultValue == null)\r
-            throw new NullPointerException("null default value");\r
-\r
-        try {\r
-            StringTokenizer tok = new StringTokenizer(margin);\r
-            String cr = tok.nextToken().trim();\r
-            String ca = tok.nextToken().trim();\r
-            String da = tok.nextToken().trim();\r
-            return new Margin(Double.parseDouble(cr), Double.parseDouble(ca), Double.parseDouble(da));\r
-        } catch (NumberFormatException e) {\r
-            return defaultValue;\r
-        }\r
-    }\r
-\r
-}\r
+/*******************************************************************************
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     VTT Technical Research Centre of Finland - initial API and implementation
+ *******************************************************************************/
+package org.simantics.utils.page;
+
+import java.awt.geom.Rectangle2D;
+import java.math.BigDecimal;
+import java.util.NoSuchElementException;
+import java.util.StringTokenizer;
+
+import org.simantics.utils.page.MarginUtils;
+import org.simantics.utils.page.MarginUtils.Margin;
+import org.simantics.utils.page.MarginUtils.Margins;
+
+/**
+ * @see http://www.cl.cam.ac.uk/~mgk25/iso-paper.html for ISO paper dimensions
+ * 
+ * TODO: use DataType 0.4 for string serialization of PageDesc
+ */
+public class PageDesc {
+
+    public static int toMillimeters(double points) {
+        return (int) Math.round(points * (25.4/72.));
+    }
+
+    public static int toPoints(double millimeters) {
+        return (int) Math.round(millimeters* (72./25.4));
+    }
+
+    public static final PageDesc  INFINITE = new PageDesc("Infinite", PageOrientation.Portrait, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
+    public static final PageDesc  A0                   = new PageDesc("A0", PageOrientation.Portrait, 841, 1189);
+    public static final PageDesc  A1                   = new PageDesc("A1", PageOrientation.Portrait, 594, 841);
+    public static final PageDesc  A2                   = new PageDesc("A2", PageOrientation.Portrait, 420, 594);
+    public static final PageDesc  A3                   = new PageDesc("A3", PageOrientation.Portrait, 297, 420);
+    public static final PageDesc  A4                   = new PageDesc("A4", PageOrientation.Portrait, 210, 297);
+    public static final PageDesc  A5                   = new PageDesc("A5", PageOrientation.Portrait, 148, 210);
+    public static final PageDesc  A6                   = new PageDesc("A6", PageOrientation.Portrait, 105, 148);
+    public static final PageDesc  A7                   = new PageDesc("A7", PageOrientation.Portrait, 74, 105);
+    public static final PageDesc  A8                   = new PageDesc("A8", PageOrientation.Portrait, 52, 74);
+    public static final PageDesc  A9                   = new PageDesc("A9", PageOrientation.Portrait, 37, 52);
+    public static final PageDesc  A10                  = new PageDesc("A10", PageOrientation.Portrait, 26, 37);
+    public static final PageDesc[]     A = { A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10 };
+    public static final PageDesc[]     items    = { INFINITE, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10 };
+    /** List of PDF usable formats. A sub-set of items. */
+    public static final PageDesc[]     PDF_ITEMS    = { A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10 };
+
+    public static final PageDesc  DEFAULT  = A4;
+
+    private final String          text;
+
+    private final PageOrientation orientation;
+
+    private final double          widthInMM;
+
+    private final double          heightInMM;
+
+    private final PageCentering   centering;
+
+    private final Margins         margins;
+
+
+    public static PageDesc[] getPredefinedDescriptions() {
+        return items;
+    }
+    
+    public static PageDesc getByName(String pageDescName) {
+       for (PageDesc item : items) {
+               if ( item.getText().equals( pageDescName ) ) return item;
+       }
+       return null;
+    }
+
+    public static PageDesc getDescription(String identification) {
+        for (PageDesc pd : getPredefinedDescriptions()) {
+            if (pd.getText().equals(identification))
+                return pd;
+        }
+        return null;
+    }
+
+    public static PageDesc getDescription(String identification, PageOrientation o) {
+        for (PageDesc pd : getPredefinedDescriptions()) {
+            if (pd.getText().equals(identification))
+                return pd.withOrientation(o);
+        }
+        return null;
+    }
+
+    public static PageDesc getDescription(PageOrientation o, double widthInMM, double heightInMM) {
+        for (PageDesc pd : getPredefinedDescriptions()) {
+            if (pd.widthInMM == widthInMM && pd.heightInMM == heightInMM)
+                return pd.withOrientation(o);
+        }
+        return new PageDesc("Custom", o, widthInMM, heightInMM);
+    }
+
+
+    public PageDesc(String text, PageOrientation o, double widthInMM, double heightInMM) {
+        this(text, o, PageCentering.TopLeftAtOrigin, widthInMM, heightInMM);
+    }
+
+    public String toRepr() {
+        return text + ":" + orientation + ":" + widthInMM + ":" + heightInMM
+                + ":" + margins.top.diagramAbsolute
+                + ":" + margins.bottom.diagramAbsolute
+                + ":" + margins.left.diagramAbsolute
+                + ":" + margins.right.diagramAbsolute; 
+    }
+    
+    public static PageDesc fromRepr(String repr) {
+        String[] parts = repr.split(":", 8);
+        return new PageDesc(parts[0], PageOrientation.valueOf(parts[1]), 
+                PageCentering.TopLeftAtOrigin,
+                Double.valueOf(parts[2]), Double.valueOf(parts[3]),
+                new Margins(
+                        MarginUtils.marginOf(0, 0, Double.valueOf(parts[4])),
+                        MarginUtils.marginOf(0, 0, Double.valueOf(parts[5])),
+                        MarginUtils.marginOf(0, 0, Double.valueOf(parts[6])),
+                        MarginUtils.marginOf(0, 0, Double.valueOf(parts[7]))
+                        )
+                );
+    }
+
+    public PageDesc(String text, PageOrientation o, PageCentering c, double widthInMM, double heightInMM) {
+        this(text, o, c, widthInMM, heightInMM, MarginUtils.NO_MARGINS);
+    }
+
+    public PageDesc(String text, PageOrientation o, PageCentering c, double widthInMM, double heightInMM, Margins margins) {
+        if (o == null)
+            throw new IllegalArgumentException("null orientation");
+
+        this.text = text;
+        this.orientation = o;
+        this.centering = c;
+        this.widthInMM = widthInMM;
+        this.heightInMM = heightInMM;
+        this.margins = margins;
+    }
+
+    public boolean isInfinite() {
+        return widthInMM == Double.POSITIVE_INFINITY || heightInMM == Double.POSITIVE_INFINITY;
+    }
+
+    public String getText() {
+        return text;
+    }
+
+    public PageOrientation getOrientation() {
+        return orientation;
+    }
+
+    public PageCentering getCentering() {
+        return centering;
+    }
+
+    public boolean contains(double x, double y) {
+        if (isInfinite())
+            return true;
+
+        if (x < 0 || y < 0)
+            return false;
+        double maxX = getOrientedWidth();
+        double maxY = getOrientedHeight();
+        if (x > maxX || y > maxY)
+            return false;
+        return true;
+    }
+
+    /**
+     * @return
+     */
+    public double getLeftEdgePos() {
+        if (centering == PageCentering.CenteredAroundOrigin)
+            return -getOrientedWidth() * 0.5;
+        return 0.0;
+    }
+
+    /**
+     * @return
+     */
+    public double getTopEdgePos() {
+        if (centering == PageCentering.CenteredAroundOrigin)
+            return -getOrientedHeight() * 0.5;
+        return 0.0;
+    }
+
+    /**
+     * @return width dimension in millimeters
+     */
+    public double getWidth() {
+        return widthInMM;
+    }
+
+    /**
+     * @return height dimension in millimeters
+     */
+    public double getHeight() {
+        return heightInMM;
+    }
+
+    /**
+     * @return the margins associated with this page description
+     */
+    public Margins getMargins() {
+        return margins;
+    }
+
+    /**
+     * @return width dimension in millimeters with respect to the selected
+     *         canvas orientation
+     */
+    public double getOrientedWidth() {
+        if (orientation == PageOrientation.Portrait)
+            return widthInMM;
+        return heightInMM;
+    }
+
+    /**
+     * @return height dimension in millimeters with respect to the selected
+     *         canvas orientation
+     */
+    public double getOrientedHeight() {
+        if (orientation == PageOrientation.Portrait)
+            return heightInMM;
+        return widthInMM;
+    }
+
+    public PageDesc withSizeFrom(PageDesc another) {
+        return new PageDesc(text, orientation, centering, another.widthInMM, another.heightInMM, margins);
+    }
+
+    public PageDesc withOrientation(PageOrientation o) {
+        if (orientation.equals(o)) {
+            return this;
+        }
+        return new PageDesc(text, o, centering, widthInMM, heightInMM, margins);
+    }
+
+    public PageDesc withCentering(PageCentering c) {
+        if (centering.equals(c)) {
+            return this;
+        }
+        return new PageDesc(text, orientation, c, widthInMM, heightInMM, margins);
+    }
+
+    public PageDesc withText(String text) {
+        if (this.text.equals(text))
+            return this;
+        return new PageDesc(text, orientation, centering, widthInMM, heightInMM, margins);
+    }
+
+    public PageDesc withMargins(Margins margins) {
+        return new PageDesc(text, orientation, centering, widthInMM, heightInMM, margins);
+    }
+
+    public void getPageRectangle(Rectangle2D r) {
+        if (r == null)
+            throw new IllegalArgumentException("null rectangle");
+        r.setFrame(getLeftEdgePos(), getTopEdgePos(), getOrientedWidth(), getOrientedHeight());
+    }
+    
+    public void getMarginsRectangle(Rectangle2D r) {
+        if (r == null)
+            throw new IllegalArgumentException("null rectangle");
+        if (margins == null)
+               getPageRectangle(r);
+        else
+               r.setFrame(getLeftEdgePos()+margins.left.diagramAbsolute,
+                                  getTopEdgePos()+margins.top.diagramAbsolute,
+                                  getOrientedWidth()-(margins.left.diagramAbsolute+margins.right.diagramAbsolute),
+                                  getOrientedHeight()-(margins.top.diagramAbsolute+margins.bottom.diagramAbsolute));
+    }
+
+    @Override
+    public int hashCode() {
+        final int PRIME = 31;
+        int result = 1;
+        long temp;
+        temp = Double.doubleToLongBits(heightInMM);
+        result = PRIME * result + (int) (temp ^ (temp >>> 32));
+        temp = Double.doubleToLongBits(widthInMM);
+        result = PRIME * result + (int) (temp ^ (temp >>> 32));
+        result = PRIME * result + orientation.hashCode();
+        result = PRIME * result + centering.hashCode();
+        result = PRIME * result + margins.hashCode();
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        final PageDesc other = (PageDesc) obj;
+        if (Double.doubleToLongBits(heightInMM) != Double.doubleToLongBits(other.heightInMM))
+            return false;
+        if (Double.doubleToLongBits(widthInMM) != Double.doubleToLongBits(other.widthInMM))
+            return false;
+        if (!orientation.equals(other.orientation))
+            return false;
+        if (!centering.equals(other.centering))
+            return false;
+        if (!margins.equals(other.margins))
+            return false;
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("%s [%s, %s, %s, %s, %s]%s", getClass().getSimpleName(), text, orientation.toString(), widthInMM, heightInMM, centering.toString(), margins);
+    }
+
+    public static PageDesc deserialize(String desc, PageDesc defaultValue) {
+        if (desc == null)
+            return defaultValue;
+
+        PageDesc pd = null;
+        try {
+            StringTokenizer tok = new StringTokenizer(desc);
+            String w = tok.nextToken().trim();
+            String h = tok.nextToken().trim();
+            String orientation = tok.nextToken().trim();
+            String centering = tok.nextToken().trim();
+            String text = tok.nextToken("\u0001").trim();
+            String margins = tok.nextToken().trim();
+
+            double ww = new BigDecimal(w).doubleValue();
+            double hh = new BigDecimal(h).doubleValue();
+
+            PageDesc pd2 = PageDesc.getDescription(PageOrientation.valueOf(orientation), ww, hh);
+            pd2 = pd2.withCentering(PageCentering.valueOf(centering));
+            pd2 = pd2.withText(text);
+            pd2 = pd2.withMargins(deserializeMargins(margins, MarginUtils.NO_MARGINS));
+
+            pd = pd2;
+        } catch (IllegalArgumentException e) {
+        } catch (NoSuchElementException e) {
+        }
+        if (pd == null)
+            pd = defaultValue;
+        return pd;
+    }
+
+    public static String serialize(PageDesc desc) {
+        //return desc.getText();
+        return String.format("%s %s %s %s %s\u0001%s",
+                Double.toString(desc.getWidth()),
+                Double.toString(desc.getHeight()),
+                desc.getOrientation().toString(),
+                desc.getCentering().toString(),
+                desc.getText(),
+                serialize(desc.getMargins()));
+    }
+
+    public static String serialize(Margins margins) {
+        StringBuilder sb = new StringBuilder();
+        sb.append(serialize(margins.top));
+        sb.append(";");
+        sb.append(serialize(margins.bottom));
+        sb.append(";");
+        sb.append(serialize(margins.left));
+        sb.append(";");
+        sb.append(serialize(margins.right));
+        return sb.toString();
+    }
+
+    private static String serialize(Margin margin) {
+        StringBuilder sb = new StringBuilder();
+        sb.append(margin.controlRelative);
+        sb.append(" ");
+        sb.append(margin.controlAbsolute);
+        sb.append(" ");
+        sb.append(margin.diagramAbsolute);
+        return sb.toString();
+    }
+
+    /**
+     * @param margins
+     * @param defaultValue valid margins
+     * @return
+     */
+    public static Margins deserializeMargins(String margins, Margins defaultValue) {
+        if (defaultValue == null)
+            throw new NullPointerException("null default value");
+
+        String[] split = margins.split(";");
+        if (split.length != 4)
+            return defaultValue;
+
+        Margin top = deserializeMargins(split[0], defaultValue.top);
+        Margin bottom = deserializeMargins(split[1], defaultValue.bottom);
+        Margin left = deserializeMargins(split[2], defaultValue.left);
+        Margin right = deserializeMargins(split[3], defaultValue.right);
+        return new Margins(top, bottom, left, right);
+    }
+
+    /**
+     * @param margin
+     * @param defaultValue a valid margin
+     * @return
+     */
+    private static Margin deserializeMargins(String margin, Margin defaultValue) {
+        if (defaultValue == null)
+            throw new NullPointerException("null default value");
+
+        try {
+            StringTokenizer tok = new StringTokenizer(margin);
+            String cr = tok.nextToken().trim();
+            String ca = tok.nextToken().trim();
+            String da = tok.nextToken().trim();
+            return new Margin(Double.parseDouble(cr), Double.parseDouble(ca), Double.parseDouble(da));
+        } catch (NumberFormatException e) {
+            return defaultValue;
+        }
+    }
+
+}