fix some font issues

This commit is contained in:
David Rose 2009-01-17 20:31:00 +00:00
parent 66619e5251
commit 864dac0290
9 changed files with 94 additions and 26 deletions

View File

@ -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::

View File

@ -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);
}
}
}

View File

@ -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());
}
////////////////////////////////////////////////////////////////////

View File

@ -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.

View File

@ -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

View File

@ -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 &copy);
void operator = (const GeomTextGlyph &copy);
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;

View File

@ -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);
}

View File

@ -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))
{
}

View File

@ -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 &copy);
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;