Browse Source

add pnmtext

David Rose 22 years ago
parent
commit
6612040c54

+ 25 - 0
panda/src/pnmtext/Sources.pp

@@ -0,0 +1,25 @@
+#define BUILD_DIRECTORY $[HAVE_FREETYPE]
+#define USE_PACKAGES freetype
+
+#define OTHER_LIBS interrogatedb:c dconfig:c dtoolconfig:m \
+                   dtoolutil:c dtoolbase:c dtool:m
+
+#begin lib_target
+  #define USE_PACKAGES freetype
+
+  #define TARGET pnmtext
+  #define LOCAL_LIBS \
+    pnmimage putil linmath
+    
+  #define SOURCES \
+    config_pnmtext.cxx config_pnmtext.h \
+    freetypeFont.cxx freetypeFont.h freetypeFont.I \
+    pnmTextGlyph.cxx pnmTextGlyph.h pnmTextGlyph.I \
+    pnmTextMaker.cxx pnmTextMaker.h pnmTextMaker.I
+
+  #define INSTALL_HEADERS \
+    freetypeFont.h freetypeFont.I \
+    pnmTextGlyph.h pnmTextGlyph.I \
+    pnmTextMaker.h pnmTextMaker.I
+
+#end lib_target

+ 51 - 0
panda/src/pnmtext/config_pnmtext.cxx

@@ -0,0 +1,51 @@
+// Filename: config_pnmtext.cxx
+// Created by:  drose (08Sep03)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "config_pnmtext.h"
+#include "staticTextFont.h"
+
+#include "dconfig.h"
+
+Configure(config_pnmtext);
+NotifyCategoryDef(pnmtext, "");
+
+ConfigureFn(config_pnmtext) {
+  init_libpnmtext();
+}
+
+const float text_point_size = config_pnmtext.GetFloat("text-point-size", 10.0f);
+const float text_pixels_per_unit = config_pnmtext.GetFloat("text-pixels-per-unit", 30.0f);
+const float text_scale_factor = config_pnmtext.GetFloat("text-scale-factor", 2.0f);
+
+////////////////////////////////////////////////////////////////////
+//     Function: init_libpnmtext
+//  Description: Initializes the library.  This must be called at
+//               least once before any of the functions or classes in
+//               this library can be used.  Normally it will be
+//               called by the static initializers and need not be
+//               called explicitly, but special cases exist.
+////////////////////////////////////////////////////////////////////
+void
+init_libpnmtext() {
+  static bool initialized = false;
+  if (initialized) {
+    return;
+  }
+  initialized = true;
+
+}

+ 35 - 0
panda/src/pnmtext/config_pnmtext.h

@@ -0,0 +1,35 @@
+// Filename: config_pnmtext.h
+// Created by:  drose (08Sep03)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef CONFIG_PNMTEXT_H
+#define CONFIG_PNMTEXT_H
+
+#include "pandabase.h"
+#include "notifyCategoryProxy.h"
+
+class DSearchPath;
+
+NotifyCategoryDecl(pnmtext, EXPCL_PANDA, EXPTP_PANDA);
+
+extern const float text_point_size;
+extern const float text_pixels_per_unit;
+extern const float text_scale_factor;
+
+extern EXPCL_PANDA void init_libpnmtext();
+
+#endif

+ 109 - 0
panda/src/pnmtext/pnmTextGlyph.I

@@ -0,0 +1,109 @@
+// Filename: pnmTextGlyph.I
+// Created by:  drose (07Sep03)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: PNMTextGlyph::get_advance
+//       Access: Public
+//  Description: Returns the number of pixels by which the pen should
+//               be advanced after rendering this glyph.
+////////////////////////////////////////////////////////////////////
+INLINE int PNMTextGlyph::
+get_advance() const {
+  return _int_advance;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PNMTextGlyph::get_left
+//       Access: Public
+//  Description: Returns the x coordinate of the leftmost pixel in the
+//               glyph.
+////////////////////////////////////////////////////////////////////
+INLINE int PNMTextGlyph::
+get_left() const {
+  return _left;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PNMTextGlyph::get_right
+//       Access: Public
+//  Description: Returns the x coordinate of the rightmost pixel in the
+//               glyph.
+////////////////////////////////////////////////////////////////////
+INLINE int PNMTextGlyph::
+get_right() const {
+  return _left + _image.get_x_size();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PNMTextGlyph::get_bottom
+//       Access: Public
+//  Description: Returns the y coordinate of the bottommost pixel in
+//               the glyph.
+////////////////////////////////////////////////////////////////////
+INLINE int PNMTextGlyph::
+get_bottom() const {
+  return _top + _image.get_y_size();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PNMTextGlyph::get_top
+//       Access: Public
+//  Description: Returns the y coordinate of the topmost pixel in the
+//               glyph.
+////////////////////////////////////////////////////////////////////
+INLINE int PNMTextGlyph::
+get_top() const {
+  return _top;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PNMTextGlyph::get_height
+//       Access: Public
+//  Description: Returns the height of the glyph in pixels.
+////////////////////////////////////////////////////////////////////
+INLINE int PNMTextGlyph::
+get_height() const {
+  return _image.get_y_size();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PNMTextGlyph::get_width
+//       Access: Public
+//  Description: Returns the width of the glyph in pixels.
+////////////////////////////////////////////////////////////////////
+INLINE int PNMTextGlyph::
+get_width() const {
+  return _image.get_x_size();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PNMTextGlyph::get_value
+//       Access: Public
+//  Description: Returns the value of the indicated pixel of the
+//               glyph.  The result is in the range [0, 1], where 0
+//               indicates the pixel is not part of the glyph, and 1
+//               indicates it is.  Intermediate values are used to
+//               represent antialiasing.
+////////////////////////////////////////////////////////////////////
+INLINE double PNMTextGlyph::
+get_value(int x, int y) const {
+  nassertr(x >= 0 && x < get_width() &&
+           y >= 0 && y < get_height(), 0.0);
+  return _image.get_gray(x, y);
+}

+ 153 - 0
panda/src/pnmtext/pnmTextGlyph.cxx

@@ -0,0 +1,153 @@
+// Filename: pnmTextGlyph.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
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "pnmTextGlyph.h"
+
+////////////////////////////////////////////////////////////////////
+//     Function: PNMTextGlyph::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+PNMTextGlyph::
+PNMTextGlyph(double advance) : 
+  _advance(advance) 
+{
+  _left = 0;
+  _top = 0;
+  _int_advance = (int)floor(_advance + 0.5);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PNMTextGlyph::Destructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+PNMTextGlyph::
+~PNMTextGlyph() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PNMTextGlyph::rescale
+//       Access: Public
+//  Description: After the image has been rendered large by FreeType,
+//               scales it small again for placing.
+////////////////////////////////////////////////////////////////////
+void PNMTextGlyph::
+rescale(double scale_factor) {
+  if (scale_factor == 1.0) {
+    return;
+  }
+  nassertv(scale_factor != 0.0);
+  _advance /= scale_factor;
+  _int_advance = (int)floor(_advance + 0.5);
+
+  if (_image.is_valid()) {
+    int orig_x_size = _image.get_x_size();
+    int orig_y_size = _image.get_y_size();
+    int orig_left = _left;
+    int orig_top = _top;
+
+    // Pad the image by a few pixels all around to allow for
+    // antialiasing at the edges.
+    int extra_pad = (int)ceil(scale_factor);
+    orig_x_size += 2*extra_pad;
+    orig_y_size += 2*extra_pad;
+    orig_left -= extra_pad;
+    orig_top += extra_pad;
+
+    // Now compute the reduced size.
+    int new_x_size = (int)ceil(orig_x_size / scale_factor);
+    int new_y_size = (int)ceil(orig_y_size / scale_factor);
+    int new_left = (int)floor(orig_left / scale_factor);
+    int new_top = (int)ceil(orig_top / scale_factor);
+
+    // And scale those back up so we can determine the amount of
+    // additional padding we need to make the pixels remain in the
+    // right place after the integer reduction.
+    int old_x_size = (int)(new_x_size * scale_factor + 0.5);
+    int old_y_size = (int)(new_y_size * scale_factor + 0.5);
+    int old_left = (int)(new_left * scale_factor + 0.5);
+    int old_top = (int)(new_top * scale_factor + 0.5);
+
+    int pad_left = orig_left - old_left;
+    int pad_top = old_top - orig_top;
+
+    // These shouldn't go negative.
+    nassertv(extra_pad + pad_left >= 0 && extra_pad + pad_top >= 0);
+
+    PNMImage enlarged(old_x_size, old_y_size, 1);
+    enlarged.copy_sub_image(_image, pad_left + extra_pad, pad_top + extra_pad);
+
+    _image.clear(new_x_size, new_y_size, 1);
+    _image.quick_filter_from(enlarged);
+
+    _left = new_left;
+    _top = new_top;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PNMTextGlyph::place
+//       Access: Public
+//  Description: Copies the glyph to the indicated destination image
+//               at the indicated origin.  It colors the glyph pixels
+//               the indicated foreground color, blends antialiased
+//               pixels with the appropriate amount of the foreground
+//               color and the existing background color, and leaves
+//               other pixels alone.
+////////////////////////////////////////////////////////////////////
+void PNMTextGlyph::
+place(PNMImage &dest_image, int xp, int yp, const Colorf &fg) {
+  if (!_image.is_valid()) {
+    // If we have no image, do nothing.
+    return;
+  }
+  RGBColord fg_rgb(fg[0], fg[1], fg[2]);
+  double fg_alpha = fg[3];
+
+  int left = xp + _left;
+  int top = yp - _top;
+  int right = left + _image.get_x_size();
+  int bottom = top + _image.get_y_size();
+
+  // Clip the glyph to the destination image.
+  int cleft = max(left, 0);
+  int ctop = max(top, 0);
+  int cright = min(right, dest_image.get_x_size());
+  int cbottom = min(bottom, dest_image.get_y_size());
+
+  for (int y = ctop; y < cbottom; y++) {
+    for (int x = cleft; x < cright; x++) {
+      double gval = get_value(x - left, y - top);
+      if (gval == 1.0) {
+        dest_image.set_xel(x, y, fg_rgb);
+        if (dest_image.has_alpha()) {
+          dest_image.set_alpha(x, y, fg_alpha);
+        }
+
+      } else if (gval > 0.0) {
+        RGBColord bg_rgb = dest_image.get_xel(x, y);
+        dest_image.set_xel(x, y, fg_rgb * gval + bg_rgb * (1.0 - gval));
+        if (dest_image.has_alpha()) {
+          double bg_alpha = dest_image.get_alpha(x, y);
+          dest_image.set_alpha(x, y, fg_alpha * gval + bg_alpha * (1.0 - gval));
+        }
+      }
+    }
+  }
+}

+ 62 - 0
panda/src/pnmtext/pnmTextGlyph.h

@@ -0,0 +1,62 @@
+// Filename: pnmTextGlyph.h
+// 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
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef PNMTEXTGLYPH_H
+#define PNMTEXTGLYPH_H
+
+#include "pandabase.h"
+
+#include "pnmImage.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : PNMTextGlyph
+// Description : A single glyph in a PNMTextMaker.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDA PNMTextGlyph {
+public:
+  PNMTextGlyph(double advance);
+  ~PNMTextGlyph();
+
+  void rescale(double scale_factor);
+  INLINE int get_advance() const;
+
+  void place(PNMImage &dest_image, int xp, int yp, 
+             const Colorf &fg = Colorf(0.0f, 0.0f, 0.0f, 1.0f));
+
+  INLINE int get_left() const;
+  INLINE int get_right() const;
+  INLINE int get_bottom() const;
+  INLINE int get_top() const;
+
+  INLINE int get_height() const;
+  INLINE int get_width() const;
+  INLINE double get_value(int x, int y) const;
+
+private:
+  PNMImage _image;
+  int _top;
+  int _left;
+  double _advance;
+  int _int_advance;
+
+  friend class PNMTextMaker;
+};
+
+#include "pnmTextGlyph.I"
+
+#endif

+ 64 - 0
panda/src/pnmtext/pnmTextMaker.I

@@ -0,0 +1,64 @@
+// Filename: pnmTextMaker.I
+// Created by:  drose (07Sep03)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: PNMTextMaker::is_valid
+//       Access: Public
+//  Description: Returns true if the PNMTextMaker is valid and ready to
+//               generate text, false otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool PNMTextMaker::
+is_valid() const {
+  return _is_valid;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PNMTextMaker::set_align
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE void PNMTextMaker::
+set_align(PNMTextMaker::Alignment align_type) {
+  if (_align != align_type) {
+    _align = align_type;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PNMTextMaker::get_align
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE 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.
+////////////////////////////////////////////////////////////////////
+INLINE void PNMTextMaker::
+generate_into(const string &text, PNMImage &dest_image, int x, int y) {
+  TextEncoder encoder;
+  encoder.set_text(text);
+  generate_into(encoder.get_wtext(), dest_image, x, y);
+}

+ 186 - 0
panda/src/pnmtext/pnmTextMaker.cxx

@@ -0,0 +1,186 @@
+// Filename: textMaker.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
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "pnmTextMaker.h"
+#include "pnmTextGlyph.h"
+#include "filename.h"
+#include "pnmImage.h"
+
+////////////////////////////////////////////////////////////////////
+//     Function: PNMTextMaker::Constructor
+//       Access: Public
+//  Description: The constructor expects the name of some font file
+//               that FreeType can read, along with face_index,
+//               indicating which font within the file to load
+//               (usually 0).
+////////////////////////////////////////////////////////////////////
+PNMTextMaker::
+PNMTextMaker(const Filename &font_filename, int face_index) {
+  initialize();
+  _is_valid = load_font(font_filename, face_index);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PNMTextMaker::Constructor
+//       Access: Public
+//  Description: This constructor works as above, but it takes the
+//               font data from an in-memory buffer instead of from a
+//               named file.
+////////////////////////////////////////////////////////////////////
+PNMTextMaker::
+PNMTextMaker(const char *font_data, int data_length, int face_index) {
+  initialize();
+  _is_valid = load_font(font_data, data_length, face_index);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PNMTextMaker::Destructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+PNMTextMaker::
+~PNMTextMaker() {
+  empty_cache();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PNMTextMaker::generate_into
+//       Access: Public
+//  Description: Generates text into the indicated image at the
+//               indicated position.
+////////////////////////////////////////////////////////////////////
+void PNMTextMaker::
+generate_into(const wstring &text, PNMImage &dest_image, int x, int y) {
+  // First, measure the total width in pixels.
+  int width = 0;
+  wstring::const_iterator ti;
+  for (ti = text.begin(); ti != text.end(); ++ti) {
+    int ch = (*ti);
+    PNMTextGlyph *glyph = get_glyph(ch);
+    width += glyph->get_advance();
+  }
+
+  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 = (*ti);
+    PNMTextGlyph *glyph = get_glyph(ch);
+    glyph->place(dest_image, xp, yp);
+    xp += glyph->get_advance();
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PNMTextMaker::get_glyph
+//       Access: Public
+//  Description: Returns the glyph for the indicated index, or NULL if
+//               it is not defined in the font.
+////////////////////////////////////////////////////////////////////
+PNMTextGlyph *PNMTextMaker::
+get_glyph(int character) {
+  int glyph_index = FT_Get_Char_Index(_face, character);
+
+  Glyphs::iterator gi;
+  gi = _glyphs.find(glyph_index);
+  if (gi != _glyphs.end()) {
+    return (*gi).second;
+  }
+
+  PNMTextGlyph *glyph = make_glyph(glyph_index);
+  _glyphs.insert(Glyphs::value_type(glyph_index, glyph));
+  return glyph;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PNMTextMaker::initialize
+//       Access: Private
+//  Description: Called from both constructors to set up some initial
+//               values.
+////////////////////////////////////////////////////////////////////
+void PNMTextMaker::
+initialize() {
+  _align = A_left;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PNMTextMaker::make_glyph
+//       Access: Private
+//  Description: Creates a new PNMTextGlyph object for the indicated
+//               index, if possible.
+////////////////////////////////////////////////////////////////////
+PNMTextGlyph *PNMTextMaker::
+make_glyph(int glyph_index) {
+  int error = FT_Load_Glyph(_face, glyph_index, FT_LOAD_RENDER);
+  if (error) {
+    nout << "Unable to render glyph " << glyph_index << "\n";
+    return (PNMTextGlyph *)NULL;
+  }
+
+  FT_GlyphSlot slot = _face->glyph;
+  FT_Bitmap &bitmap = slot->bitmap;
+
+  double advance = slot->advance.x / 64.0;
+
+  if (bitmap.width == 0 || bitmap.rows == 0) {
+    // If we got an empty bitmap, it's a special case.
+    PNMTextGlyph *glyph = new PNMTextGlyph(advance);
+    glyph->rescale(_scale_factor);
+    return glyph;
+
+  } else {
+    PNMTextGlyph *glyph = new PNMTextGlyph(advance);
+    PNMImage &glyph_image = glyph->_image;
+    glyph_image.clear(bitmap.width, bitmap.rows, 1);
+    copy_bitmap_to_pnmimage(bitmap, glyph_image);
+
+    glyph->_top = slot->bitmap_top;
+    glyph->_left = slot->bitmap_left;
+
+    glyph->rescale(_scale_factor);
+    return glyph;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PNMTextMaker::empty_cache
+//       Access: Private
+//  Description: Empties the cache of previously-generated glyphs.
+////////////////////////////////////////////////////////////////////
+void PNMTextMaker::
+empty_cache() {
+  Glyphs::iterator gi;
+  for (gi = _glyphs.begin(); gi != _glyphs.end(); ++gi) {
+    PNMTextGlyph *glyph = (*gi).second;
+    delete glyph;
+  }
+}

+ 82 - 0
panda/src/pnmtext/pnmTextMaker.h

@@ -0,0 +1,82 @@
+// Filename: pnmTextMaker.h
+// 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
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef PNMTEXTMAKER_H
+#define PNMTEXTMAKER_H
+
+#include "pandabase.h"
+#include "pmap.h"
+#include "freetypeFont.h"
+#include "textEncoder.h"
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+class Filename;
+class PNMImage;
+class PNMTextGlyph;
+
+////////////////////////////////////////////////////////////////////
+//       Class : PNMTextMaker
+// Description : This object uses the Freetype library to generate
+//               text directly into an image.  It is different from
+//               the TextNode/DynamicTextFont interface, which use the
+//               Freetype library to generate text in the scene graph,
+//               to be rendered onscreen via the Panda render
+//               traversal.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDA PNMTextMaker : public FreetypeFont {
+public:
+  PNMTextMaker(const Filename &font_filename, int face_index);
+  PNMTextMaker(const char *font_data, int data_length, int face_index);
+  ~PNMTextMaker();
+
+  enum Alignment {
+    A_left,
+    A_right,
+    A_center,
+  };
+
+  INLINE bool is_valid() const;
+
+  INLINE void set_align(Alignment align_type);
+  INLINE Alignment get_align() const;
+
+  INLINE void generate_into(const string &text,
+                            PNMImage &dest_image, int x, int y);
+  void generate_into(const wstring &text,
+                     PNMImage &dest_image, int x, int y);
+
+  PNMTextGlyph *get_glyph(int character);
+
+private:
+  void initialize();
+  PNMTextGlyph *make_glyph(int glyph_index);
+  void empty_cache();
+
+  bool _is_valid;
+
+  typedef pmap<int, PNMTextGlyph *> Glyphs;
+  Glyphs _glyphs;
+
+  Alignment _align;
+};
+
+#include "pnmTextMaker.I"
+
+#endif