00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "eggMakeFont.h"
00020 #include "charBitmap.h"
00021 #include "charPlacement.h"
00022 #include "pkFontFile.h"
00023
00024 #include <string_utils.h>
00025 #include <eggGroup.h>
00026 #include <eggTexture.h>
00027 #include <eggVertexPool.h>
00028 #include <eggPolygon.h>
00029 #include <eggPoint.h>
00030 #include <pointerTo.h>
00031
00032 #include <math.h>
00033
00034
00035
00036
00037
00038
00039 EggMakeFont::
00040 EggMakeFont() : EggWriter(true, false) {
00041 set_program_description
00042 ("egg-mkfont reads a rasterized font stored in a "
00043 "Metafont/TeX pk file format, and generates an egg "
00044 "file and corresponding texture map that can be used with "
00045 "Panda's TextNode object to render text in the font.\n\n"
00046
00047 "The input pk file can come from any of a number of sources. "
00048 "It may be a Metafont font that ships with TeX, or it may "
00049 "have been converted from a PostScript font, or you can use "
00050 "freetype (see www.freetype.org) to convert a TTF font to pk.\n\n");
00051
00052
00053 clear_runlines();
00054 add_runline("[opts] -o output.egg file.pk");
00055 add_runline("[opts] file.pk output.egg");
00056
00057 add_option
00058 ("i", "filename", 0,
00059 "Name of the texture image to write. The default if this is omitted "
00060 "is based on the name of the egg file.",
00061 &EggMakeFont::dispatch_filename, NULL, &_output_image_filename);
00062
00063 add_option
00064 ("c", "num", 0,
00065 "Specifies the number of channels of the output image. This should "
00066 "either 1, 2, 3, or 4. If the number is 1 or 3 a grayscale image is "
00067 "generated, with the text in white on black. If the number is 2 or 4 "
00068 "a completely white image is generated, with the text in the alpha "
00069 "channel. This parameter may also be specified as the third number "
00070 "on -d, below. The default is 1.",
00071 &EggMakeFont::dispatch_int, NULL, &_output_zsize);
00072
00073 add_option
00074 ("fg", "r,g,b[,a]", 0,
00075 "Specifies the foreground color of the generated texture map. The "
00076 "default is white: 1,1,1,1, which leads to the most flexibility "
00077 "as the color can be modulated at runtime to any suitable color.",
00078 &EggMakeFont::dispatch_color, NULL, &_fg[0]);
00079
00080 add_option
00081 ("bg", "r,g,b[,a]", 0,
00082 "Specifies the background color of the generated texture map. The "
00083 "default is transparent black: 0,0,0,0, which allows the text to be "
00084 "visible against any color background by placing a polygon of a "
00085 "suitable color behind it.",
00086 &EggMakeFont::dispatch_color, NULL, &_bg[0]);
00087
00088 add_option
00089 ("d", "x,y[,c]", 0,
00090 "Dimensions in pixels of the texture image, with an optional number of "
00091 "channels. Normally, you should not specify this parameter, as "
00092 "egg-mkfont will choose an image size that yields a scale factor "
00093 "between 2.5 and 4, which leads to good antialiased letters. If you "
00094 "want a larger or smaller image, you could force the image size "
00095 "with this parameter, but it would probably yield better results if "
00096 "you re-rasterized the font at a different DPI instead.",
00097 &EggMakeFont::dispatch_dimensions, &_got_output_size);
00098
00099 add_option
00100 ("sf", "factor", 0,
00101
00102 "The scale factor of the generated image. This is the factor by which "
00103 "the font image is generated oversized, then reduced to its final size, "
00104 "to generate antialiased letters. Values between 2.5 and 4 are generally "
00105 "best. Normally, you should not specify this parameter, as egg-mkfont "
00106 "will choose a scale factor automatically to best fit the letters in the "
00107 "space available. If you do specify a scale factor with -sf, you must "
00108 "also specify an image size with -d.",
00109 &EggMakeFont::dispatch_double, &_got_scale_factor, &_scale_factor);
00110
00111 add_option
00112 ("nr", "", 0,
00113 "No reduce. After the oversized image is generated, rather than reducing "
00114 "it to its final size, just leave it as it is, and assume the user will "
00115 "reduce it later. This may be desireable if you intend to adjust the "
00116 "letters by hand in some way after the image is generated.",
00117 &EggMakeFont::dispatch_none, &_no_reduce);
00118
00119 add_option
00120 ("g", "radius", 0,
00121 "The radius of the Gaussian filter used to antialias the letters. [1.2]",
00122 &EggMakeFont::dispatch_double, NULL, &_gaussian_radius);
00123
00124 add_option
00125 ("b", "n", 0,
00126 "The number of buffer pixels between two adjacent characters in "
00127 "the palette image. [4.0]",
00128 &EggMakeFont::dispatch_double, NULL, &_buffer_pixels);
00129
00130 add_option
00131 ("B", "n", 0,
00132 "The number of extra pixels around a single character in the "
00133 "generated polygon. [1.0]",
00134 &EggMakeFont::dispatch_double, NULL, &_poly_pixels);
00135
00136 add_option
00137 ("ds", "size", 0,
00138 "Specify the design size of the resulting font. The design size of "
00139 "a font is the height of a typical capital letter; it's the approximate "
00140 "height of a line of text. This sets the size of the polygons "
00141 "accordingly. [1.0]",
00142 &EggMakeFont::dispatch_double, NULL, &_ds);
00143
00144 add_option
00145 ("scale", "size", 0,
00146 "Specify an additional scale to the font, without changing its design "
00147 "size. This makes the letters larger (or smaller) without changing "
00148 "the spacing between lines. Usually you should use -ds instead of "
00149 "-scale to change the size of the text.",
00150 &EggMakeFont::dispatch_double, NULL, &_scale);
00151
00152 add_option
00153 ("all", "", 0,
00154 "Extract all the characters in the font. Normally, only the "
00155 "ASCII characters in the range 33 .. 127 are extracted.",
00156 &EggMakeFont::dispatch_none, &_get_all);
00157
00158 add_option
00159 ("only", "'chars'", 0,
00160 "Extract *only* the indicated characters from the font. The parameter "
00161 "should be a quoted string of letters and symbols that are to be "
00162 "extracted. If the hyphen appears, it indicates a range of characters, "
00163 "e.g. A-Z to extract all the capital letters. If the hyphen appears "
00164 "as the first or last character it loses its special meaning.",
00165 &EggMakeFont::dispatch_string, NULL, &_only_chars);
00166
00167 add_option
00168 ("sc", "", 0,
00169 "Small caps: generate lowercase letters as small capitals. This "
00170 "allows the lowercase and capital letters to share the same space "
00171 "on the texture map.",
00172 &EggMakeFont::dispatch_none, &_small_caps);
00173
00174 add_option
00175 ("scs", "", 0,
00176 "Small caps scale: the ratio of the size of a lowercase letter to "
00177 "its uppercase equivalent, when -sc is in effect. [0.8]",
00178 &EggMakeFont::dispatch_double, NULL, &_small_caps_scale);
00179
00180 _fg.set(1.0, 1.0, 1.0, 1.0);
00181 _bg.set(0.0, 0.0, 0.0, 0.0);
00182 _output_xsize = 256;
00183 _output_ysize = 256;
00184 _output_zsize = 1;
00185 _buffer_pixels = 4.0;
00186 _poly_pixels = 1.0;
00187 _scale_factor = 3.0;
00188 _gaussian_radius = 1.2;
00189 _ds = 1.0;
00190 _scale = 1.0;
00191 _small_caps_scale = 0.8;
00192 }
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203 bool EggMakeFont::
00204 handle_args(ProgramBase::Args &args) {
00205 if (args.empty()) {
00206 nout << "Must specify name of pk file on command line.\n";
00207 return false;
00208 }
00209
00210 _input_font_filename = args[0];
00211 args.pop_front();
00212 return EggWriter::handle_args(args);
00213 }
00214
00215
00216
00217
00218
00219
00220
00221 bool EggMakeFont::
00222 dispatch_dimensions(ProgramBase *self, const string &opt, const string &arg, void *) {
00223 EggBase *base = (EggBase *)self;
00224 EggMakeFont *me = (EggMakeFont *)base->as_writer();
00225 return me->ns_dispatch_dimensions(opt, arg);
00226 }
00227
00228
00229
00230
00231
00232
00233
00234 bool EggMakeFont::
00235 ns_dispatch_dimensions(const string &opt, const string &arg) {
00236 vector_string words;
00237 tokenize(arg, words, ",");
00238
00239 bool okflag = false;
00240 if (words.size() == 2) {
00241 okflag =
00242 string_to_int(words[0], _output_xsize) &&
00243 string_to_int(words[1], _output_ysize);
00244
00245 } else if (words.size() == 3) {
00246 okflag =
00247 string_to_int(words[0], _output_xsize) &&
00248 string_to_int(words[1], _output_ysize) &&
00249 string_to_int(words[2], _output_zsize);
00250 }
00251
00252 if (!okflag) {
00253 nout << "-" << opt
00254 << " requires two or three integers separated by commas.\n";
00255 return false;
00256 }
00257
00258 return true;
00259 }
00260
00261
00262
00263
00264
00265
00266
00267 TexCoordd EggMakeFont::
00268 get_uv(double x, double y) {
00269 return TexCoordd(x / (double)_working_xsize,
00270 ((double)_working_ysize - y) / (double)_working_ysize);
00271 }
00272
00273
00274
00275
00276
00277
00278
00279
00280 LPoint2d EggMakeFont::
00281 get_xy(double x, double y) {
00282 return LPoint2d(x / (_font->get_hppp() * _ppu), -y / (_font->get_vppp() * _ppu));
00283 }
00284
00285
00286
00287
00288
00289
00290
00291 EggVertex *EggMakeFont::
00292 make_vertex(const LPoint2d &xy) {
00293 return
00294 _vpool->make_new_vertex(LPoint3d::origin(_coordinate_system) +
00295 LVector3d::rfu(xy[0], 0.0, xy[1], _coordinate_system));
00296 }
00297
00298
00299
00300
00301
00302
00303
00304 void EggMakeFont::
00305 copy_character(const CharPlacement &pl) {
00306 const CharBitmap *bm = pl._bm;
00307 int xp = pl._x;
00308 int yp = pl._y;
00309
00310 int character = bm->_character;
00311 int hoff = bm->_hoff;
00312 int voff = bm->_voff;
00313 double dx = bm->_dx;
00314 double dy = bm->_dy;
00315 int width = bm->get_width();
00316 int height = bm->get_height();
00317
00318
00319 if (_output_image.has_alpha()) {
00320 for (int y = 0; y < height; y++) {
00321 for (int x = 0; x < width; x++) {
00322 if (bm->_block[y][x]) {
00323 _output_image.set_xel(xp + x, yp + y, _fg[0], _fg[1], _fg[2]);
00324 _output_image.set_alpha(xp + x, yp + y, _fg[3]);
00325 }
00326 }
00327 }
00328 } else {
00329 for (int y = 0; y < height; y++) {
00330 for (int x = 0; x < width; x++) {
00331 if (bm->_block[y][x]) {
00332 _output_image.set_xel(xp + x, yp + y, _fg[0], _fg[1], _fg[2]);
00333 }
00334 }
00335 }
00336 }
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348 double b = _working_poly_pixels;
00349
00350 TexCoordd uv_ul = get_uv(xp - b, yp - b);
00351 TexCoordd uv_lr = get_uv(xp + width + b, yp + height + b);
00352 LPoint2d xy_ul = get_xy(-hoff - b, -voff - b);
00353 LPoint2d xy_lr = get_xy(-hoff + width + b, -voff + height + b);
00354 LPoint2d dp = get_xy(dx, dy);
00355
00356 EggVertex *v1 = make_vertex(LPoint2d(xy_ul[0], xy_lr[1]));
00357 EggVertex *v2 = make_vertex(LPoint2d(xy_lr[0], xy_lr[1]));
00358 EggVertex *v3 = make_vertex(LPoint2d(xy_lr[0], xy_ul[1]));
00359 EggVertex *v4 = make_vertex(LPoint2d(xy_ul[0], xy_ul[1]));
00360
00361 v1->set_uv(TexCoordd(uv_ul[0], uv_lr[1]));
00362 v2->set_uv(TexCoordd(uv_lr[0], uv_lr[1]));
00363 v3->set_uv(TexCoordd(uv_lr[0], uv_ul[1]));
00364 v4->set_uv(TexCoordd(uv_ul[0], uv_ul[1]));
00365
00366
00367 string group_name = format_string(character);
00368 PT(EggGroup) group = new EggGroup(group_name);
00369 _egg_defs[character] = group;
00370
00371 EggPolygon *poly = new EggPolygon();
00372 group->add_child(poly);
00373 poly->set_texture(_tref);
00374
00375 poly->add_vertex(v1);
00376 poly->add_vertex(v2);
00377 poly->add_vertex(v3);
00378 poly->add_vertex(v4);
00379
00380
00381
00382
00383 EggVertex *v0 = make_vertex(dp);
00384 EggPoint *point = new EggPoint;
00385 group->add_child(point);
00386 point->add_vertex(v0);
00387
00388 if (_small_caps && isupper(character)) {
00389
00390
00391
00392 xy_ul *= _small_caps_scale;
00393 xy_lr *= _small_caps_scale;
00394 dp *= _small_caps_scale;
00395 character = tolower(character);
00396
00397 EggVertex *v1 = make_vertex(LPoint2d(xy_ul[0], xy_lr[1]));
00398 EggVertex *v2 = make_vertex(LPoint2d(xy_lr[0], xy_lr[1]));
00399 EggVertex *v3 = make_vertex(LPoint2d(xy_lr[0], xy_ul[1]));
00400 EggVertex *v4 = make_vertex(LPoint2d(xy_ul[0], xy_ul[1]));
00401
00402 v1->set_uv(TexCoordd(uv_ul[0], uv_lr[1]));
00403 v2->set_uv(TexCoordd(uv_lr[0], uv_lr[1]));
00404 v3->set_uv(TexCoordd(uv_lr[0], uv_ul[1]));
00405 v4->set_uv(TexCoordd(uv_ul[0], uv_ul[1]));
00406
00407 string group_name = format_string(character);
00408 PT(EggGroup) group = new EggGroup(group_name);
00409 _egg_defs[character] = group;
00410
00411 EggPolygon *poly = new EggPolygon();
00412 group->add_child(poly);
00413 poly->set_texture(_tref);
00414
00415 poly->add_vertex(v1);
00416 poly->add_vertex(v2);
00417 poly->add_vertex(v3);
00418 poly->add_vertex(v4);
00419
00420 EggVertex *v0 = make_vertex(dp);
00421 EggPoint *point = new EggPoint;
00422 group->add_child(point);
00423 point->add_vertex(v0);
00424 }
00425 }
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438 bool EggMakeFont::
00439 consider_scale_factor(double scale_factor) {
00440 _scale_factor = scale_factor;
00441 _working_xsize = (int)floor(_output_xsize * _scale_factor + 0.5);
00442 _working_ysize = (int)floor(_output_ysize * _scale_factor + 0.5);
00443 _working_buffer_pixels = (int)floor(_buffer_pixels * _scale_factor + 0.5);
00444
00445 _layout.reset(_working_xsize, _working_ysize, _working_buffer_pixels);
00446
00447 bool ok = true;
00448 int num_chars = _font->get_num_chars();
00449 for (int i = 0; i < num_chars; i++) {
00450 CharBitmap *bm = _font->get_char(i);
00451 if (!(_small_caps && islower(bm->_character))) {
00452 ok = _layout.place_character(bm);
00453 if (!ok) {
00454
00455 return false;
00456 }
00457 }
00458 }
00459
00460
00461 return true;
00462 }
00463
00464
00465
00466
00467
00468
00469
00470
00471 void EggMakeFont::
00472 choose_scale_factor(double too_small, double too_large) {
00473 if (too_large - too_small < 0.000001) {
00474
00475 consider_scale_factor(too_large);
00476 return;
00477 }
00478
00479 double mid = (too_small + too_large) / 2.0;
00480 if (consider_scale_factor(mid)) {
00481
00482 choose_scale_factor(too_small, mid);
00483 } else {
00484
00485 choose_scale_factor(mid, too_large);
00486 }
00487 }
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500 bool EggMakeFont::
00501 choose_scale_factor() {
00502
00503
00504 double too_small, too_large;
00505 int sanity_count = 0;
00506
00507 double guess = 1.0;
00508 if (consider_scale_factor(guess)) {
00509
00510 do {
00511 too_large = guess;
00512 guess = guess / 2.0;
00513 if (sanity_count++ > 20) {
00514 return false;
00515 }
00516 } while (consider_scale_factor(guess));
00517 too_small = guess;
00518
00519 } else {
00520
00521 do {
00522 too_small = guess;
00523 guess = guess * 2.0;
00524 if (sanity_count++ > 20) {
00525 return false;
00526 }
00527 } while (!consider_scale_factor(guess));
00528 too_large = guess;
00529 }
00530
00531 choose_scale_factor(too_small, too_large);
00532 return true;
00533 }
00534
00535
00536
00537
00538
00539
00540
00541
00542 void EggMakeFont::
00543 choose_image_size() {
00544
00545 _output_xsize = 256;
00546 _output_ysize = 256;
00547
00548 bool sane = choose_scale_factor();
00549
00550 if (sane && _scale_factor <= 2.5) {
00551
00552
00553 do {
00554 if (_output_ysize < _output_xsize) {
00555 _output_xsize /= 2;
00556 } else {
00557 _output_ysize /= 2;
00558 }
00559 sane = choose_scale_factor();
00560 } while (sane && _scale_factor <= 2.5);
00561
00562 if (!sane) {
00563
00564 _output_xsize *= 2;
00565 }
00566 choose_scale_factor();
00567
00568 } else if (_scale_factor > 4.0) {
00569
00570
00571 do {
00572 if (_output_ysize < _output_xsize) {
00573 _output_ysize *= 2;
00574 } else {
00575 _output_xsize *= 2;
00576 }
00577 sane = choose_scale_factor();
00578 } while (!sane || _scale_factor > 4.0);
00579 }
00580 }
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591 void EggMakeFont::
00592 unsmooth_rgb(PNMImage &image) {
00593 for (int y = 0; y < image.get_y_size(); y++) {
00594 for (int x = 0; x < image.get_x_size(); x++) {
00595 double alpha = image.get_alpha(x, y);
00596 if (alpha != 0.0) {
00597 image.set_xel(x, y, image.get_xel(x, y) / alpha);
00598 }
00599 }
00600 }
00601 }
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611 string EggMakeFont::
00612 expand_hyphen(const string &str) {
00613 string result;
00614 size_t last = 0;
00615
00616 size_t hyphen = str.find('-', last + 1);
00617 while (hyphen < str.length() - 1) {
00618 size_t ap = hyphen - 1;
00619 size_t zp = hyphen + 1;
00620 result += str.substr(last, ap - last);
00621 char a = str[ap];
00622 char z = str[zp];
00623
00624 for (char i = a; i <= z; i++) {
00625 result += i;
00626 }
00627
00628 last = zp + 1;
00629 hyphen = str.find('-', last + 1);
00630 }
00631
00632 result += str.substr(last);
00633 return result;
00634 }
00635
00636
00637
00638
00639
00640
00641 void EggMakeFont::
00642 run() {
00643 if (_output_image_filename.empty() && has_output_filename()) {
00644 _output_image_filename = get_output_filename();
00645 _output_image_filename.set_extension("rgb");
00646 }
00647
00648 if (_output_image_filename.empty()) {
00649 nout << "No output image filename given.\n";
00650 exit(1);
00651 }
00652
00653 if (!_only_chars.empty()) {
00654 _only_chars = expand_hyphen(_only_chars);
00655 nout << "Extracting only characters: " << _only_chars << "\n";
00656 if (_small_caps) {
00657 _only_chars = upcase(_only_chars);
00658 }
00659 }
00660
00661 _font = new PkFontFile();
00662 if (!_font->read(_input_font_filename, _get_all, _only_chars)) {
00663 nout << "Unable to read " << _input_font_filename << ".\n";
00664 exit(1);
00665 }
00666
00667 nout << "Placing " << _font->get_num_chars() << " letters.\n";
00668
00669
00670
00671
00672 _font->sort_chars_by_height();
00673
00674
00675
00676 if (_got_scale_factor && _got_output_size) {
00677
00678 if (!consider_scale_factor(_scale_factor)) {
00679 nout << "Ran out of room on font image; try increasing the image "
00680 "size or the scale factor.\n";
00681 exit(1);
00682 }
00683
00684 } else if (_got_output_size) {
00685
00686 choose_scale_factor();
00687
00688 } else if (_got_scale_factor) {
00689
00690
00691 nout << "It is meaningless to specify a scale factor (-sf) without "
00692 "also specifying an image size (-d). Ignoring scale factor.\n";
00693 choose_image_size();
00694
00695 } else {
00696
00697
00698 choose_image_size();
00699 }
00700
00701 _working_poly_pixels = _poly_pixels * _scale_factor;
00702 _output_image.clear(_working_xsize, _working_ysize, _output_zsize);
00703
00704
00705
00706 _use_alpha = (_output_zsize != 3) && (_fg[3] != 1.0 || _bg[3] != 1.0);
00707 if (_use_alpha && _output_zsize == 1) {
00708
00709
00710 _fg[0] = _fg[3];
00711 _bg[0] = _bg[3];
00712 }
00713
00714 _output_image.fill(_bg[0], _bg[1], _bg[2]);
00715 if (_output_image.has_alpha()) {
00716 _output_image.alpha_fill(_bg[3]);
00717 }
00718
00719 _group = new EggGroup();
00720 _data.add_child(_group);
00721 _tref = new EggTexture("chars", _output_image_filename);
00722 _group->add_child(_tref);
00723 _vpool = new EggVertexPool("vpool");
00724 _group->add_child(_vpool);
00725
00726
00727 EggTexture::Format format = EggTexture::F_unspecified;
00728 if (_use_alpha) {
00729 switch (_output_zsize) {
00730 case 1:
00731 format = EggTexture::F_alpha;
00732 break;
00733 case 2:
00734 format = EggTexture::F_luminance_alpha;
00735 break;
00736 case 4:
00737 format = EggTexture::F_rgba;
00738 break;
00739 }
00740 } else {
00741 switch (_output_zsize) {
00742 case 1:
00743 case 2:
00744 format = EggTexture::F_luminance;
00745 break;
00746 case 3:
00747 case 4:
00748 format = EggTexture::F_rgb;
00749 break;
00750 }
00751 }
00752 _tref->set_format(format);
00753
00754
00755
00756 _group->set_switch_flag(true);
00757 _group->set_switch_fps(2.0);
00758
00759
00760 _ppu = _font->get_ds() / (_ds * _scale);
00761
00762
00763 CharLayout::Placements::const_iterator pi;
00764 for (pi = _layout._placements.begin();
00765 pi != _layout._placements.end();
00766 ++pi) {
00767 copy_character(*pi);
00768 }
00769
00770
00771
00772 EggDefs::const_iterator edi;
00773 for (edi = _egg_defs.begin(); edi != _egg_defs.end(); ++edi) {
00774 _group->add_child((*edi).second.p());
00775 }
00776
00777
00778 EggGroup *ds_group = new EggGroup("ds");
00779 _group->add_child(ds_group);
00780 EggVertex *vtx = make_vertex(LPoint2d(0.0, _ds));
00781 EggPoint *point = new EggPoint;
00782 ds_group->add_child(point);
00783 point->add_vertex(vtx);
00784
00785 if (_use_alpha && _output_zsize != 1) {
00786 if (_bg[3] == 0.0) {
00787
00788
00789
00790 _output_image.fill(_fg[0], _fg[1], _fg[2]);
00791
00792 } else if (_bg[3] == 1.0) {
00793
00794 _output_image.fill(_bg[0], _bg[1], _bg[2]);
00795 }
00796 }
00797
00798
00799 nout << "Scale factor is " << _scale_factor << "\n";
00800
00801 if (_no_reduce) {
00802
00803 nout << "Image destination size is " << _output_xsize
00804 << " by " << _output_ysize << " by " << _output_zsize
00805 << "; not reducing.\n";
00806 nout << "Generating " << _working_xsize << " by " << _working_ysize
00807 << " by " << _output_zsize << " image: "
00808 << _output_image_filename << "\n";
00809
00810 _output_image.write(_output_image_filename);
00811
00812 } else if (_output_xsize == _working_xsize &&
00813 _output_ysize == _working_ysize) {
00814
00815 nout << "Generating " << _output_xsize << " by " << _output_ysize
00816 << " by " << _output_zsize << " image: "
00817 << _output_image_filename << "\n";
00818 _output_image.write(_output_image_filename);
00819
00820 } else {
00821
00822
00823 PNMImage small_image(_output_xsize, _output_ysize, _output_zsize);
00824 small_image.gaussian_filter_from(_gaussian_radius, _output_image);
00825
00826
00827 if (_use_alpha && _bg[3] != 0.0 && _bg[3] != 1.0) {
00828
00829
00830 unsmooth_rgb(small_image);
00831 }
00832
00833
00834 nout << "Generating " << _output_xsize << " by " << _output_ysize
00835 << " by " << _output_zsize << " image: "
00836 << _output_image_filename << "\n";
00837 small_image.write(_output_image_filename);
00838 }
00839
00840 write_egg_file();
00841 }
00842
00843
00844 int main(int argc, char *argv[]) {
00845 EggMakeFont prog;
00846 prog.parse_command_line(argc, argv);
00847 prog.run();
00848 return 0;
00849 }