diff --git a/panda/src/text/dynamicTextFont.I b/panda/src/text/dynamicTextFont.I index cb65b07ff6..62e59eb0f5 100644 --- a/panda/src/text/dynamicTextFont.I +++ b/panda/src/text/dynamicTextFont.I @@ -494,10 +494,11 @@ get_bg() const { // cached. // // The color is the desired color of the outline, width -// is the number of pixels beyond the letter that the -// outline extends, and feather is a number in the range -// 0.0 .. 1.0 that controls the softness of the outline. -// Set the width to 0.0 to disable the outline. +// is the number of points beyond the letter that the +// outline extends (a typical font is 10 points high), +// and feather is a number in the range 0.0 .. 1.0 that +// controls the softness of the outline. Set the width +// to 0.0 to disable the outline. // // This should only be called before any characters have // been requested out of the font, or immediately after @@ -531,7 +532,7 @@ get_outline_color() const { // Function: DynamicTextFont::get_outline_width // Access: Published // Description: Returns the width of the outline pixels of the -// font, as the number of pixels beyond each letter. +// font, as the number of points beyond each letter. // See set_outline(). //////////////////////////////////////////////////////////////////// INLINE float DynamicTextFont:: diff --git a/panda/src/text/dynamicTextFont.cxx b/panda/src/text/dynamicTextFont.cxx index f3ef71684a..2e11752ddc 100644 --- a/panda/src/text/dynamicTextFont.cxx +++ b/panda/src/text/dynamicTextFont.cxx @@ -546,7 +546,10 @@ make_glyph(int character, int glyph_index) { PNMImage reduced(int_x_size, int_y_size, PNMImage::CT_grayscale); reduced.quick_filter_from(image); - outline = (int)ceil(_outline_width); + // convert the outline width from points to tex_pixels. + float outline_pixels = _outline_width / _points_per_unit * _tex_pixels_per_unit; + outline = (int)ceil(outline_pixels); + int_x_size += outline * 2; int_y_size += outline * 2; tex_x_size += outline * 2; @@ -564,8 +567,8 @@ make_glyph(int character, int glyph_index) { } } - glyph->make_geom(slot->bitmap_top + outline * _scale_factor, - slot->bitmap_left - outline * _scale_factor, + glyph->make_geom((int)floor(slot->bitmap_top + outline * _scale_factor + 0.5f), + (int)floor(slot->bitmap_left - outline * _scale_factor + 0.5f), advance, _poly_margin, tex_x_size, tex_y_size, _font_pixels_per_unit, _tex_pixels_per_unit); @@ -664,20 +667,26 @@ copy_pnmimage_to_texture(const PNMImage &image, DynamicTextGlyph *glyph) { if (_has_outline) { // Gaussian blur the glyph to generate an outline. PNMImage outline(image.get_x_size(), image.get_y_size(), PNMImage::CT_grayscale); - outline.gaussian_filter_from(_outline_width, image); + float outline_pixels = _outline_width / _points_per_unit * _tex_pixels_per_unit; + outline.gaussian_filter_from(outline_pixels * 0.707, image); + + // Filter the resulting outline to make a harder edge. Square + // _outline_feather first to make the range more visually linear + // (this approximately compensates for the Gaussian falloff of + // the feathered edge). + float f = _outline_feather * _outline_feather; - // Filter the resulting outline to make a harder edge. for (int yi = 0; yi < outline.get_y_size(); yi++) { for (int xi = 0; xi < outline.get_x_size(); xi++) { float v = outline.get_gray(xi, yi); if (v == 0.0f) { // Do nothing. - } else if (v >= _outline_feather) { + } else if (v >= f) { // Clamp to 1. outline.set_gray(xi, yi, 1.0); } else { - // Linearly scale the range 0 .. _outline_feather onto 0 .. 1. - outline.set_gray(xi, yi, v / _outline_feather); + // Linearly scale the range 0 .. f onto 0 .. 1. + outline.set_gray(xi, yi, v / f); } } } diff --git a/panda/src/text/dynamicTextGlyph.cxx b/panda/src/text/dynamicTextGlyph.cxx index f1e36410e4..b3f6b10925 100644 --- a/panda/src/text/dynamicTextGlyph.cxx +++ b/panda/src/text/dynamicTextGlyph.cxx @@ -74,10 +74,9 @@ erase(DynamicTextFont *font) { nassertv(_page != (DynamicTextPage *)NULL); nassertv(_page->has_ram_image()); - int ysizetop = _page->get_y_size() - 1; - int width = _page->get_x_size(); - - _page->fill_region(_x, _y, _x_size, _y_size, font->get_bg()); + _page->fill_region(_x + _margin, + _page->get_y_size() - (_y + _y_size + _margin), + _x_size, _y_size, font->get_bg()); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/text/dynamicTextPage.cxx b/panda/src/text/dynamicTextPage.cxx index eee4609b85..a38e62a128 100644 --- a/panda/src/text/dynamicTextPage.cxx +++ b/panda/src/text/dynamicTextPage.cxx @@ -96,7 +96,7 @@ slot_glyph(int character, int x_size, int y_size, int margin) { //////////////////////////////////////////////////////////////////// void DynamicTextPage:: fill_region(int x, int y, int x_size, int y_size, const Colorf &color) { - nassertv(x >= 0 && x < _x_size && y >= 0 && y < _y_size); + nassertv(x >= 0 && x + x_size <= _x_size && y >= 0 && y + y_size <= _y_size); int num_components = get_num_components(); if (num_components == 1) { // Luminance or alpha. diff --git a/panda/src/text/geomTextGlyph.cxx b/panda/src/text/geomTextGlyph.cxx index e603350b5e..446f67ebe3 100644 --- a/panda/src/text/geomTextGlyph.cxx +++ b/panda/src/text/geomTextGlyph.cxx @@ -42,6 +42,18 @@ GeomTextGlyph(DynamicTextGlyph *glyph, const GeomVertexData *data) : } } +//////////////////////////////////////////////////////////////////// +// Function: GeomTextGlyph::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +GeomTextGlyph:: +GeomTextGlyph(const GeomVertexData *data) : + Geom(data) +{ + // With this constructor, there are no glyphs initially. +} + //////////////////////////////////////////////////////////////////// // Function: GeomTextGlyph::Copy Constructor // Access: Public @@ -146,6 +158,32 @@ copy_primitives_from(const Geom *other) { return true; } +//////////////////////////////////////////////////////////////////// +// Function: GeomTextGlyph::count_geom +// Access: Public +// Description: Records the reference count of the other Geom within +// this Geom, as if the primitives were copied in via +// copy_primitives_from() (but does not actually copy +// any primitives). This is particularly necessary for +// GeomTextGlyph's reference counting mechanism. +// +// Does nothing if the other Geom is not a +// GeomTextGlyph. +//////////////////////////////////////////////////////////////////// +void GeomTextGlyph:: +count_geom(const Geom *other) { + if (other->is_of_type(GeomTextGlyph::get_class_type())) { + const GeomTextGlyph *tother; + DCAST_INTO_V(tother, other); + + Glyphs::const_iterator gi; + for (gi = tother->_glyphs.begin(); gi != tother->_glyphs.end(); ++gi) { + _glyphs.push_back(*gi); + (*gi)->_geom_count++; + } + } +} + //////////////////////////////////////////////////////////////////// // Function: GeomTextGlyph::output // Access: Public, Virtual diff --git a/panda/src/text/geomTextGlyph.h b/panda/src/text/geomTextGlyph.h index f40dcf851c..1e922666bc 100644 --- a/panda/src/text/geomTextGlyph.h +++ b/panda/src/text/geomTextGlyph.h @@ -25,16 +25,17 @@ //////////////////////////////////////////////////////////////////// // Class : GeomTextGlyph // Description : This is a specialization on Geom for containing a -// triangle strip intended to represent a -// DynamicTextGlyph. Its sole purpose is to maintain -// the geom count on the glyph, so we can determine the -// actual usage count on a dynamic glyph (and thus know -// when it is safe to recycle the glyph). +// primitive intended to represent a DynamicTextGlyph. +// Its sole purpose is to maintain the geom count on the +// glyph, so we can determine the actual usage count on +// a dynamic glyph (and thus know when it is safe to +// recycle the glyph). //////////////////////////////////////////////////////////////////// class EXPCL_PANDA_TEXT GeomTextGlyph : public Geom { public: GeomTextGlyph(DynamicTextGlyph *glyph, const GeomVertexData *data); + GeomTextGlyph(const GeomVertexData *data); GeomTextGlyph(const GeomTextGlyph ©); void operator = (const GeomTextGlyph ©); virtual ~GeomTextGlyph(); @@ -42,6 +43,7 @@ public: virtual Geom *make_copy() const; virtual bool copy_primitives_from(const Geom *other); + void count_geom(const Geom *other); virtual void output(ostream &out) const; virtual void write(ostream &out, int indent_level = 0) const; diff --git a/panda/src/text/textAssembler.I b/panda/src/text/textAssembler.I index 7fd6e51126..fb50c42026 100644 --- a/panda/src/text/textAssembler.I +++ b/panda/src/text/textAssembler.I @@ -543,3 +543,20 @@ operator < (const TextAssembler::GeomCollectorKey &other) const { } return _format < other._format; } + +//////////////////////////////////////////////////////////////////// +// Function: TextAssembler::GeomCollector::count_geom +// Access: Public +// Description: If the indicated Geom is a GeomTextGlyph, increments +// its reference count and adds it into this geom. This +// is necessary to keep references to outstanding +// glyphs, so we know when it's safe to recycle +// no-longer-used glyphs. +// +// If the indicated Geom is an ordinary Geom, does +// nothing. +//////////////////////////////////////////////////////////////////// +INLINE void TextAssembler::GeomCollector:: +count_geom(const Geom *geom) { + _geom->count_geom(geom); +} diff --git a/panda/src/text/textAssembler.cxx b/panda/src/text/textAssembler.cxx index 7426510fda..ccfd01ec1e 100644 --- a/panda/src/text/textAssembler.cxx +++ b/panda/src/text/textAssembler.cxx @@ -2221,6 +2221,7 @@ assign_append_to(GeomCollectorMap &geom_collector_map, mi = geom_collector_map.insert(GeomCollectorMap::value_type(key, GeomCollector(vdata->get_format()))).first; } GeomCollector &geom_collector = (*mi).second; + geom_collector.count_geom(geom); // We use this map to keep track of vertex indices we have already // added, so that we don't needlessly duplicate vertices into our @@ -2299,7 +2300,7 @@ copy_graphic_to(PandaNode *node, const RenderState *state, TextAssembler::GeomCollector:: GeomCollector(const GeomVertexFormat *format) : _vdata(new GeomVertexData("merged_geom", format, Geom::UH_static)), - _geom(new Geom(_vdata)) + _geom(new GeomTextGlyph(_vdata)) { } diff --git a/panda/src/text/textAssembler.h b/panda/src/text/textAssembler.h index 1a03158e5c..3700e26017 100644 --- a/panda/src/text/textAssembler.h +++ b/panda/src/text/textAssembler.h @@ -22,7 +22,7 @@ #include "unicodeLatinMap.h" #include "geomNode.h" #include "pointerTo.h" -#include "geom.h" +#include "geomTextGlyph.h" #include "textPropertiesManager.h" #include "textEncoder.h" #include "geomVertexRewriter.h" @@ -200,6 +200,7 @@ private: GeomCollector(const GeomVertexFormat *format); GeomCollector(const GeomCollector ©); + INLINE void count_geom(const Geom *geom); GeomPrimitive *get_primitive(TypeHandle prim_type); int append_vertex(const GeomVertexData *orig_vdata, int orig_row, const LMatrix4f &xform); @@ -207,7 +208,7 @@ private: private: PT(GeomVertexData) _vdata; - PT(Geom) _geom; + PT(GeomTextGlyph) _geom; PT(GeomTriangles) _triangles; PT(GeomLines) _lines; PT(GeomPoints) _points;