View Javadoc

1   /***********************************************************************************************************************
2    * Copyright (c) 2003, International Barcode Consortium
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without modification,
6    * are permitted provided that the following conditions are met:
7    *
8    * Redistributions of source code must retain the above copyright notice, this list of
9    * conditions and the following disclaimer.
10   * Redistributions in binary form must reproduce the above copyright notice, this list of
11   * conditions and the following disclaimer in the documentation and/or other materials
12   * provided with the distribution.
13   * Neither the name of the International Barcode Consortium nor the names of any contributors may be used to endorse
14   * or promote products derived from this software without specific prior written permission.
15   *
16   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
17   * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
18   * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
19   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22   * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23   * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24   * POSSIBILITY OF SUCH DAMAGE.
25   ***********************************************************************************************************************/
26  
27  package net.sourceforge.barbecue.output;
28  
29  import org.jdom.Document;
30  import org.jdom.Element;
31  import org.jdom.DocType;
32  import org.jdom.Namespace;
33  import org.jdom.output.XMLOutputter;
34  
35  import java.io.BufferedWriter;
36  import java.io.IOException;
37  import java.io.Writer;
38  import java.awt.*;
39  
40  /**
41   * SVG outputter to output barcodes as SVG files.
42   *
43   * Contributed by Ryan Martell.
44   *
45   * @author Ryan Martell
46   * @author <a href="mailto:opensource@ianbourke.com">Ian Bourke</a>
47   */
48  public class SVGOutput extends AbstractOutput {
49      
50      private static final String DEFAULT_FAMILY = "Arial";
51      private static final int DEFAULT_SIZE = 20;
52      
53      private static final String[] FONT_STYLES = new String[] {
54          "font-style: normal", "font-weight: bold", "font-style: italic"
55      };
56      
57      private String units;
58      private final Writer writer;
59      private Element root;
60      private Document doc;
61      
62      /**
63       * Creates a new instance of SVGOutput.
64       * @param writer The Writer to output the SVG text to
65       * @param font The font for text rendering (only if Barcode has drawText set to true)
66       * @param fgColor Foreground color
67       * @param bgColor Background color
68       * @param scalar The scalar value to convert to units.  if barWidth is 1, and you want the
69       * smallest bar to be 1/128 of an inch, this should be set to 1.0/128, and units
70       * should be set to "in"
71       * @param units The units for the scalar, above.  "in", "cm", "mm", "px" are acceptable values.
72       */
73      public SVGOutput(java.io.Writer writer, Font font, Color fgColor, Color bgColor, double scalar, String units) {
74          super(font, true, scalar, fgColor, bgColor);
75          this.writer = writer;
76          this.units = units;
77      }
78      
79      /**
80       * From AbstractOutput - sets up the SVG output.
81       */
82      public void beginDraw() {
83          root = createElement("svg");
84          doc = new Document(root);
85      }
86      
87      /**
88       * From AbstractOutput - finished up the SVG output.
89       * @param width The output width (in pixels) of the barcode
90       * @param height The output height (in pixels) of the barcode.
91       */
92      public void endDraw(int width, int height) throws OutputException {
93          root.setNamespace(Namespace.getNamespace("svg", "http://www.w3.org/2000/svg"));
94          root.setAttribute("width", getScaledDimension(width));
95          root.setAttribute("height", getScaledDimension(height));
96          doc.setDocType(new DocType("svg", "-//W3C//DTD SVG 1.1//EN", "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"));
97          
98          try {
99              BufferedWriter bw = new BufferedWriter(writer);
100             XMLOutputter outputter = new XMLOutputter();
101             outputter.output(doc, bw);
102             bw.flush();
103             bw.close();
104         } catch (IOException e) {
105             throw new OutputException(e.getMessage(), e);
106         }
107     }
108     
109     protected Element createElement(String name) {
110     	Element e = new Element(name);
111         e.setNamespace(Namespace.getNamespace("svg", "http://www.w3.org/2000/svg"));
112     	return e;
113     }
114     
115     /**
116      * From AbstractOutput - outputs the correct rectangle to the SVG output.
117      * @param x the x coordinate
118      * @param y the y coordinate
119      * @param width the width
120      * @param height the height
121      * @param paintWithForegroundColor if true, use the foreground color, otherwise use the background color
122      */
123     public int drawBar(int x, int y, int width, int height, boolean paintWithForegroundColor) {
124         Element rectElement = createElement("rect");
125         rectElement.setAttribute("x", getScaledDimension(x));
126         rectElement.setAttribute("y", getScaledDimension(y));
127         rectElement.setAttribute("width", getScaledDimension(width));
128         rectElement.setAttribute("height", getScaledDimension(height));
129         rectElement.setAttribute("style", "fill:" + getColorAsCSS(paintWithForegroundColor ? foregroundColour : backgroundColour) + ";");
130         root.addContent(rectElement);
131         return width;
132     }
133 
134 	public int drawText(String text, LabelLayout layout) throws OutputException {
135 		Element textElement = createElement("text");
136         textElement.setAttribute("x", getScaledDimension((int) layout.getBackgroundX()));
137         textElement.setAttribute("y", getScaledDimension((int) layout.getBackgroundY()));
138         textElement.setAttribute("style", constructStyleText());
139         textElement.addContent(text);
140         root.addContent(textElement);
141 		return 0;
142 	}
143 
144 	public void paintBackground(int x, int y, int width, int height) {
145         // uncertain if anything should occur here...
146     }
147     
148     private String constructStyleText() {
149         String family = DEFAULT_FAMILY;
150         int size = DEFAULT_SIZE;
151         int style = Font.PLAIN;
152         
153         if (font != null) {
154             family = font.getFamily();
155             size = font.getSize();
156             style = font.getStyle();
157         }
158         
159         StringBuffer buffer = new StringBuffer();
160         buffer.append("font-family: ");
161         buffer.append(family);
162         buffer.append("; ");
163         buffer.append("font-size: ");
164         buffer.append(size);
165         buffer.append("pt; ");
166         buffer.append(getFontStyle(style));
167         buffer.append("; ");
168         return buffer.toString();
169     }
170     
171     private String getFontStyle(int style) {
172         if (style > FONT_STYLES.length && style >= 0) {
173             return FONT_STYLES[Font.PLAIN];
174         } else {
175             return FONT_STYLES[style];
176         }
177     }
178     
179     private String getScaledDimension(int value) {
180         return "" + (value * scalar + units);
181     }
182     
183     private String getColorAsCSS(Color c) {
184         StringBuffer sb = new StringBuffer("#");
185         float [] components = c.getColorComponents(null);
186         for (int ii = 0; ii < components.length; ii++) {
187             String s = Integer.toHexString((int) (255 * components[ii])).toUpperCase();
188             if (s.length() == 1) {
189                 sb.append('0');
190             }
191             sb.append(s);
192         }
193         return sb.toString();
194     }
195 }