From 54563e7a009ed8b31356129447f90ee5c918d616 Mon Sep 17 00:00:00 2001 From: David Rose Date: Mon, 8 Apr 2002 00:36:20 +0000 Subject: [PATCH] add font-samples --- pandaapp/src/indexify/Sources.pp | 17 ++ pandaapp/src/indexify/fontSamples.cxx | 259 +++++++++++++++++++++++++ pandaapp/src/indexify/fontSamples.h | 63 ++++++ pandaapp/src/indexify/indexify.cxx | 3 +- pandaapp/src/indexify/indexify.h | 5 +- pandaapp/src/indexify/pnmTextMaker.cxx | 47 ++++- pandaapp/src/indexify/pnmTextMaker.h | 10 + 7 files changed, 397 insertions(+), 7 deletions(-) create mode 100644 pandaapp/src/indexify/fontSamples.cxx create mode 100644 pandaapp/src/indexify/fontSamples.h diff --git a/pandaapp/src/indexify/Sources.pp b/pandaapp/src/indexify/Sources.pp index fd618b18b3..c97e90064c 100644 --- a/pandaapp/src/indexify/Sources.pp +++ b/pandaapp/src/indexify/Sources.pp @@ -19,3 +19,20 @@ pnmTextMaker.cxx pnmTextMaker.h #end bin_target + +#begin bin_target + #define USE_FREETYPE yes + + #define TARGET font-samples + #define OTHER_LIBS \ + progbase \ + pnmimage:c pnmimagetypes:c panda:m \ + pystub + + #define SOURCES \ + default_font.cxx default_font.h \ + fontSamples.cxx fontSamples.h \ + pnmTextGlyph.cxx pnmTextGlyph.h \ + pnmTextMaker.cxx pnmTextMaker.h + +#end bin_target diff --git a/pandaapp/src/indexify/fontSamples.cxx b/pandaapp/src/indexify/fontSamples.cxx new file mode 100644 index 0000000000..f6bfc09b49 --- /dev/null +++ b/pandaapp/src/indexify/fontSamples.cxx @@ -0,0 +1,259 @@ +// Filename: fontSamples.cxx +// Created by: drose (03Apr02) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#include "fontSamples.h" +#include "pnmTextMaker.h" +#include "default_font.h" +#include "pnmImage.h" + +#include "notify.h" + +//////////////////////////////////////////////////////////////////// +// Function: FontSamples::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +FontSamples:: +FontSamples() { + clear_runlines(); + add_runline("[opts] fontname [fontname ...]"); + + set_program_description + ("Generates one or more image files with one line of text from " + "each of several given font files, as a font sample sheet."); + + add_option + ("t", "text", 0, + "Specifies the sample text to render using each font.", + &FontSamples::dispatch_string, NULL, &_sample_text); + + add_option + ("sh", "height", 0, + "Specifies the pixel height of each sample.", + &FontSamples::dispatch_int, NULL, &_sample_height); + + add_option + ("nf", "filename", 0, + "Specifies the filename of the font to be used to write each font's " + "name.", + &FontSamples::dispatch_filename, NULL, &_name_font_filename); + + add_option + ("nh", "height", 0, + "Specifies the pixel height of each font's name.", + &FontSamples::dispatch_int, NULL, &_name_height); + + add_option + ("fontaa", "factor", 0, + "Specifies a scale factor to apply to the fonts " + "for the purpose of antialiasing the fonts a " + "little better than FreeType can do by itself. The letters are " + "generated large and then scaled to their proper size. Normally this " + "should be a number in the range 3 to 4 for best effect.", + &FontSamples::dispatch_double, NULL, &_font_aa_factor); + + add_option + ("space", "y", 0, + "Specifies the vertical space in pixels between font samples.", + &FontSamples::dispatch_int, NULL, &_vert_space); + + add_option + ("image", "x, y", 0, + "Specifies the width and height in pixels of the resulting image(s).", + &FontSamples::dispatch_int_pair, NULL, &_image_width); + + add_option + ("o", "filename", 50, + "Specify the filename(s) to which the resulting image file will " + "be written. This should contain the string '%d' which will be " + "filled in with the index number of the particular frame.", + &FontSamples::dispatch_string, NULL, &_output_filename); + + _sample_text = "The quick brown fox jumped over the lazy dog's back."; + _sample_height = 14; + _name_height = 10; + _font_aa_factor = 4.0; + _vert_space = 10; + _image_width = 600; + _image_height = 600; + _output_filename = "samples-%d.jpg"; + _name_text_maker = (PNMTextMaker *)NULL; +} + +//////////////////////////////////////////////////////////////////// +// Function: FontSamples::Destructor +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +FontSamples:: +~FontSamples() { + if (_name_text_maker != (PNMTextMaker *)NULL) { + delete _name_text_maker; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: FontSamples::handle_args +// Access: Protected, Virtual +// Description: Does something with the additional arguments on the +// command line (after all the -options have been +// parsed). Returns true if the arguments are good, +// false otherwise. +//////////////////////////////////////////////////////////////////// +bool FontSamples:: +handle_args(ProgramBase::Args &args) { + if (args.empty()) { + nout << "You must specify the font filenames on the command line.\n"; + return false; + } + + Args::const_iterator ai; + for (ai = args.begin(); ai != args.end(); ++ai) { + Filename filename = Filename::from_os_specific(*ai); + filename.standardize(); + if (filename.exists()) { + _font_filenames.push_back(filename); + + } else { + nout << filename << " does not exist.\n"; + return false; + } + } + + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: FontSamples::post_command_line +// Access: Protected, Virtual +// Description: This is called after the command line has been +// completely processed, and it gives the program a +// chance to do some last-minute processing and +// validation of the options and arguments. It should +// return true if everything is fine, false if there is +// an error. +//////////////////////////////////////////////////////////////////// +bool FontSamples:: +post_command_line() { + if (_font_filenames.empty()) { + nout << "No font filenames.\n"; + return false; + } + + if (_name_height != 0) { + if (!_name_font_filename.empty()) { + _name_text_maker = new PNMTextMaker(_name_font_filename, 0); + if (!_name_text_maker->is_valid()) { + delete _name_text_maker; + _name_text_maker = (PNMTextMaker *)NULL; + } + } + + if (_name_text_maker == (PNMTextMaker *)NULL) { + _name_text_maker = new PNMTextMaker(default_font, default_font_size, 0); + if (!_name_text_maker->is_valid()) { + nout << "Unable to open default font.\n"; + delete _name_text_maker; + _name_text_maker = (PNMTextMaker *)NULL; + } + } + } + + if (_name_text_maker != (PNMTextMaker *)NULL) { + _name_text_maker->set_pixel_size(_name_height, _font_aa_factor); + } else { + _name_height = 0; + } + + return ProgramBase::post_command_line(); +} + +//////////////////////////////////////////////////////////////////// +// Function: FontSamples::run +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +void FontSamples:: +run() { + int output_index = 1; + PNMImage output_image(_image_width, _image_height, 1); + static const int output_filename_size = 1024; + char output_filename[output_filename_size]; + + bool all_ok = true; + + output_image.fill(1, 1, 1); + int y = _vert_space; + + int vert_per_font = + _sample_height + _name_height + _vert_space; + + Filenames::iterator fi; + for (fi = _font_filenames.begin(); fi != _font_filenames.end(); ++fi) { + if (y > _image_height - vert_per_font) { + // Write out the current image. + snprintf(output_filename, output_filename_size, + _output_filename.c_str(), output_index); + nout << "Writing " << output_filename << "\n"; + if (!output_image.write(output_filename)) { + nout << "Unable to write to " << output_filename << "\n"; + exit(1); + } + output_index++; + output_image.fill(1, 1, 1); + y = _vert_space; + } + const Filename &filename = (*fi); + PNMTextMaker *text_maker = new PNMTextMaker(filename, 0); + if (!text_maker->is_valid()) { + all_ok = false; + } else { + text_maker->set_pixel_size(_sample_height, _font_aa_factor); + text_maker->generate_into(_sample_text, output_image, + 16, y + _sample_height); + if (_name_text_maker != (PNMTextMaker *)NULL) { + string desc = filename.get_basename() + ": " + text_maker->get_name(); + _name_text_maker->generate_into(desc, output_image, + 16, y + _sample_height + _name_height); + } + } + + y += vert_per_font; + delete text_maker; + } + + if (!all_ok) { + exit(1); + } + + snprintf(output_filename, output_filename_size, + _output_filename.c_str(), output_index); + nout << "Writing " << output_filename << "\n"; + if (!output_image.write(output_filename)) { + nout << "Unable to write to " << output_filename << "\n"; + exit(1); + } +} + + +int main(int argc, char *argv[]) { + FontSamples prog; + prog.parse_command_line(argc, argv); + prog.run(); + return 0; +} diff --git a/pandaapp/src/indexify/fontSamples.h b/pandaapp/src/indexify/fontSamples.h new file mode 100644 index 0000000000..27e719d4f1 --- /dev/null +++ b/pandaapp/src/indexify/fontSamples.h @@ -0,0 +1,63 @@ +// Filename: indexify.h +// Created by: drose (07Apr02) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#ifndef FONTSAMPLES_H +#define FONTSAMPLES_H + +#include "pandatoolbase.h" + +#include "programBase.h" +#include "filename.h" +#include "pvector.h" + +class PNMTextMaker; + +//////////////////////////////////////////////////////////////////// +// Class : FontSamples +// Description : A program to generate one or more image files showing +// samples of various fonts. +//////////////////////////////////////////////////////////////////// +class FontSamples : public ProgramBase { +public: + FontSamples(); + virtual ~FontSamples(); + +protected: + virtual bool handle_args(Args &args); + virtual bool post_command_line(); + +public: + void run(); + + string _sample_text; + int _sample_height; + int _name_height; + Filename _name_font_filename; + double _font_aa_factor; + int _vert_space; + int _image_width; + int _image_height; + string _output_filename; + + typedef pvector Filenames; + Filenames _font_filenames; + + PNMTextMaker *_name_text_maker; +}; + +#endif diff --git a/pandaapp/src/indexify/indexify.cxx b/pandaapp/src/indexify/indexify.cxx index 415e4c1476..3535c56b58 100644 --- a/pandaapp/src/indexify/indexify.cxx +++ b/pandaapp/src/indexify/indexify.cxx @@ -25,8 +25,6 @@ #include "indexParameters.h" #include "string_utils.h" -#include - //////////////////////////////////////////////////////////////////// // Function: Indexify::Constructor // Access: Public @@ -342,6 +340,7 @@ post_command_line() { if (_text_maker != (PNMTextMaker *)NULL) { _text_maker->set_pixel_size(caption_font_size, _font_aa_factor); + _text_maker->set_align(PNMTextMaker::A_center); } } diff --git a/pandaapp/src/indexify/indexify.h b/pandaapp/src/indexify/indexify.h index cfed8883b7..1796cd4b2d 100644 --- a/pandaapp/src/indexify/indexify.h +++ b/pandaapp/src/indexify/indexify.h @@ -30,7 +30,10 @@ class PNMTextMaker; //////////////////////////////////////////////////////////////////// // Class : Indexify -// Description : +// Description : A program to generate a series of thumbnail images +// and HTML pages to view a number of image files in an +// archive directory, before writing the archive to a +// permanent medium like a CD. //////////////////////////////////////////////////////////////////// class Indexify : public ProgramBase { public: diff --git a/pandaapp/src/indexify/pnmTextMaker.cxx b/pandaapp/src/indexify/pnmTextMaker.cxx index d93c164f4f..ecf56ab726 100644 --- a/pandaapp/src/indexify/pnmTextMaker.cxx +++ b/pandaapp/src/indexify/pnmTextMaker.cxx @@ -89,6 +89,8 @@ PNMTextMaker(const Filename &font_filename, int face_index) { } } } + + _align = A_left; } //////////////////////////////////////////////////////////////////// @@ -141,6 +143,8 @@ PNMTextMaker(const char *font_data, int font_data_size, int face_index) { _scale_factor = 0.0; } } + + _align = A_left; } //////////////////////////////////////////////////////////////////// @@ -192,16 +196,37 @@ set_pixel_size(int pixel_size, double scale_factor) { empty_cache(); } +//////////////////////////////////////////////////////////////////// +// Function: PNMTextMaker::set_align +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void PNMTextMaker:: +set_align(PNMTextMaker::Alignment align_type) { + if (_align != align_type) { + _align = align_type; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: PNMTextMaker::get_align +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +PNMTextMaker::Alignment PNMTextMaker:: +get_align() const { + return _align; +} + //////////////////////////////////////////////////////////////////// // Function: PNMTextMaker::generate_into // Access: Public // Description: Generates text into the indicated image at the -// indicated position. Currently, text is centered -// horizontally, with the baseline on the y position. +// indicated position. //////////////////////////////////////////////////////////////////// void PNMTextMaker:: generate_into(const string &text, PNMImage &dest_image, int x, int y) { - // First, measure the total width in pixels, so we can center. + // First, measure the total width in pixels. int width = 0; string::const_iterator ti; for (ti = text.begin(); ti != text.end(); ++ti) { @@ -210,9 +235,23 @@ generate_into(const string &text, PNMImage &dest_image, int x, int y) { width += glyph->get_advance(); } - int xp = x - (width / 2); + int xp; int yp = y; + switch (_align) { + case A_left: + xp = x; + break; + + case A_center: + xp = x - (width / 2); + break; + + case A_right: + xp = x - width; + break; + } + // Now place the text. for (ti = text.begin(); ti != text.end(); ++ti) { int ch = (unsigned char)(*ti); diff --git a/pandaapp/src/indexify/pnmTextMaker.h b/pandaapp/src/indexify/pnmTextMaker.h index 1ba4421c2f..2d85e9ad6f 100644 --- a/pandaapp/src/indexify/pnmTextMaker.h +++ b/pandaapp/src/indexify/pnmTextMaker.h @@ -41,10 +41,19 @@ public: PNMTextMaker(const char *font_data, int font_data_size, int face_index); ~PNMTextMaker(); + enum Alignment { + A_left, + A_right, + A_center, + }; + bool is_valid() const; void set_pixel_size(int pixel_size, double scale_factor = 1.0); + void set_align(Alignment align_type); + Alignment get_align() const; + void generate_into(const string &text, PNMImage &dest_image, int x, int y); @@ -64,6 +73,7 @@ private: FT_Face _face; double _scale_factor; double _line_height; + Alignment _align; static FT_Library _ft_library; static bool _ft_initialized;