KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openlaszlo > compiler > LineMetrics


1 /*****************************************************************************
2  * LineMetrics.java
3  * ****************************************************************************/

4
5 /* J_LZ_COPYRIGHT_BEGIN *******************************************************
6 * Copyright 2001-2004 Laszlo Systems, Inc. All Rights Reserved. *
7 * Use is subject to license terms. *
8 * J_LZ_COPYRIGHT_END *********************************************************/

9
10 package org.openlaszlo.compiler;
11 import java.io.*;
12 import java.util.*;
13 import org.openlaszlo.xml.internal.XMLUtils;
14 import org.apache.log4j.*;
15
16
17 /** Utility functions for measuring HTML content, and translating it into Flash strings.
18  *
19  * @author <a HREF="mailto:hminsky@laszlosystems.com">Henry Minsky</a>
20  */

21
22
23 /** Used to hold line widths while calculating element text metrics */
24 class LineMetrics {
25     double maxw = 0.0;
26     double w = 0.0;
27     boolean verbatim = false;
28     int nlines = 1;
29
30     int last_space_pos;
31     int last_newline_pos;
32     double last_spacewidth = 0;
33
34     int trailing_newlines = 0;
35
36     /* Cases where we need to normalize whitespace across element boundaries
37
38     foo <i>bar</i>
39     foo <i> bar</i>
40     <i>foo</i> bar
41     <i>foo </i>bar
42     <i>foo </i> bar
43     <i>foo</i> <b>bar</b>
44     <i>foo</i> <b> bar</b>
45     <i>foo </i> <b> bar</b>
46     <i>foo </i><b> bar</b>
47     */

48     /** Keep swallowing whitespace until the first non-whitespace character is
49     encountered.
50     */

51     boolean trim = true;
52
53     StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
54
55     public String JavaDoc toString() {
56         return "LineMetrics: maxw="+maxw+" nlines="+nlines+" verbatim="+verbatim+ " str=|"+buf.toString()+"|";
57     }
58
59     /* Add a run of HTML, normalizing runs of whitespace to single
60        spaces if required. Flash's HTML text areas are sensitive to whitespace,
61        so we need to present exactly the amount of whitespace that is desired.
62
63        The trick is to figure out when to insert whitespace,
64        especially as whitespace is carried across element boundaries.
65        We keep one bit of state across Elements:
66
67         trim:
68           Tells the next element that it should
69           discard any leading whitespace, because either this is the
70           start of a line, or because we have inserted a trailing
71           whitespace already.
72
73         
74     */

75
76     void addHTML (String JavaDoc rawtext, String JavaDoc normalized_text, FontInfo fontInfo, SWFWriter generator) {
77         if (rawtext.length() == 0) {
78             return;
79         }
80         boolean leading_whitespace = Character.isWhitespace(rawtext.charAt(0));
81         boolean trailing_whitespace = Character.isWhitespace(rawtext.charAt(rawtext.length()-1));
82         boolean all_whitespace = (normalized_text.length() == 0);
83
84         if (all_whitespace) {
85             if (!this.trim && (leading_whitespace || trailing_whitespace)) {
86                 normalized_text = " ";
87             } else {
88                 normalized_text = "";
89             }
90             this.trim = true;
91         } else {
92             if (!this.trim && leading_whitespace) {
93                 normalized_text = " " + normalized_text;
94             }
95             if (trailing_whitespace) {
96                 normalized_text = normalized_text + " ";
97             }
98             this.trim = trailing_whitespace;
99         }
100
101         addSpan(normalized_text, fontInfo, generator);
102     }
103
104     void setVerbatim (boolean val) {
105         this.verbatim = val;
106         resetLineWidth();
107     }
108
109     /** Add a run of text to the current text block, tracking the max width
110      and accumulating the text into a buffer. */

111     void addSpan (String JavaDoc str, FontInfo fontInfo, SWFWriter generator) {
112         if (str.length() > 0) {
113             if (generator != null) {
114                 double sw = TextCompiler.getTextWidth(str, fontInfo, generator, this);
115                 w += sw;
116             }
117             str = XMLUtils.escapeXml(str);
118
119             // Remember the position of the last space char on the
120
// line, in case we need to trim it later.
121
if (!verbatim) {
122                 int buflen = buf.length();
123                 char lastchar = str.charAt(str.length()-1);
124                 if (lastchar == ' ') {
125                     last_space_pos = buflen + str.length() -1;
126                 } else {
127                     last_space_pos = -1;
128                 }
129
130                 int newline_pos = str.lastIndexOf('\n');
131                 if (newline_pos >= 0) {
132                     last_newline_pos = newline_pos + buflen;
133                 }
134             }
135             buf.append(str);
136         }
137     }
138
139     /** Add an HTML command, does not affect textwidth */
140     void addFormat (String JavaDoc str) {
141         buf.append(str);
142     }
143
144     void addStartTag (String JavaDoc tagName, FontInfo fontInfo, SWFWriter generator) {
145         addFormat("<" + tagName);
146     }
147
148     void endStartTag () {
149         addFormat(">");
150     }
151
152     void addEndTag (String JavaDoc tagName) {
153         addFormat("</" + tagName + ">");
154     }
155
156     /* @return the normalized text string */
157     String JavaDoc getText () {
158         return buf.toString();
159     }
160
161     /* Compute maxwidth of this line and any previous lines. */
162     void endOfLine() {
163         // Trim trailing whitespace at end of lines
164
if (!verbatim) {
165             if (last_space_pos > 0 && last_space_pos > last_newline_pos) {
166                 buf.deleteCharAt(last_space_pos);
167                 w -= last_spacewidth;
168             }
169         }
170         maxw = Math.max(maxw, w);
171         w = 0.0;
172         last_space_pos = -1;
173     }
174
175     /** act as if a linebreak had occurred, for purposes of calculating max text width
176      */

177      void resetLineWidth() {
178          maxw = Math.max(maxw, w);
179          w = 0.0;
180          last_space_pos = -1;
181      }
182
183     /** End the line and add an HTML linebreak command element to the output buffer. */
184     void newline() {
185         nlines++;
186         endOfLine();
187         trim = true;
188         buf.append("<br/>");
189     }
190
191     /** Ensures that at least two newline chars are present at end of
192          buffer. */

193     void paragraphBreak () {
194         // Do not put blank space at beginning of text
195
if (buf.length() == 0) return;
196
197         // Count how many trailing newlines at end of output string
198
trailing_newlines = 0;
199         for (int i = buf.length()-1; i >= 0; i--) {
200             char c = buf.charAt(i);
201             if (c == '\t' || c == ' ') continue;
202             if (c == '\n') {
203                 trailing_newlines++;
204             } else {
205                 break;
206             }
207         }
208         if (trailing_newlines == 0) {
209             buf.append("<br/><br/>");
210         } else if (trailing_newlines == 1) {
211             buf.append("<br/>");
212         } else {
213             // don't need any more trailing newlines
214
}
215     }
216
217 }
218
Popular Tags