00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "eggMakeFont.h"
00016 #include "rangeIterator.h"
00017 #include "palettizer.h"
00018 #include "filenameUnifier.h"
00019 #include "eggFile.h"
00020 #include "textureImage.h"
00021 #include "sourceTextureImage.h"
00022 #include "pnmTextMaker.h"
00023 #include "pnmTextGlyph.h"
00024 #include "eggData.h"
00025 #include "eggGroup.h"
00026 #include "eggPoint.h"
00027 #include "eggPolygon.h"
00028 #include "eggTexture.h"
00029 #include "eggVertexPool.h"
00030 #include "eggVertex.h"
00031 #include "string_utils.h"
00032 #include "dcast.h"
00033 #include "pystub.h"
00034
00035 #include <ctype.h>
00036
00037
00038
00039
00040
00041
00042 EggMakeFont::
00043 EggMakeFont() : EggWriter(true, false) {
00044 set_program_description
00045 ("egg-mkfont uses the FreeType library to generate an egg file "
00046 "and a series of texture images from a font file "
00047 "input, such as a TTF file. The resulting egg file "
00048 "can be loaded in Panda as a font for rendering text, even "
00049 "if FreeType is not compiled into the executing Panda.\n\n"
00050
00051 "egg-mkfont will normally run the generated egg file through "
00052 "egg-palettize automatically as part of the generation process. "
00053 "This collects the individual glyph textures into a small number "
00054 "of texture maps. If you intend to run the font through egg-palettize "
00055 "yourself later, you may choose to omit this step.");
00056
00057 clear_runlines();
00058 add_runline("[opts] -o output.egg font");
00059 add_runline("[opts] font output.egg");
00060
00061 add_option
00062 ("fg", "r,g,b[,a]", 0,
00063 "Specifies the foreground color of the generated texture map. The "
00064 "default is white: 1,1,1,1, which leads to the most flexibility "
00065 "as the color can be modulated at runtime to any suitable color.",
00066 &EggMakeFont::dispatch_color, NULL, &_fg[0]);
00067
00068 add_option
00069 ("bg", "r,g,b[,a]", 0,
00070 "Specifies the background color of the generated texture map. The "
00071 "default is transparent: 1,1,1,0, which allows the text to be "
00072 "visible against any color background by placing a polygon of a "
00073 "suitable color behind it. If the alpha component of either -fg "
00074 "or -bg is not 1, the generated texture images will include an "
00075 "alpha component; if both colors specify an alpha component of 1 "
00076 "(or do not specify an alpha compenent), then the generated images "
00077 "will not include an alpha component.",
00078 &EggMakeFont::dispatch_color, NULL, &_bg[0]);
00079
00080 add_option
00081 ("interior", "r,g,b[,a]", 0,
00082 "Specifies the color to render the interior part of a hollow font. "
00083 "This is a special effect that involves analysis of the bitmap after "
00084 "the font has been rendered, and so is more effective when the pixel "
00085 "size is large. It also implies -noaa (but you can use a scale "
00086 "factor with -sf to achieve antialiasing).",
00087 &EggMakeFont::dispatch_color, &_got_interior, &_interior[0]);
00088
00089 add_option
00090 ("chars", "range", 0,
00091 "Specifies the characters of the font that are used. The range "
00092 "specification may include combinations of decimal or hex unicode "
00093 "values (where hex values are identified with a leading 0x), separated "
00094 "by commas and hyphens to indicate ranges, e.g. '32-126,0xfa0-0xfff'. "
00095 "It also may specify ranges of ASCII characters by enclosing them "
00096 "within square brackets, e.g. '[A-Za-z0-9]'. If this is not specified, "
00097 "the default is the set of ASCII characters.",
00098 &EggMakeFont::dispatch_range, NULL, &_range);
00099
00100 add_option
00101 ("extra", "file.egg", 0,
00102 "Specifies additional externally-painted glyphs to mix into the "
00103 "generated egg file. The named egg file is expected to contain one "
00104 "or more groups, each of which is named with the decimal unicode "
00105 "number of a character and should contain one polygon. These groups "
00106 "are simply copied into the output egg file as if they were generated "
00107 "locally. This option may be repeated.",
00108 &EggMakeFont::dispatch_vector_string, NULL, &_extra_filenames);
00109
00110 add_option
00111 ("ppu", "pixels", 0,
00112 "Specify the pixels per unit. This is the number of pixels in the "
00113 "generated texture map that are used for each onscreen unit (or each "
00114 "10 points of font; see -ps). Setting this number larger results in "
00115 "an easier-to-read font, but at the cost of more texture memory. "
00116 "The default is 30.",
00117 &EggMakeFont::dispatch_double, NULL, &_pixels_per_unit);
00118
00119 add_option
00120 ("ps", "size", 0,
00121 "Specify the point size of the resulting font. This controls the "
00122 "apparent size of the font when it is rendered onscreen. By convention, "
00123 "a 10 point font is 1 screen unit high, so the default is 10.",
00124 &EggMakeFont::dispatch_double, NULL, &_point_size);
00125
00126 add_option
00127 ("pm", "n", 0,
00128 "The number of extra pixels around a single character in the "
00129 "generated polygon. This may be a floating-point number. The "
00130 "default is 1.",
00131 &EggMakeFont::dispatch_double, NULL, &_poly_margin);
00132
00133 add_option
00134 ("tm", "n", 0,
00135 "The number of extra pixels around each character in the texture map. "
00136 "This may only be an integer. The default is 2. This is meaningful "
00137 "when -nopal is also used; in the normal case, use -pm to control "
00138 "both the polygon size and the texture map spacing.",
00139 &EggMakeFont::dispatch_int, NULL, &_tex_margin);
00140
00141 add_option
00142 ("rm", "n", 0,
00143 "The amount of padding in screen units to place around the glyph when "
00144 "rendered. This differs from -pm in that it has no effect on the "
00145 "generated texture map, only on the generated egg. Use this in order to "
00146 "space the characters out in case they appear to be too close together "
00147 "when rendered. The default is 0.",
00148 &EggMakeFont::dispatch_double, NULL, &_render_margin);
00149
00150 add_option
00151 ("sf", "factor", 0,
00152 "The scale factor of the generated image. This is the factor by which "
00153 "the font image is generated oversized, then reduced to its final size, "
00154 "to improve antialiasing. If the specified font contains one "
00155 "or more fixed-size fonts instead of a scalable font, the scale factor "
00156 "may be automatically adjusted as necessary to scale the closest-"
00157 "matching font to the desired pixel size. The default is 2.",
00158 &EggMakeFont::dispatch_double, &_got_scale_factor, &_scale_factor);
00159
00160 add_option
00161 ("noaa", "", 0,
00162 "Disable low-level antialiasing by the Freetype library. "
00163 "This is unrelated to the antialiasing that is applied due to the "
00164 "scale factor specified by -sf; you may have either one, neither, or "
00165 "both kinds of antialiasing enabled.",
00166 &EggMakeFont::dispatch_none, &_no_native_aa);
00167
00168 add_option
00169 ("nopal", "", 0,
00170 "Don't run egg-palettize automatically on the output file, but "
00171 "just output the raw egg file and all of its individual texture "
00172 "images, one for each glyph.",
00173 &EggMakeFont::dispatch_none, &_no_palettize);
00174
00175 add_option
00176 ("nr", "", 0,
00177 "Don't actually reduce the images after applying the scale factor, but "
00178 "leave them at their inflated sizes. Presumably you will reduce "
00179 "them later, for instance with egg-palettize.",
00180 &EggMakeFont::dispatch_none, &_no_reduce);
00181
00182 add_option
00183 ("gp", "pattern", 0,
00184 "The pattern to be used to generate the glyph texture images. This "
00185 "string will be passed to sprintf to generate the actual file name; it "
00186 "should contain the string %d or %x (or some variant such as %03d) "
00187 "which will be filled in with the Unicode number of each symbol. "
00188 "If it is omitted, the default is based on the name of the egg file. "
00189 "This is used only if -nopal is specified; in the normal case, "
00190 "without -nopal, use -pp instead.",
00191 &EggMakeFont::dispatch_string, NULL, &_output_glyph_pattern);
00192
00193 add_option
00194 ("pp", "pattern", 0,
00195 "The pattern to be used to generate the palette texture images. This "
00196 "string is effectively passed to egg-palettize as the -tn option, and "
00197 "thus should contain %i for the palette index number. This is used "
00198 "if -nopal is not specified.",
00199 &EggMakeFont::dispatch_string, NULL, &_output_palette_pattern);
00200
00201 add_option
00202 ("palsize", "xsize,ysize", 0,
00203 "Specify the size of the palette texture images. This is used if "
00204 "-nopal is not specified.",
00205 &EggMakeFont::dispatch_int_pair, NULL, _palette_size);
00206
00207 add_option
00208 ("face", "index", 0,
00209 "Specify the face index of the particular face within the font file "
00210 "to use. Some font files contain multiple faces, indexed beginning "
00211 "at 0. The default is face 0.",
00212 &EggMakeFont::dispatch_int, NULL, &_face_index);
00213
00214 _fg.set(1.0, 1.0, 1.0, 1.0);
00215 _bg.set(1.0, 1.0, 1.0, 0.0);
00216 _interior.set(1.0, 1.0, 1.0, 1.0);
00217 _pixels_per_unit = 30.0;
00218 _point_size = 10.0;
00219 _poly_margin = 1.0;
00220 _tex_margin = 2;
00221 _render_margin = 0.0;
00222 _palette_size[0] = _palette_size[1] = 256;
00223 _face_index = 0;
00224
00225 _text_maker = NULL;
00226 _vpool = NULL;
00227 _group = NULL;
00228 }
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239 bool EggMakeFont::
00240 handle_args(ProgramBase::Args &args) {
00241 if (args.empty()) {
00242 nout << "Must specify name of font file on command line.\n";
00243 return false;
00244 }
00245
00246 _input_font_filename = args[0];
00247 args.pop_front();
00248 return EggWriter::handle_args(args);
00249 }
00250
00251
00252
00253
00254
00255
00256 void EggMakeFont::
00257 run() {
00258 if (has_output_filename() && !get_output_filename().get_dirname().empty()) {
00259 FilenameUnifier::set_rel_dirname(get_output_filename().get_dirname());
00260 } else {
00261 FilenameUnifier::set_rel_dirname(".");
00262 }
00263
00264 _text_maker = new PNMTextMaker(_input_font_filename, _face_index);
00265 if (!_text_maker->is_valid()) {
00266 exit(1);
00267 }
00268
00269 if (_got_interior) {
00270 _no_native_aa = true;
00271 }
00272
00273 if (!_got_scale_factor) {
00274
00275
00276 if (_no_native_aa) {
00277 _scale_factor = 4.0;
00278 } else {
00279 _scale_factor = 2.0;
00280 }
00281 }
00282
00283 _text_maker->set_point_size(_point_size);
00284 _text_maker->set_native_antialias(!_no_native_aa);
00285 _text_maker->set_interior_flag(_got_interior);
00286 _text_maker->set_pixels_per_unit(_pixels_per_unit);
00287 _text_maker->set_scale_factor(_scale_factor);
00288
00289
00290
00291 _pixels_per_unit = _text_maker->get_pixels_per_unit();
00292 _scale_factor = _text_maker->get_scale_factor();
00293
00294 if (_text_maker->get_font_pixel_size() != 0) {
00295 nout << "Using " << _text_maker->get_font_pixel_size() << "-pixel font.\n";
00296 }
00297
00298
00299
00300
00301
00302 _palettize_scale_factor = _scale_factor;
00303 if (_scale_factor != 1.0 && (_no_reduce || !_no_palettize)) {
00304
00305
00306
00307
00308
00309
00310
00311 _tex_margin = (int)(_tex_margin * _scale_factor);
00312 _poly_margin *= _scale_factor;
00313 _pixels_per_unit *= _scale_factor;
00314 _scale_factor = 1.0;
00315 _text_maker->set_pixels_per_unit(_pixels_per_unit);
00316 _text_maker->set_scale_factor(1.0);
00317 }
00318
00319 if (_no_reduce) {
00320
00321
00322
00323 _palette_size[0] = (int)(_palette_size[0] * _palettize_scale_factor);
00324 _palette_size[1] = (int)(_palette_size[1] * _palettize_scale_factor);
00325 _palettize_scale_factor = 1.0;
00326 }
00327
00328 if (_range.is_empty()) {
00329
00330
00331 _range.add_range(0x20, 0x7e);
00332 }
00333 if (_output_glyph_pattern.empty()) {
00334
00335 _output_glyph_pattern = get_output_filename().get_fullpath_wo_extension() + "%03d.png";
00336 }
00337 if (_output_palette_pattern.empty()) {
00338
00339 _output_palette_pattern = get_output_filename().get_fullpath_wo_extension() + "_%i";
00340 }
00341
00342
00343
00344 bool needs_alpha = (_fg[3] != 1.0 || _bg[3] != 1.0 || _interior[3] != 1.0);
00345 bool needs_color = (_fg[0] != _fg[1] || _fg[1] != _fg[2] ||
00346 _bg[0] != _bg[1] || _bg[1] != _bg[2] ||
00347 _interior[0] != _interior[1] || _interior[1] != _interior[2]);
00348
00349 if (needs_alpha) {
00350 if (needs_color) {
00351 _num_channels = 4;
00352 _format = EggTexture::F_rgba;
00353 } else {
00354 if (_fg[0] == 1.0 && _bg[0] == 1.0 && _interior[0] == 1.0) {
00355
00356
00357
00358 _fg[0] = _fg[1] = _fg[2] = _fg[3];
00359 _bg[0] = _bg[1] = _bg[2] = _bg[3];
00360 _interior[0] = _interior[1] = _interior[2] = _interior[3];
00361 _num_channels = 1;
00362 _format = EggTexture::F_alpha;
00363 } else {
00364 _num_channels = 2;
00365 _format = EggTexture::F_luminance_alpha;
00366 }
00367 }
00368 } else {
00369 if (needs_color) {
00370 _num_channels = 3;
00371 _format = EggTexture::F_rgb;
00372 } else {
00373 _num_channels = 1;
00374 _format = EggTexture::F_luminance;
00375 }
00376 }
00377
00378
00379
00380
00381 pal = new Palettizer;
00382 pal->_generated_image_pattern = _output_palette_pattern;
00383 pal->_omit_solitary = false;
00384 pal->_round_uvs = false;
00385
00386
00387
00388
00389 char buffer[1024];
00390 sprintf(buffer, ":margin 0;:coverage 1000;:background %f %f %f %f;:palette %d %d;*: %f%% keep-format",
00391 _bg[0], _bg[1], _bg[2], _bg[3],
00392 _palette_size[0], _palette_size[1],
00393 100.0 / _palettize_scale_factor);
00394 istringstream txa_script(buffer);
00395 pal->read_txa_file(txa_script, "default script");
00396
00397 pal->all_params_set();
00398
00399
00400
00401
00402 PT(EggData) egg_data = new EggData;
00403 _group = new EggGroup();
00404 egg_data->add_child(_group);
00405 append_command_comment(egg_data);
00406
00407 _vpool = new EggVertexPool("vpool");
00408 _group->add_child(_vpool);
00409
00410
00411
00412 _group->set_switch_flag(true);
00413 _group->set_switch_fps(2.0);
00414
00415
00416 EggGroup *ds_group = new EggGroup("ds");
00417 _group->add_child(ds_group);
00418 EggVertex *vtx = make_vertex(LPoint2d(0.0, _text_maker->get_line_height()));
00419 EggPoint *point = new EggPoint;
00420 ds_group->add_child(point);
00421 point->add_vertex(vtx);
00422
00423
00424 RangeIterator ri(_range);
00425 do {
00426 add_character(ri.get_code());
00427 } while (ri.next());
00428
00429
00430 if (!_extra_filenames.empty()) {
00431 vector_string::const_iterator si;
00432 for (si = _extra_filenames.begin(); si != _extra_filenames.end(); ++si) {
00433 add_extra_glyphs(*si);
00434 }
00435 }
00436
00437 if (_no_palettize) {
00438
00439
00440 Textures::iterator ti;
00441 for (ti = _textures.begin(); ti != _textures.end(); ++ti) {
00442 TextureImage *texture = (*ti);
00443 texture->write(texture->read_source_image());
00444 }
00445
00446 egg_data->write_egg(get_output());
00447
00448 } else {
00449
00450
00451 string name = get_output_filename().get_basename();
00452 EggFile *egg_file = pal->get_egg_file(name);
00453 egg_file->from_command_line(egg_data, "", get_output_filename(),
00454 get_exec_command());
00455
00456 pal->add_command_line_egg(egg_file);
00457 pal->process_all(true, "");
00458 pal->optimal_resize();
00459 pal->generate_images(true);
00460 if (!pal->write_eggs()) {
00461 exit(1);
00462 }
00463
00464 }
00465 }
00466
00467
00468
00469
00470
00471
00472 bool EggMakeFont::
00473 dispatch_range(const string &, const string &arg, void *var) {
00474 RangeDescription *ip = (RangeDescription *)var;
00475 return ip->parse_parameter(arg);
00476 }
00477
00478
00479
00480
00481
00482
00483
00484 EggVertex *EggMakeFont::
00485 make_vertex(const LPoint2d &xy) {
00486 return
00487 _vpool->make_new_vertex(LPoint3d::origin(_coordinate_system) +
00488 LVector3d::rfu(xy[0], 0.0, xy[1], _coordinate_system));
00489 }
00490
00491
00492
00493
00494
00495
00496
00497 void EggMakeFont::
00498 add_character(int code) {
00499 PNMTextGlyph *glyph = _text_maker->get_glyph(code);
00500 if (glyph == (PNMTextGlyph *)NULL) {
00501 nout << "No definition in font for character " << code << ".\n";
00502 return;
00503 }
00504
00505 make_geom(glyph, code);
00506 }
00507
00508
00509
00510
00511
00512
00513
00514 void EggMakeFont::
00515 make_geom(PNMTextGlyph *glyph, int character) {
00516
00517 string group_name = format_string(character);
00518 EggGroup *group = new EggGroup(group_name);
00519 _group->add_child(group);
00520
00521 if (glyph->get_width() != 0 && glyph->get_height() != 0) {
00522 int bitmap_top = glyph->get_top();
00523 int bitmap_left = glyph->get_left();
00524 double tex_x_size = glyph->get_width();
00525 double tex_y_size = glyph->get_height();
00526
00527 double poly_margin = _poly_margin;
00528 double x_origin = _tex_margin;
00529 double y_origin = _tex_margin;
00530 double page_y_size = tex_y_size + _tex_margin * 2;
00531 double page_x_size = tex_x_size + _tex_margin * 2;
00532
00533
00534 double tex_poly_margin = poly_margin / _pixels_per_unit;
00535 double origin_y = bitmap_top / _pixels_per_unit;
00536 double origin_x = bitmap_left / _pixels_per_unit;
00537 double top = origin_y + tex_poly_margin;
00538 double left = origin_x - tex_poly_margin;
00539 double bottom = origin_y - tex_y_size / _pixels_per_unit - tex_poly_margin;
00540 double right = origin_x + tex_x_size / _pixels_per_unit + tex_poly_margin;
00541
00542
00543 double uv_top = 1.0f - (double)(y_origin - poly_margin) / page_y_size;
00544 double uv_left = (double)(x_origin - poly_margin) / page_x_size;
00545 double uv_bottom = 1.0f - (double)(y_origin + poly_margin + tex_y_size) / page_y_size;
00546 double uv_right = (double)(x_origin + poly_margin + tex_x_size) / page_x_size;
00547
00548
00549 EggVertex *v1 = make_vertex(LPoint2d(left, bottom));
00550 EggVertex *v2 = make_vertex(LPoint2d(right, bottom));
00551 EggVertex *v3 = make_vertex(LPoint2d(right, top));
00552 EggVertex *v4 = make_vertex(LPoint2d(left, top));
00553
00554 v1->set_uv(LTexCoordd(uv_left, uv_bottom));
00555 v2->set_uv(LTexCoordd(uv_right, uv_bottom));
00556 v3->set_uv(LTexCoordd(uv_right, uv_top));
00557 v4->set_uv(LTexCoordd(uv_left, uv_top));
00558
00559 EggPolygon *poly = new EggPolygon();
00560 group->add_child(poly);
00561 poly->set_texture(get_tref(glyph, character));
00562
00563 poly->add_vertex(v1);
00564 poly->add_vertex(v2);
00565 poly->add_vertex(v3);
00566 poly->add_vertex(v4);
00567 }
00568
00569
00570
00571
00572 EggVertex *v0 = make_vertex(LPoint2d(glyph->get_advance() / _pixels_per_unit + _render_margin, 0.0));
00573 EggPoint *point = new EggPoint;
00574 group->add_child(point);
00575 point->add_vertex(v0);
00576 }
00577
00578
00579
00580
00581
00582
00583
00584
00585 EggTexture *EggMakeFont::
00586 get_tref(PNMTextGlyph *glyph, int character) {
00587 TRefs::iterator ti = _trefs.find(glyph);
00588 if (ti != _trefs.end()) {
00589 return (*ti).second;
00590 }
00591
00592 EggTexture *tref = make_tref(glyph, character);
00593 _trefs[glyph] = tref;
00594 return tref;
00595 }
00596
00597
00598
00599
00600
00601
00602
00603 EggTexture *EggMakeFont::
00604 make_tref(PNMTextGlyph *glyph, int character) {
00605 char buffer[1024];
00606 sprintf(buffer, _output_glyph_pattern.c_str(), character);
00607
00608 Filename texture_filename = buffer;
00609 PNMImage image(glyph->get_width() + _tex_margin * 2,
00610 glyph->get_height() + _tex_margin * 2, _num_channels);
00611 image.fill(_bg[0], _bg[1], _bg[2]);
00612 if (image.has_alpha()) {
00613 image.alpha_fill(_bg[3]);
00614 }
00615 if (_got_interior) {
00616 glyph->place(image, -glyph->get_left() + _tex_margin,
00617 glyph->get_top() + _tex_margin, _fg, _interior);
00618 } else {
00619 glyph->place(image, -glyph->get_left() + _tex_margin,
00620 glyph->get_top() + _tex_margin, _fg);
00621 }
00622
00623
00624
00625
00626
00627
00628 string name = texture_filename.get_basename_wo_extension();
00629 TextureImage *texture = pal->get_texture(name);
00630 _textures.push_back(texture);
00631 texture->set_filename("", texture_filename);
00632 SourceTextureImage *source = texture->get_source(texture_filename, "", 0);
00633 texture->set_source_image(image);
00634 source->set_header(image);
00635
00636 EggTexture *tref = new EggTexture(name, texture_filename);
00637 tref->set_format(_format);
00638 tref->set_wrap_mode(EggTexture::WM_clamp);
00639 tref->set_minfilter(EggTexture::FT_linear_mipmap_linear);
00640 tref->set_magfilter(EggTexture::FT_linear);
00641 tref->set_quality_level(EggTexture::QL_best);
00642
00643 return tref;
00644 }
00645
00646
00647
00648
00649
00650
00651
00652 void EggMakeFont::
00653 add_extra_glyphs(const Filename &extra_filename) {
00654 PT(EggData) extra_data = new EggData;
00655
00656 if (!extra_data->read(extra_filename)) {
00657 return;
00658 }
00659
00660 _group->steal_children(*extra_data);
00661 }
00662
00663
00664
00665
00666
00667
00668
00669
00670 void EggMakeFont::
00671 r_add_extra_glyphs(EggGroupNode *egg_group) {
00672 if (egg_group->is_of_type(EggGroup::get_class_type())) {
00673 EggGroup *group = DCAST(EggGroup, egg_group);
00674 if (is_numeric(group->get_name())) {
00675 EggGroup *new_group = new EggGroup(group->get_name());
00676 _group->add_child(new_group);
00677 new_group->steal_children(*group);
00678 return;
00679 }
00680 }
00681
00682 EggGroupNode::iterator ci;
00683 for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
00684 EggNode *child = (*ci);
00685 if (child->is_of_type(EggGroupNode::get_class_type())) {
00686 r_add_extra_glyphs(DCAST(EggGroupNode, child));
00687 }
00688 }
00689 }
00690
00691
00692
00693
00694
00695
00696
00697 bool EggMakeFont::
00698 is_numeric(const string &str) {
00699 if (str.empty()) {
00700 return false;
00701 }
00702
00703 string::const_iterator si;
00704 for (si = str.begin(); si != str.end(); ++si) {
00705 if (!isdigit(*si)) {
00706 return false;
00707 }
00708 }
00709
00710 return true;
00711 }
00712
00713 int main(int argc, char *argv[]) {
00714
00715 pystub();
00716
00717 EggMakeFont prog;
00718 prog.parse_command_line(argc, argv);
00719 prog.run();
00720 return 0;
00721 }