KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jimm > datavision > layout > LaTeXLE


1 package jimm.datavision.layout;
2 import jimm.datavision.*;
3 import jimm.datavision.field.*;
4 import jimm.datavision.layout.LineDrawer;
5 import java.io.*;
6
7 /**
8  * A LaTeX2e layout engine.
9  *
10  * @author Jim Menard, <a HREF="mailto:jimm@io.com">jimm@io.com</a>
11  */

12 public class LaTeXLE extends LayoutEngine implements LineDrawer {
13
14 protected double linethickness;
15
16 public LaTeXLE(PrintWriter out) {
17     super(out);
18     linethickness = 0;
19 }
20
21 /**
22  * Outputs the beginning of the document.
23  */

24 protected void doStart() {
25     String JavaDoc latexPaperSize = report.getPaperFormat().getLaTeXPaperSizeString();
26     out.println("\\documentclass[11pt" +
27 (latexPaperSize == null ? "" : ("," + latexPaperSize)) +
28 "]{article}\n" +
29 "\n" +
30 "\\oddsidemargin -1in\n" +
31 "\\evensidemargin -1in\n" +
32 "\\textwidth " + pageWidth() + "pt\n" +
33 "\\headheight -0.5pt\n" +
34 "\\headsep 0pt\n" +
35 "\\topmargin 0.0in\n" +
36 "\\textheight " + pageHeight() + "pt\n" +
37 "\n" +
38 "\\begin{document}\n" +
39 "\\pagestyle{empty}\n" +
40 "\\setlength{\\unitlength}{1pt}\n" +
41 "% Generated by DataVision version " + info.Version + "\n" +
42 "% " + info.URL);
43 }
44
45 /**
46  * Outputs the end of the document.
47  */

48 protected void doEnd() {
49     out.println("\\end{document}");
50 }
51
52 /**
53  * Start a new page.
54  */

55 protected void doStartPage() {
56     if (pageNumber > 1)
57     out.println("\\newpage");
58     out.println("% ======== Page " + pageNumber + " ========");
59     out.println("\\begin{picture}(" + pageWidth() + "," + pageHeight() + ")");
60 }
61
62 /**
63  * End a page.
64  */

65 protected void doEndPage() {
66     out.println("\\end{picture}");
67 }
68
69 /**
70  * Outputs a field.
71  *
72  * @param field the field to output
73  */

74 protected void doOutputField(Field field) {
75     String JavaDoc fieldAsString = field.toString();
76     if (fieldAsString == null || fieldAsString.length() == 0) {
77     makeBorders(field);
78     out.println();
79     return;
80     }
81
82     Format format = field.getFormat();
83     Rectangle bounds = field.getBounds();
84
85     // \put(x, y) {
86
putField(field);
87
88     // Calculate font size. Return array; first element for now, second
89
// element for later.
90
String JavaDoc[] size = selectFontSize(format);
91     if (size != null) out.print(size[0]);
92
93     // Align
94
String JavaDoc align = "";
95     switch (format.getAlign()) {
96     case Format.ALIGN_CENTER:
97     align = "\\begin{center}";
98     break;
99     case Format.ALIGN_RIGHT:
100     align = "\\raggedleft ";
101     break;
102     }
103     out.print("\\begin{minipage}[t]{" + bounds.width + "pt}" + align);
104
105 // // [NOTE: BROKEN; BALANCING '}' BELOW DOESN'T BALANCE PROPERLY
106
// // Nice for debugging: frame the box
107
// out.print("\\framebox(" + bounds.width + "," + bounds.height + "){"
108
// + align + "}{");
109

110     // Bold, italic, underline
111
if (format.isBold()) out.print("\\textbf{");
112     if (format.isItalic()) out.print("\\textit{");
113     if (format.isUnderline()) out.print("\\underline{");
114
115     // The actual, real, this-is-it field data
116
out.print(makeSafe(fieldAsString));
117
118     // Close align, bold, italic, underline, and font size
119
if (format.isUnderline()) out.print("}");
120     if (format.isItalic()) out.print("}");
121     if (format.isBold()) out.print("}");
122
123     if (format.getAlign() == Format.ALIGN_CENTER) out.print("\\end{center}");
124
125 // // [NOTE: BROKEN; THIS BALANCING '}' DOESN'T BALANCE PROPERLY
126
// // Nice for debugging: close the frame box
127
// out.print("}");
128

129     out.print("\\end{minipage}");
130
131     if (size != null) out.print(size[1]);
132
133     // Close \put
134
out.print("}");
135
136     // Borders
137
makeBorders(field);
138
139     out.println();
140 }
141
142 /**
143  * Ignores image output
144  *
145  * @param field an image field
146  */

147 protected void doOutputImage(ImageField field) {}
148
149 /**
150  * Outputs a line. Calls {@link #drawLine}.
151  *
152  * @param line a line
153  */

154 protected void doOutputLine(Line line) {
155     drawLine(line, null);
156 }
157
158 /**
159  * Returns array of two strings that set/reset font size. If format is
160  * <code>null</code> or has no size, return <code>null</code>.
161  *
162  * @return an array of two strings
163  */

164 protected String JavaDoc[] selectFontSize(Format format) {
165     if (format == null || format.getSize() == 0)
166     return null;
167     String JavaDoc[] size = new String JavaDoc[2];
168     size[0] = "{\\fontsize{" + format.getSize() + "pt}{"
169     + (format.getSize() * 1.2) + "pt}";
170     size[1] = "}";
171     return size;
172 }
173
174 /**
175  * Outputs borders.
176  */

177 protected void makeBorders(Field field) {
178     field.getBorderOrDefault().eachLine(this, null);
179 }
180
181 /**
182  * Draw a single line.
183  *
184  * @param line a line
185  */

186 public void drawLine(Line line, Object JavaDoc arg) {
187     Point p0 = line.getPoint(0);
188     Point p1 = line.getPoint(1);
189     double xdiff = p1.x - p0.x;
190     double ydiff = p1.y - p0.y;
191
192     if (xdiff == 0 && ydiff == 0)
193     return;
194
195     double xslope, yslope;
196     if ( ydiff == 0) { // Horizontal
197
if (p1.x < p0.x)
198         xslope = -1;
199     else if (p1.x > p0.x)
200         xslope = 1;
201     else
202         xslope = 0;
203     yslope = 0;
204     }
205     else if (xdiff == 0) { // Vertical
206
xslope = 0;
207     if (p1.y < p0.y)
208         yslope = 1;
209     else if (p1.y > p0.y)
210         yslope = -1;
211     else
212         yslope = 0;
213     }
214     else {
215 // xslope = xdiff / ydiff;
216
// yslope = ydiff / xdiff;
217
xslope = xdiff;
218     yslope = ydiff;
219 // FIX
220
double[] slopes = pickNearestSlope(xslope / yslope);
221     if (slopes == null) {
222         xslope = 1;
223         yslope = 0;
224     }
225     else {
226         xslope = slopes[0];
227         yslope = slopes[1];
228     }
229     }
230     setLineThickness(line.getThickness());
231     putLine(line, xslope, yslope);
232 }
233
234 /**
235  * Returns an array containing two doubleing-point values representing
236  * the x and y values needed for a LaTeX2e line. LaTeX2e insists that
237  * these two values be integers, but we use doubles for accuracy and
238  * let <code>putLine</code> truncate them.
239  *
240  * @param slope a double
241  * @return an array containing x and y values
242  */

243 protected double[] pickNearestSlope(double slope) {
244     boolean found = false;
245     double xySlopeAbs = 0, xSlope = 0, ySlope = 0;
246     for (int x = -6; x <= 6; ++x) {
247     for (int y = -6; y <= 6; ++y) {
248         if (!found || xySlopeAbs > (slope - Math.abs(x / y))) {
249         xySlopeAbs = Math.abs(slope - (x / y));
250         xSlope = x;
251         ySlope = y;
252         found = true;
253         }
254     }
255     }
256     if (!found) return null;
257
258     double[] answer = new double[2];
259     answer[0] = xSlope;
260     answer[1] = ySlope;
261     return answer;
262 }
263
264 /**
265  * Sets the line thickness for drawing.
266  *
267  * @param t thickness
268  */

269 protected void setLineThickness(double t) {
270     if (linethickness != t) {
271     linethickness = t;
272     out.print("\\linethickness{" + linethickness + "pt}");
273     }
274 }
275
276 /**
277  * Outputs the LaTeX2e code that places the field on the page.
278  */

279 protected void putField(Field field) {
280     double y;
281     Rectangle bounds = field.getBounds();
282     if (currentSection.getArea().getArea() == SectionArea.PAGE_FOOTER) {
283     // Page footers are anchored to the bottom of the page
284
y = currentSection.getOutputHeight() - bounds.y;
285     }
286     else {
287     y = pageHeight() - (pageHeightUsed + bounds.y);
288     }
289
290     // In a \put command, x and y determine the bottom left corner of
291
// whatever you are placing.
292
y -= field.getOutputHeight();
293
294     out.print("\\put(" + bounds.x + "," + y + "){");
295 }
296
297 /**
298  * Outputs the LaTeX2e code that places the line on the page. Both xslope
299  * and yslope are cast to ints because that's what LaTeX2e requires.
300  *
301  * @param line the line to draw
302  * @param xslope the X slope of the line; must be from -6 through 6
303  * @param yslope the Y slope of the line; must be from -6 through 6
304  */

305 protected void putLine(Line line, double xslope, double yslope) {
306     double y;
307     Point p0 = line.getPoint(0);
308     if (currentSection.getArea().getArea() == SectionArea.PAGE_FOOTER) {
309     // Page footers are anchored to the bottom of the page
310
y = p0.y;
311     }
312     else {
313     y = pageHeight() - (pageHeightUsed + p0.y);
314     }
315
316     // In a \put command, x and y determine the bottom left corner of
317
// whatever you are placing.
318
out.println("\\put(" + p0.x + "," + y + "){\\line(" + (int)xslope + ","
319         + (int)yslope + "){" + line.length() + "}}");
320 }
321
322 /**
323  * Returns a new string with all LaTeX2e special characters replaced
324  * by their printable equivalents.
325  *
326  * @param str
327  * @return a string safe for LaTeX2e output
328  */

329 protected String JavaDoc makeSafe(String JavaDoc str) {
330     StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
331     int len = str.length();
332     for (int i = 0; i < len; ++i) {
333     char c = str.charAt(i);
334     switch (c) {
335     case '\\':
336         buf.append("$\\backslash$");
337         break;
338     case '~':
339         buf.append("\\textasciitilde");
340         break;
341     case '#': case '$': case '%': case '&': case '_':
342     case '^': case '{': case '}':
343         buf.append('\\');
344         buf.append(c);
345         break;
346     default:
347         buf.append(c);
348         break;
349     }
350     }
351     return buf.toString();
352 }
353
354 }
355
Popular Tags