42 set_program_brief(
"generates .egg files with rasterized font glyphs");
43 set_program_description
44 (
"egg-mkfont uses the FreeType library to generate an egg file " 45 "and a series of texture images from a font file " 46 "input, such as a TTF file. The resulting egg file " 47 "can be loaded in Panda as a font for rendering text, even " 48 "if FreeType is not compiled into the executing Panda.\n\n" 50 "egg-mkfont will normally run the generated egg file through " 51 "egg-palettize automatically as part of the generation process. " 52 "This collects the individual glyph textures into a small number " 53 "of texture maps. If you intend to run the font through egg-palettize " 54 "yourself later, you may choose to omit this step.");
57 add_runline(
"[opts] -o output.egg font");
58 add_runline(
"[opts] font output.egg");
61 (
"fg",
"r,g,b[,a]", 0,
62 "Specifies the foreground color of the generated texture map. The " 63 "default is white: 1,1,1,1, which leads to the most flexibility " 64 "as the color can be modulated at runtime to any suitable color.",
65 &EggMakeFont::dispatch_color,
nullptr, &_fg[0]);
68 (
"bg",
"r,g,b[,a]", 0,
69 "Specifies the background color of the generated texture map. The " 70 "default is transparent: 1,1,1,0, which allows the text to be " 71 "visible against any color background by placing a polygon of a " 72 "suitable color behind it. If the alpha component of either -fg " 73 "or -bg is not 1, the generated texture images will include an " 74 "alpha component; if both colors specify an alpha component of 1 " 75 "(or do not specify an alpha compenent), then the generated images " 76 "will not include an alpha component.",
77 &EggMakeFont::dispatch_color,
nullptr, &_bg[0]);
80 (
"interior",
"r,g,b[,a]", 0,
81 "Specifies the color to render the interior part of a hollow font. " 82 "This is a special effect that involves analysis of the bitmap after " 83 "the font has been rendered, and so is more effective when the pixel " 84 "size is large. It also implies -noaa (but you can use a scale " 85 "factor with -sf to achieve antialiasing).",
86 &EggMakeFont::dispatch_color, &_got_interior, &_interior[0]);
90 "Specifies the characters of the font that are used. The range " 91 "specification may include combinations of decimal or hex unicode " 92 "values (where hex values are identified with a leading 0x), separated " 93 "by commas and hyphens to indicate ranges, e.g. '32-126,0xfa0-0xfff'. " 94 "It also may specify ranges of ASCII characters by enclosing them " 95 "within square brackets, e.g. '[A-Za-z0-9]'. If this is not specified, " 96 "the default set has all ASCII characters and an assorted set of " 97 "latin-1 characters, diacritics and punctuation marks.",
98 &EggMakeFont::dispatch_range,
nullptr, &_range);
101 (
"extra",
"file.egg", 0,
102 "Specifies additional externally-painted glyphs to mix into the " 103 "generated egg file. The named egg file is expected to contain one " 104 "or more groups, each of which is named with the decimal unicode " 105 "number of a character and should contain one polygon. These groups " 106 "are simply copied into the output egg file as if they were generated " 107 "locally. This option may be repeated.",
108 &EggMakeFont::dispatch_vector_string,
nullptr, &_extra_filenames);
112 "Specify the pixels per unit. This is the number of pixels in the " 113 "generated texture map that are used for each onscreen unit (or each " 114 "10 points of font; see -ps). Setting this number larger results in " 115 "an easier-to-read font, but at the cost of more texture memory. " 116 "The default is 40.",
117 &EggMakeFont::dispatch_double,
nullptr, &_pixels_per_unit);
121 "Specify the point size of the resulting font. This controls the " 122 "apparent size of the font when it is rendered onscreen. By convention, " 123 "a 10 point font is 1 screen unit high, so the default is 10.",
124 &EggMakeFont::dispatch_double,
nullptr, &_point_size);
128 "If this is set, a signed distance field will be generated, which " 129 "results in crisp text even when the text is enlarged or zoomed in.",
130 &EggMakeFont::dispatch_true,
nullptr, &_generate_distance_field);
134 "The number of extra pixels around a single character in the " 135 "generated polygon. This may be a floating-point number. The " 137 &EggMakeFont::dispatch_double,
nullptr, &_poly_margin);
141 "The number of extra pixels around each character in the texture map. " 142 "This may only be an integer. The default is 2. This is meaningful " 143 "when -nopal is also used; in the normal case, use -pm to control " 144 "both the polygon size and the texture map spacing.",
145 &EggMakeFont::dispatch_int,
nullptr, &_tex_margin);
149 "The amount of padding in screen units to place around the glyph when " 150 "rendered. This differs from -pm in that it has no effect on the " 151 "generated texture map, only on the generated egg. Use this in order to " 152 "space the characters out in case they appear to be too close together " 153 "when rendered. The default is 0.",
154 &EggMakeFont::dispatch_double,
nullptr, &_render_margin);
158 "The scale factor of the generated image. This is the factor by which " 159 "the font image is generated oversized, then reduced to its final size, " 160 "to improve antialiasing. If the specified font contains one " 161 "or more fixed-size fonts instead of a scalable font, the scale factor " 162 "may be automatically adjusted as necessary to scale the closest-" 163 "matching font to the desired pixel size. The default is 2.",
164 &EggMakeFont::dispatch_double, &_got_scale_factor, &_scale_factor);
168 "Disable low-level antialiasing by the Freetype library. " 169 "This is unrelated to the antialiasing that is applied due to the " 170 "scale factor specified by -sf; you may have either one, neither, or " 171 "both kinds of antialiasing enabled.",
172 &EggMakeFont::dispatch_none, &_no_native_aa);
176 "Don't run egg-palettize automatically on the output file, but " 177 "just output the raw egg file and all of its individual texture " 178 "images, one for each glyph.",
179 &EggMakeFont::dispatch_none, &_no_palettize);
183 "Don't actually reduce the images after applying the scale factor, but " 184 "leave them at their inflated sizes. Presumably you will reduce " 185 "them later, for instance with egg-palettize.",
186 &EggMakeFont::dispatch_none, &_no_reduce);
190 "The pattern to be used to generate the glyph texture images. This " 191 "string will be passed to sprintf to generate the actual file name; it " 192 "should contain the string %d or %x (or some variant such as %03d) " 193 "which will be filled in with the Unicode number of each symbol. " 194 "If it is omitted, the default is based on the name of the egg file. " 195 "This is used only if -nopal is specified; in the normal case, " 196 "without -nopal, use -pp instead.",
197 &EggMakeFont::dispatch_string,
nullptr, &_output_glyph_pattern);
201 "The pattern to be used to generate the palette texture images. This " 202 "string is effectively passed to egg-palettize as the -tn option, and " 203 "thus should contain %i for the palette index number. This is used " 204 "if -nopal is not specified.",
205 &EggMakeFont::dispatch_string,
nullptr, &_output_palette_pattern);
208 (
"palsize",
"xsize,ysize", 0,
209 "Specify the size of the palette texture images. This is used if " 210 "-nopal is not specified.",
211 &EggMakeFont::dispatch_int_pair,
nullptr, _palette_size);
215 "Specify the face index of the particular face within the font file " 216 "to use. Some font files contain multiple faces, indexed beginning " 217 "at 0. The default is face 0.",
218 &EggMakeFont::dispatch_int,
nullptr, &_face_index);
220 _fg.set(1.0, 1.0, 1.0, 1.0);
221 _bg.set(1.0, 1.0, 1.0, 0.0);
222 _interior.set(1.0, 1.0, 1.0, 1.0);
223 _pixels_per_unit = 40.0;
227 _render_margin = 0.0;
228 _palette_size[0] = _palette_size[1] = 512;
230 _generate_distance_field =
false;
232 _text_maker =
nullptr;
246 nout <<
"Must specify name of font file on command line.\n";
250 _input_font_filename = args[0];
252 return EggWriter::handle_args(args);
266 _text_maker =
new PNMTextMaker(_input_font_filename, _face_index);
272 _no_native_aa =
true;
275 if (!_got_scale_factor) {
278 if (_generate_distance_field) {
280 }
else if (_no_native_aa) {
287 _text_maker->set_point_size(_point_size);
288 _text_maker->set_native_antialias(!_no_native_aa);
290 _text_maker->set_pixels_per_unit(_pixels_per_unit);
291 _text_maker->set_scale_factor(_scale_factor);
295 _pixels_per_unit = _text_maker->get_pixels_per_unit();
296 _scale_factor = _text_maker->get_scale_factor();
298 if (_text_maker->get_font_pixel_size() != 0) {
299 nout <<
"Using " << _text_maker->get_font_pixel_size() <<
"-pixel font.\n";
305 _palettize_scale_factor = _scale_factor;
306 if (_scale_factor != 1.0 && (_no_reduce || !_no_palettize)) {
314 _tex_margin = (int)(_tex_margin * _scale_factor);
315 _poly_margin *= _scale_factor;
316 _pixels_per_unit *= _scale_factor;
318 _text_maker->set_pixels_per_unit(_pixels_per_unit);
319 _text_maker->set_scale_factor(1.0);
326 _palette_size[0] = (int)(_palette_size[0] * _palettize_scale_factor);
327 _palette_size[1] = (int)(_palette_size[1] * _palettize_scale_factor);
328 _palettize_scale_factor = 1.0;
333 _range.add_range(0x20, 0x7e);
335 _range.add_singleton(0xa1);
336 _range.add_singleton(0xa9);
337 _range.add_singleton(0xab);
339 _range.add_singleton(0xb0);
340 _range.add_singleton(0xb5);
341 _range.add_singleton(0xb8);
342 _range.add_singleton(0xbb);
343 _range.add_singleton(0xbf);
345 _range.add_singleton(0xc6);
346 _range.add_singleton(0xc7);
349 _range.add_singleton(0xdf);
350 _range.add_singleton(0xe6);
351 _range.add_singleton(0xe7);
352 _range.add_singleton(0xf0);
353 _range.add_singleton(0xf8);
354 _range.add_singleton(0xfe);
359 _range.add_singleton(0x0131);
360 _range.add_singleton(0x0237);
363 _range.add_range(0x2018, 0x201f);
365 _range.add_singleton(0x2026);
368 _range.add_range(0x0300, 0x030f);
370 if (_output_glyph_pattern.empty()) {
374 if (_output_palette_pattern.empty()) {
381 bool needs_alpha = (_fg[3] != 1.0 || _bg[3] != 1.0 || _interior[3] != 1.0);
382 bool needs_color = (_fg[0] != _fg[1] || _fg[1] != _fg[2] ||
383 _bg[0] != _bg[1] || _bg[1] != _bg[2] ||
384 _interior[0] != _interior[1] || _interior[1] != _interior[2]);
389 _format = EggTexture::F_rgba;
391 if (_fg[0] == 1.0 && _bg[0] == 1.0 && _interior[0] == 1.0) {
394 _fg[0] = _fg[1] = _fg[2] = _fg[3];
395 _bg[0] = _bg[1] = _bg[2] = _bg[3];
396 _interior[0] = _interior[1] = _interior[2] = _interior[3];
398 _format = EggTexture::F_alpha;
401 _format = EggTexture::F_luminance_alpha;
407 _format = EggTexture::F_rgb;
410 _format = EggTexture::F_luminance;
418 pal->_generated_image_pattern = _output_palette_pattern;
419 pal->_omit_solitary =
false;
420 pal->_round_uvs =
false;
425 sprintf(buffer,
":margin 0;:coverage 1000;:background %f %f %f %f;:palette %d %d;*: %f%% keep-format",
426 _bg[0], _bg[1], _bg[2], _bg[3],
427 _palette_size[0], _palette_size[1],
428 100.0 / _palettize_scale_factor);
429 std::istringstream txa_script(buffer);
439 egg_data->add_child(_group);
440 append_command_comment(egg_data);
447 _group->set_switch_flag(
true);
448 _group->set_switch_fps(2.0);
450 double margin = _poly_margin;
451 if (_generate_distance_field) {
456 if (_poly_margin >= 1) {
468 EggVertex *vtx = make_vertex(LPoint2d(margin / _pixels_per_unit, _text_maker->get_line_height()));
476 add_character(ri.get_code());
480 if (!_extra_filenames.empty()) {
481 vector_string::const_iterator si;
482 for (si = _extra_filenames.begin(); si != _extra_filenames.end(); ++si) {
483 add_extra_glyphs(*si);
490 Textures::iterator ti;
491 for (ti = _textures.begin(); ti != _textures.end(); ++ti) {
521 dispatch_range(
const string &,
const string &arg,
void *var) {
531 make_vertex(
const LPoint2d &xy) {
534 LVector3d::rfu(xy[0], 0.0, xy[1], _coordinate_system));
541 add_character(
int code) {
543 if (glyph ==
nullptr) {
544 nout <<
"No definition in font for character " << code <<
".\n";
548 make_geom(glyph, code);
558 string group_name = format_string(character);
563 int bitmap_top = glyph->
get_top();
564 int bitmap_left = glyph->
get_left();
568 double poly_margin = _poly_margin;
569 double x_origin = _tex_margin;
570 double y_origin = _tex_margin;
571 double page_y_size = tex_y_size + _tex_margin * 2;
572 double page_x_size = tex_x_size + _tex_margin * 2;
575 double tex_poly_margin = poly_margin / _pixels_per_unit;
576 double origin_y = bitmap_top / _pixels_per_unit;
577 double origin_x = bitmap_left / _pixels_per_unit;
578 double top = origin_y + tex_poly_margin;
579 double left = origin_x - tex_poly_margin;
580 double bottom = origin_y - tex_y_size / _pixels_per_unit - tex_poly_margin;
581 double right = origin_x + tex_x_size / _pixels_per_unit + tex_poly_margin;
584 double uv_top = 1.0f - (double)(y_origin - poly_margin) / page_y_size;
585 double uv_left = (double)(x_origin - poly_margin) / page_x_size;
586 double uv_bottom = 1.0f - (double)(y_origin + poly_margin + tex_y_size) / page_y_size;
587 double uv_right = (double)(x_origin + poly_margin + tex_x_size) / page_x_size;
590 EggVertex *v1 = make_vertex(LPoint2d(left, bottom));
591 EggVertex *v2 = make_vertex(LPoint2d(right, bottom));
592 EggVertex *v3 = make_vertex(LPoint2d(right, top));
593 EggVertex *v4 = make_vertex(LPoint2d(left, top));
595 v1->
set_uv(LTexCoordd(uv_left, uv_bottom));
596 v2->
set_uv(LTexCoordd(uv_right, uv_bottom));
597 v3->
set_uv(LTexCoordd(uv_right, uv_top));
598 v4->
set_uv(LTexCoordd(uv_left, uv_top));
612 EggVertex *v0 = make_vertex(LPoint2d(glyph->
get_advance() / _pixels_per_unit + _render_margin, 0.0));
615 point->add_vertex(v0);
624 TRefs::iterator ti = _trefs.find(glyph);
625 if (ti != _trefs.end()) {
629 EggTexture *tref = make_tref(glyph, character);
630 _trefs[glyph] = tref;
641 sprintf(buffer, _output_glyph_pattern.c_str(), character);
645 glyph->
get_height() + _tex_margin * 2, _num_channels);
646 image.
fill(_bg[0], _bg[1], _bg[2]);
647 if (image.has_alpha()) {
648 image.alpha_fill(_bg[3]);
652 glyph->
get_top() + _tex_margin, _fg, _interior);
655 glyph->
get_top() + _tex_margin, _fg);
662 string name = texture_filename.get_basename_wo_extension();
664 _textures.push_back(texture);
671 tref->set_format(_format);
672 tref->set_wrap_mode(EggTexture::WM_clamp);
673 tref->set_minfilter(EggTexture::FT_linear_mipmap_linear);
674 tref->set_magfilter(EggTexture::FT_linear);
675 tref->set_quality_level(EggTexture::QL_best);
685 add_extra_glyphs(
const Filename &extra_filename) {
688 if (!extra_data->read(extra_filename)) {
701 if (egg_group->
is_of_type(EggGroup::get_class_type())) {
703 if (is_numeric(group->get_name())) {
711 EggGroupNode::iterator ci;
712 for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
714 if (child->
is_of_type(EggGroupNode::get_class_type())) {
725 is_numeric(
const string &str) {
730 string::const_iterator si;
731 for (si = str.begin(); si != str.end(); ++si) {
740 int main(
int argc,
char *argv[]) {
bool write(const PNMImage &image) const
Writes out the image in the indicated PNMImage to the _filename and/or _alpha_filename.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
int get_advance() const
Returns the number of pixels by which the pen should be advanced after rendering this glyph.
The name of this class derives from the fact that we originally implemented it as a layer on top of t...
TextureImage * get_texture(const std::string &name)
Returns the TextureImage with the given name.
virtual void parse_command_line(int argc, char **argv)
Dispatches on each of the options on the command line, and passes the remaining parameters to handle_...
This is the main engine behind egg-palettize.
A base class for nodes in the hierarchy that are not leaf nodes.
bool is_empty() const
Returns true if there are no codes described in the range.
SourceTextureImage * get_source(const Filename &filename, const Filename &alpha_filename, int alpha_file_channel)
Returns the SourceTextureImage corresponding to the given filename(s).
Defines a texture map that may be applied to geometry.
void process_all(bool force_texture_read, const Filename &state_filename)
Reprocesses all textures known.
void set_texture(EggTexture *texture)
Replaces the current list of textures with the indicated texture.
bool parse_parameter(const std::string ¶m)
Parses a string of comma- and hyphen-delimited unicode values, in decimal and/or hex,...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Walks through all the Unicode characters described by a RangeDescription class.
This program uses FreeType to generate an egg file and a series of texture images from a font file in...
This is the primary interface into all the egg data, and the root of the egg file structure.
This object uses the Freetype library to generate text directly into an image.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A single point, or a collection of points as defined by a single <PointLight> entry.
int get_top() const
Returns the y coordinate of the topmost pixel in the glyph.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggVertex * make_new_vertex()
Allocates and returns a new vertex from the pool.
int get_height() const
Returns the height of the glyph in pixels.
Filename get_output_filename() const
If has_output_filename() returns true, this is the filename that the user specified.
int get_left() const
Returns the x coordinate of the leftmost pixel in the glyph.
void read_txa_file(std::istream &txa_file, const std::string &txa_filename)
Reads in the .txa file and keeps it ready for matching textures and egg files.
bool has_output_filename() const
Returns true if the user specified an output filename, false otherwise (e.g.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
The main glue of the egg hierarchy, this corresponds to the <Group>, <Instance>, and <Joint> type nod...
bool set_filename(PaletteGroup *group, const std::string &basename)
Sets the filename, and if applicable, the alpha_filename, from the indicated basename.
void set_distance_field_radius(int radius)
If this is set to something other than 0, Panda will generate a signed distance field with the given ...
bool from_command_line(EggData *data, const Filename &source_filename, const Filename &dest_filename, const std::string &egg_comment)
Accepts the information about the egg file as supplied from the command line.
void place(PNMImage &dest_image, int xp, int yp, const LColor &fg)
Copies the glyph to the indicated destination image at the indicated origin.
The name of a file, such as a texture file or an Egg file.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void all_params_set()
Called after all command line parameters have been set up, this is a hook to do whatever initializati...
Any one-, two-, three-, or four-component vertex, possibly with attributes such as a normal.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
int get_width() const
Returns the width of the glyph in pixels.
void steal_children(EggGroupNode &other)
Moves all the children from the other node to this one.
bool write_eggs()
Adjusts the egg files to reference the newly generated textures, and writes them out.
void set_header(const PNMImageHeader &header)
Sets the header information associated with this image, as if it were loaded from the disk.
std::string get_exec_command() const
Returns the command that invoked this program, as a shell-friendly string, suitable for pasting into ...
void set_alpha_mode(AlphaMode mode)
Specifies precisely how the transparency for this geometry should be achieved, or if it should be use...
void generate_images(bool redo_all)
Actually generates the appropriate palette and unplaced texture images into the map directories.
This is a texture image reference as it appears in an egg file: the source image of the texture.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void set_interior_flag(bool interior_flag)
Sets the flag that indicates whether the interior of hollow fonts is identified as a preprocess as ea...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
std::string get_basename() const
Returns the basename part of the filename.
EggNode * add_child(EggNode *node)
Adds the indicated child to the group and returns it.
void set_source_image(const PNMImage &image)
Accepts the indicated source image as if it had been read from disk.
bool is_valid() const
Returns true if the PNMTextMaker is valid and ready to generate text, false otherwise.
const PNMImage & read_source_image()
Reads in the original image, if it has not already been read, and returns it.
A base class for things that may be directly added into the egg hierarchy.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A single glyph in a PNMTextMaker.
This is the base class for a program that generates an egg file output, but doesn't read any for inpu...
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
This represents a single source texture that is referenced by one or more egg files.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void optimal_resize()
Attempts to resize each PalettteImage down to its smallest possible size.
void fill(float red, float green, float blue)
Sets the entire image (except the alpha channel) to the given color.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void add_command_line_egg(EggFile *egg_file)
Adds the indicated EggFile to the list of eggs that are considered to have been read on the command l...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
std::ostream & get_output()
Returns an output stream that corresponds to the user's intended egg file output–either stdout,...
void set_uv(const LTexCoordd &texCoord)
Replaces the unnamed UV coordinate pair on the vertex with the indicated value.
A collection of vertices.
EggVertex * add_vertex(EggVertex *vertex)
Adds the indicated vertex to the end of the primitive's list of vertices, and returns it.
This describes a sparse range of Unicode character codes for conversion that may be specified on the ...
std::string get_fullpath_wo_extension() const
Returns the full filename–directory and basename parts–except for the extension.
This represents a single egg file known to the palettizer.
PNMTextGlyph * get_glyph(int character)
Returns the glyph for the indicated index, or NULL if it is not defined in the font.
static void set_rel_dirname(const Filename &rel_dirname)
Sets the name of the directory that texture filenames will be written relative to,...
EggFile * get_egg_file(const std::string &name)
Returns the EggFile with the given name.