00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "textFont.h"
00020 #include "config_text.h"
00021 #include "ctype.h"
00022
00023 TypeHandle TextFont::_type_handle;
00024
00025
00026
00027
00028
00029
00030
00031 INLINE bool
00032 isblank(unsigned int ch) {
00033 return (ch == ' ' || ch == '\t');
00034 }
00035
00036
00037
00038
00039
00040
00041 INLINE bool
00042 isspacew(unsigned int ch) {
00043 return isascii(ch) && isspace(ch);
00044 }
00045
00046
00047
00048
00049
00050
00051 TextFont::
00052 TextFont() {
00053 _is_valid = false;
00054 _line_height = 1.0f;
00055 _space_advance = 0.25f;
00056 }
00057
00058
00059
00060
00061
00062
00063 TextFont::
00064 ~TextFont() {
00065 }
00066
00067
00068
00069
00070
00071
00072
00073 float TextFont::
00074 calc_width(int character) {
00075 if (character == ' ') {
00076
00077 return _space_advance;
00078 }
00079
00080 const TextGlyph *glyph;
00081 get_glyph(character, glyph);
00082 if (glyph == (TextGlyph *)NULL) {
00083
00084 return 0.0f;
00085 }
00086
00087 return glyph->get_advance();
00088 }
00089
00090
00091
00092
00093
00094
00095
00096
00097 float TextFont::
00098 calc_width(const string &line) {
00099 float width = 0.0f;
00100
00101 string::const_iterator si;
00102 for (si = line.begin(); si != line.end(); ++si) {
00103 width += calc_width(*si);
00104 }
00105
00106 return width;
00107 }
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118 string TextFont::
00119 wordwrap_to(const string &text, float wordwrap_width,
00120 bool preserve_trailing_whitespace) {
00121 string output_text;
00122
00123 size_t p = 0;
00124
00125
00126 float initial_width = 0.0f;
00127 while (p < text.length() && isspace((unsigned int)text[p])) {
00128 if (text[p] == '\n') {
00129 initial_width = 0.0f;
00130 } else {
00131 initial_width += calc_width(text[p]);
00132 }
00133 output_text += text[p];
00134 p++;
00135 }
00136 bool needs_newline = false;
00137
00138 while (p < text.length()) {
00139 nassertr(!isspace((unsigned int)text[p]), string());
00140
00141
00142
00143
00144 size_t q = p;
00145 bool any_spaces = false;
00146 bool overflow = false;
00147
00148 float width = initial_width;
00149 while (q < text.length() && text[q] != '\n') {
00150 if (isspace((unsigned int)text[q])) {
00151 any_spaces = true;
00152 }
00153
00154 width += calc_width(text[q]);
00155 q++;
00156
00157 if (width > wordwrap_width) {
00158
00159 q--;
00160 overflow = true;
00161 break;
00162 }
00163 }
00164
00165 if (overflow && any_spaces) {
00166
00167
00168 while (q > p && !isspace((unsigned int)text[q])) {
00169 q--;
00170 }
00171 }
00172
00173
00174 size_t next_start = q;
00175 while (next_start < text.length() && isblank(text[next_start])) {
00176 next_start++;
00177 }
00178
00179
00180 while (q > p && isspace(text[q - 1])) {
00181 q--;
00182 }
00183
00184 if (next_start == p) {
00185
00186
00187
00188 q++;
00189 next_start++;
00190 while (next_start < text.length() && isblank(text[next_start])) {
00191 next_start++;
00192 }
00193 }
00194
00195 if (needs_newline) {
00196 output_text += '\n';
00197 }
00198 needs_newline = true;
00199
00200 if (preserve_trailing_whitespace) {
00201 q = next_start;
00202 }
00203 output_text += text.substr(p, q - p);
00204
00205
00206
00207 if (next_start < text.length() && text[next_start] == '\n') {
00208
00209 output_text += '\n';
00210 next_start++;
00211 needs_newline = false;
00212 }
00213 p = next_start;
00214
00215
00216 initial_width = 0.0f;
00217 while (p < text.length() && isspace((unsigned int)text[p])) {
00218 if (text[p] == '\n') {
00219 initial_width = 0.0f;
00220 } else {
00221 initial_width += calc_width(text[p]);
00222 }
00223 output_text += text[p];
00224 p++;
00225 }
00226 }
00227
00228 return output_text;
00229 }
00230
00231
00232
00233
00234
00235
00236 void TextFont::
00237 write(ostream &out, int indent_level) const {
00238 indent(out, indent_level)
00239 << "TextFont " << get_name() << "\n";
00240 }
00241
00242
00243
00244
00245
00246
00247
00248
00249 float TextFont::
00250 calc_width(const wstring &line) {
00251 float width = 0.0f;
00252
00253 wstring::const_iterator si;
00254 for (si = line.begin(); si != line.end(); ++si) {
00255 width += calc_width(*si);
00256 }
00257
00258 return width;
00259 }
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270 wstring TextFont::
00271 wordwrap_to(const wstring &text, float wordwrap_width,
00272 bool preserve_trailing_whitespace) {
00273 wstring output_text;
00274
00275 size_t p = 0;
00276
00277
00278 float initial_width = 0.0f;
00279 while (p < text.length() && isspacew(text[p])) {
00280 if (text[p] == '\n') {
00281 initial_width = 0.0f;
00282 } else {
00283 initial_width += calc_width(text[p]);
00284 }
00285 output_text += text[p];
00286 p++;
00287 }
00288 bool needs_newline = false;
00289
00290 while (p < text.length()) {
00291 nassertr(!isspacew(text[p]), wstring());
00292
00293
00294
00295
00296 size_t q = p;
00297 bool any_spaces = false;
00298 bool overflow = false;
00299
00300 float width = initial_width;
00301 while (q < text.length() && text[q] != '\n') {
00302 if (isspacew(text[q])) {
00303 any_spaces = true;
00304 }
00305
00306 width += calc_width(text[q]);
00307 q++;
00308
00309 if (width > wordwrap_width) {
00310
00311 q--;
00312 overflow = true;
00313 break;
00314 }
00315 }
00316
00317 if (overflow && any_spaces) {
00318
00319
00320 while (q > p && !isspacew(text[q])) {
00321 q--;
00322 }
00323 }
00324
00325
00326 size_t next_start = q;
00327 while (next_start < text.length() && isblank(text[next_start])) {
00328 next_start++;
00329 }
00330
00331
00332 while (q > p && isspacew(text[q - 1])) {
00333 q--;
00334 }
00335
00336 if (next_start == p) {
00337
00338
00339
00340 q++;
00341 next_start++;
00342 while (next_start < text.length() && isblank(text[next_start])) {
00343 next_start++;
00344 }
00345 }
00346
00347 if (needs_newline) {
00348 output_text += '\n';
00349 }
00350 needs_newline = true;
00351
00352 if (preserve_trailing_whitespace) {
00353 q = next_start;
00354 }
00355 output_text += text.substr(p, q - p);
00356
00357
00358
00359 if (next_start < text.length() && text[next_start] == '\n') {
00360
00361 output_text += '\n';
00362 next_start++;
00363 needs_newline = false;
00364 }
00365 p = next_start;
00366
00367
00368 initial_width = 0.0f;
00369 while (p < text.length() && isspacew(text[p])) {
00370 if (text[p] == '\n') {
00371 initial_width = 0.0f;
00372 } else {
00373 initial_width += calc_width(text[p]);
00374 }
00375 output_text += text[p];
00376 p++;
00377 }
00378 }
00379
00380 return output_text;
00381 }