00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "staticTextFont.h"
00020 #include "config_text.h"
00021
00022 #include "geom.h"
00023 #include "geomPoint.h"
00024 #include "geomNode.h"
00025 #include "renderState.h"
00026 #include "dcast.h"
00027
00028 TypeHandle StaticTextFont::_type_handle;
00029
00030
00031
00032
00033
00034
00035
00036
00037 StaticTextFont::
00038 StaticTextFont(PandaNode *font_def) {
00039 nassertv(font_def != (PandaNode *)NULL);
00040 _font = font_def;
00041 _glyphs.clear();
00042
00043 find_characters(font_def, RenderState::make_empty());
00044 _is_valid = !_glyphs.empty();
00045
00046 set_name(font_def->get_name());
00047 }
00048
00049
00050
00051
00052
00053
00054 void StaticTextFont::
00055 write(ostream &out, int indent_level) const {
00056 indent(out, indent_level)
00057 << "StaticTextFont " << get_name() << "; "
00058 << _glyphs.size() << " characters available in font:\n";
00059 Glyphs::const_iterator gi;
00060
00061
00062
00063
00064 static const int num_letters = 26;
00065 static const int num_digits = 10;
00066 bool lowercase[num_letters];
00067 bool uppercase[num_letters];
00068 bool digits[num_digits];
00069
00070 memset(lowercase, 0, sizeof(bool) * num_letters);
00071 memset(uppercase, 0, sizeof(bool) * num_letters);
00072 memset(digits, 0, sizeof(bool) * num_digits);
00073
00074 int count_lowercase = 0;
00075 int count_uppercase = 0;
00076 int count_digits = 0;
00077
00078 for (gi = _glyphs.begin(); gi != _glyphs.end(); ++gi) {
00079 int ch = (*gi).first;
00080 if (ch < 128) {
00081 if (islower(ch)) {
00082 count_lowercase++;
00083 lowercase[ch - 'a'] = true;
00084
00085 } else if (isupper(ch)) {
00086 count_uppercase++;
00087 uppercase[ch - 'A'] = true;
00088
00089 } else if (isdigit(ch)) {
00090 count_digits++;
00091 digits[ch - '0'] = true;
00092 }
00093 }
00094 }
00095
00096 if (count_lowercase == num_letters) {
00097 indent(out, indent_level + 2)
00098 << "All lowercase letters\n";
00099
00100 } else if (count_lowercase > 0) {
00101 indent(out, indent_level + 2)
00102 << "Some lowercase letters: ";
00103 for (int i = 0; i < num_letters; i++) {
00104 if (lowercase[i]) {
00105 out << (char)(i + 'a');
00106 }
00107 }
00108 out << "\n";
00109 }
00110
00111 if (count_uppercase == num_letters) {
00112 indent(out, indent_level + 2)
00113 << "All uppercase letters\n";
00114
00115 } else if (count_uppercase > 0) {
00116 indent(out, indent_level + 2)
00117 << "Some uppercase letters: ";
00118 for (int i = 0; i < num_letters; i++) {
00119 if (uppercase[i]) {
00120 out << (char)(i + 'A');
00121 }
00122 }
00123 out << "\n";
00124 }
00125
00126 if (count_digits == num_digits) {
00127 indent(out, indent_level + 2)
00128 << "All digits\n";
00129
00130 } else if (count_digits > 0) {
00131 indent(out, indent_level + 2)
00132 << "Some digits: ";
00133 for (int i = 0; i < num_digits; i++) {
00134 if (digits[i]) {
00135 out << (char)(i + '0');
00136 }
00137 }
00138 out << "\n";
00139 }
00140
00141 for (gi = _glyphs.begin(); gi != _glyphs.end(); ++gi) {
00142 int ch = (*gi).first;
00143 if (ch >= 128 || !isalnum(ch)) {
00144 indent(out, indent_level + 2)
00145 << ch;
00146 if (ch < isprint(ch)) {
00147 out << " = '" << (char)ch << "'\n";
00148 }
00149 }
00150 }
00151 }
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164 bool StaticTextFont::
00165 get_glyph(int character, const TextGlyph *&glyph) {
00166 Glyphs::const_iterator gi = _glyphs.find(character);
00167 if (gi == _glyphs.end()) {
00168
00169 glyph = (TextGlyph *)NULL;
00170 return false;
00171 }
00172
00173 glyph = (*gi).second;
00174 return true;
00175 }
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186 void StaticTextFont::
00187 find_character_gsets(PandaNode *root, Geom *&ch, GeomPoint *&dot,
00188 const RenderState *&state, const RenderState *net_state) {
00189 CPT(RenderState) next_net_state = net_state->compose(root->get_state());
00190
00191 if (root->is_geom_node()) {
00192 GeomNode *geode = DCAST(GeomNode, root);
00193
00194 for (int i = 0; i < geode->get_num_geoms(); i++) {
00195 dDrawable *geom = geode->get_geom(i);
00196 if (geom->is_of_type(GeomPoint::get_class_type())) {
00197 dot = DCAST(GeomPoint, geom);
00198
00199 } else if (geom->is_of_type(Geom::get_class_type())) {
00200 ch = DCAST(Geom, geom);
00201 state = next_net_state->compose(geode->get_geom_state(i));
00202 }
00203 }
00204
00205 } else {
00206 PandaNode::Children cr = root->get_children();
00207 int num_children = cr.get_num_children();
00208 for (int i = 0; i < num_children; i++) {
00209 find_character_gsets(cr.get_child(i), ch, dot, state, next_net_state);
00210 }
00211 }
00212 }
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 void StaticTextFont::
00223 find_characters(PandaNode *root, const RenderState *net_state) {
00224 CPT(RenderState) next_net_state = net_state->compose(root->get_state());
00225 string name = root->get_name();
00226
00227 bool all_digits = !name.empty();
00228 const char *p = name.c_str();
00229 while (all_digits && *p != '\0') {
00230
00231
00232
00233 all_digits = (isdigit(*p) != 0);
00234 p++;
00235 }
00236
00237 if (all_digits) {
00238 int character = atoi(name.c_str());
00239 Geom *ch = NULL;
00240 GeomPoint *dot = NULL;
00241 const RenderState *state = NULL;
00242 find_character_gsets(root, ch, dot, state, next_net_state);
00243 if (dot != NULL) {
00244
00245
00246 PTA_Vertexf alist;
00247 PTA_ushort ilist;
00248 float width;
00249 dot->get_coords(alist, ilist);
00250 if (ilist.empty()) {
00251 width = alist[0][0];
00252 } else {
00253 width = alist[ilist[0]][0];
00254 }
00255
00256 _glyphs[character] = new TextGlyph(ch, state, width);
00257 }
00258
00259 } else if (name == "ds") {
00260
00261
00262
00263 Geom *ch = NULL;
00264 GeomPoint *dot = NULL;
00265 const RenderState *state = NULL;
00266 find_character_gsets(root, ch, dot, state, next_net_state);
00267 if (dot != NULL) {
00268
00269
00270 PTA_Vertexf alist;
00271 PTA_ushort ilist;
00272 dot->get_coords(alist, ilist);
00273 if (ilist.empty()) {
00274 _line_height = alist[0][2];
00275 } else {
00276 _line_height = alist[ilist[0]][2];
00277 }
00278 _space_advance = 0.25f * _line_height;
00279 }
00280
00281 } else {
00282 PandaNode::Children cr = root->get_children();
00283 int num_children = cr.get_num_children();
00284 for (int i = 0; i < num_children; i++) {
00285 find_characters(cr.get_child(i), next_net_state);
00286 }
00287 }
00288 }