mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-01 09:23:03 -04:00
generate cheesy accents if font doesn't have them
This commit is contained in:
parent
7421fe3e05
commit
5b7526d3a0
@ -23,7 +23,8 @@
|
||||
stringDecoder.I stringDecoder.h \
|
||||
textFont.I textFont.h \
|
||||
textGlyph.I textGlyph.h \
|
||||
textNode.I textNode.h textNode.cxx
|
||||
textNode.I textNode.h textNode.cxx \
|
||||
unicodeLatinMap.h
|
||||
|
||||
#define INCLUDED_SOURCES \
|
||||
config_text.cxx \
|
||||
@ -35,7 +36,8 @@
|
||||
geomTextGlyph.cxx \
|
||||
stringDecoder.cxx \
|
||||
staticTextFont.cxx \
|
||||
textFont.cxx textGlyph.cxx
|
||||
textFont.cxx textGlyph.cxx \
|
||||
unicodeLatinMap.cxx
|
||||
|
||||
#define INSTALL_HEADERS \
|
||||
config_text.h \
|
||||
@ -48,9 +50,10 @@
|
||||
stringDecoder.I stringDecoder.h \
|
||||
textFont.I textFont.h \
|
||||
textGlyph.I textGlyph.h \
|
||||
textNode.I textNode.h
|
||||
textNode.I textNode.h \
|
||||
unicodeLatinMap.h
|
||||
|
||||
|
||||
#define IGATESCAN all
|
||||
|
||||
#end lib_target
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "dynamicTextFont.h"
|
||||
#include "dynamicTextPage.h"
|
||||
#include "geomTextGlyph.h"
|
||||
#include "unicodeLatinMap.h"
|
||||
|
||||
#include "dconfig.h"
|
||||
|
||||
|
@ -118,67 +118,6 @@ get_scale_factor() const {
|
||||
return _scale_factor;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DynamicTextFont::set_small_caps
|
||||
// Access: Published
|
||||
// Description: Sets the small_caps flag. When this is set,
|
||||
// lowercase letters are generated as scaled-down
|
||||
// versions of their uppercase equivalents. This is
|
||||
// particularly useful to set for fonts that do not have
|
||||
// lowercase letters.
|
||||
//
|
||||
// It is also a good idea to set this for a font that
|
||||
// has already implemented lowercase letters as
|
||||
// scaled-down versions of their uppercase equivalents,
|
||||
// since without this flag the texture memory may
|
||||
// needlessly duplicate equivalent glyphs for upper and
|
||||
// lowercase letters. Setting this flag causes the
|
||||
// texture memory to share the mixed-case letters.
|
||||
//
|
||||
// The amount by which the lowercase letters are scaled
|
||||
// is specified by set_small_caps_scale().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void DynamicTextFont::
|
||||
set_small_caps(bool small_caps) {
|
||||
_small_caps = small_caps;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DynamicTextFont::get_small_caps
|
||||
// Access: Published
|
||||
// Description: Returns the small_caps flag. See set_small_caps().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool DynamicTextFont::
|
||||
get_small_caps() const {
|
||||
return _small_caps;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DynamicTextFont::set_small_caps_scale
|
||||
// Access: Published
|
||||
// Description: Sets the scale factor applied to lowercase letters
|
||||
// from their uppercase equivalents, when the small_caps
|
||||
// flag is in effect. See set_small_caps(). Normally,
|
||||
// this will be a number less than one.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void DynamicTextFont::
|
||||
set_small_caps_scale(float small_caps_scale) {
|
||||
_small_caps_scale = small_caps_scale;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DynamicTextFont::get_small_caps_scale
|
||||
// Access: Published
|
||||
// Description: Returns the scale factor applied to lowercase letters
|
||||
// from their uppercase equivalents, when the small_caps
|
||||
// flag is in effect. See set_small_caps() and
|
||||
// set_small_caps_scale().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE float DynamicTextFont::
|
||||
get_small_caps_scale() const {
|
||||
return _small_caps_scale;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DynamicTextFont::set_texture_margin
|
||||
// Access: Published
|
||||
|
@ -325,20 +325,12 @@ write(ostream &out, int indent_level) const {
|
||||
// printable glyph.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool DynamicTextFont::
|
||||
get_glyph(int character, const TextGlyph *&glyph, float &glyph_scale) {
|
||||
get_glyph(int character, const TextGlyph *&glyph) {
|
||||
if (!_is_valid) {
|
||||
glyph = (TextGlyph *)NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
glyph_scale = 1.0f;
|
||||
if (character < 128 && islower(character) && get_small_caps()) {
|
||||
// If we have small_caps on, we implement lowercase letters by
|
||||
// applying a scale to the corresponding uppercase letter.
|
||||
glyph_scale = get_small_caps_scale();
|
||||
character = toupper(character);
|
||||
}
|
||||
|
||||
int glyph_index = FT_Get_Char_Index(_face, character);
|
||||
|
||||
Cache::iterator ci = _cache.find(glyph_index);
|
||||
@ -368,8 +360,6 @@ initialize() {
|
||||
_point_size = text_point_size;
|
||||
_tex_pixels_per_unit = text_pixels_per_unit;
|
||||
_scale_factor = text_scale_factor;
|
||||
_small_caps = text_small_caps;
|
||||
_small_caps_scale = text_small_caps_scale;
|
||||
|
||||
// We don't necessarily want to use mipmaps, since we don't want to
|
||||
// regenerate those every time the texture changes, but we probably
|
||||
|
@ -57,11 +57,6 @@ PUBLISHED:
|
||||
INLINE bool set_scale_factor(float scale_factor);
|
||||
INLINE float get_scale_factor() const;
|
||||
|
||||
INLINE void set_small_caps(bool small_caps);
|
||||
INLINE bool get_small_caps() const;
|
||||
INLINE void set_small_caps_scale(float small_caps_scale);
|
||||
INLINE float get_small_caps_scale() const;
|
||||
|
||||
INLINE void set_texture_margin(int texture_margin);
|
||||
INLINE int get_texture_margin() const;
|
||||
INLINE void set_poly_margin(float poly_margin);
|
||||
@ -91,8 +86,7 @@ PUBLISHED:
|
||||
virtual void write(ostream &out, int indent_level) const;
|
||||
|
||||
public:
|
||||
virtual bool get_glyph(int character, const TextGlyph *&glyph,
|
||||
float &glyph_scale);
|
||||
virtual bool get_glyph(int character, const TextGlyph *&glyph);
|
||||
|
||||
private:
|
||||
void initialize();
|
||||
@ -110,8 +104,6 @@ private:
|
||||
float _tex_pixels_per_unit;
|
||||
float _scale_factor;
|
||||
float _font_pixels_per_unit;
|
||||
bool _small_caps;
|
||||
float _small_caps_scale;
|
||||
int _texture_margin;
|
||||
float _poly_margin;
|
||||
int _page_x_size, _page_y_size;
|
||||
|
@ -35,22 +35,6 @@ DynamicTextGlyph::
|
||||
~DynamicTextGlyph() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DynamicTextGlyph::get_geom
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns a Geom that renders the particular glyph.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PT(Geom) DynamicTextGlyph::
|
||||
get_geom() const {
|
||||
if (_geom == (Geom *)NULL) {
|
||||
return _geom;
|
||||
}
|
||||
|
||||
// A DynamicTextGlyph must make a copy of its GeomTextGlyph, so that
|
||||
// it will increase the reference count properly.
|
||||
return _geom->make_copy();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DynamicTextGlyph::get_row
|
||||
// Access: Public
|
||||
|
@ -45,7 +45,6 @@ private:
|
||||
|
||||
public:
|
||||
virtual ~DynamicTextGlyph();
|
||||
virtual PT(Geom) get_geom() const;
|
||||
|
||||
INLINE bool intersects(int x, int y, int x_size, int y_size) const;
|
||||
unsigned char *get_row(int y);
|
||||
|
@ -162,9 +162,7 @@ write(ostream &out, int indent_level) const {
|
||||
// printable glyph.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool StaticTextFont::
|
||||
get_glyph(int character, const TextGlyph *&glyph, float &glyph_scale) {
|
||||
glyph_scale = 1.0f;
|
||||
|
||||
get_glyph(int character, const TextGlyph *&glyph) {
|
||||
Glyphs::const_iterator gi = _glyphs.find(character);
|
||||
if (gi == _glyphs.end()) {
|
||||
// No definition for this character.
|
||||
|
@ -47,8 +47,7 @@ PUBLISHED:
|
||||
virtual void write(ostream &out, int indent_level) const;
|
||||
|
||||
public:
|
||||
virtual bool get_glyph(int character, const TextGlyph *&glyph,
|
||||
float &glyph_scale);
|
||||
virtual bool get_glyph(int character, const TextGlyph *&glyph);
|
||||
|
||||
private:
|
||||
void find_character_gsets(PandaNode *root, Geom *&ch, GeomPoint *&dot,
|
||||
|
@ -78,14 +78,13 @@ calc_width(int character) {
|
||||
}
|
||||
|
||||
const TextGlyph *glyph;
|
||||
float glyph_scale;
|
||||
get_glyph(character, glyph, glyph_scale);
|
||||
get_glyph(character, glyph);
|
||||
if (glyph == (TextGlyph *)NULL) {
|
||||
// Unknown character.
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
return glyph->get_advance() * glyph_scale;
|
||||
return glyph->get_advance();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
@ -65,8 +65,7 @@ public:
|
||||
wstring wordwrap_to(const wstring &text, float wordwrap_width,
|
||||
bool preserve_trailing_whitespace);
|
||||
|
||||
virtual bool get_glyph(int character, const TextGlyph *&glyph,
|
||||
float &glyph_scale)=0;
|
||||
virtual bool get_glyph(int character, const TextGlyph *&glyph)=0;
|
||||
|
||||
protected:
|
||||
bool _is_valid;
|
||||
|
@ -67,6 +67,24 @@ operator = (const TextGlyph ©) {
|
||||
_advance = copy._advance;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextGlyph::get_geom
|
||||
// Access: Public
|
||||
// Description: Returns a Geom that renders the particular glyph.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PT(Geom) TextGlyph::
|
||||
get_geom() const {
|
||||
if (_geom == (Geom *)NULL) {
|
||||
return _geom;
|
||||
}
|
||||
|
||||
// We always return a copy of the geom. That will allow the caller
|
||||
// to modify its vertices without fear of stomping on other copies;
|
||||
// it is also critical for the DynamicTextGlyph, which depends on
|
||||
// this behavior to properly count references to this glyph.
|
||||
return _geom->make_copy();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextGlyph::get_state
|
||||
// Access: Public
|
||||
|
@ -20,27 +20,9 @@
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextGlyph::Destructor
|
||||
// Access: Public, Virtual
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TextGlyph::
|
||||
~TextGlyph() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextGlyph::get_geom
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns a Geom that renders the particular glyph.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PT(Geom) TextGlyph::
|
||||
get_geom() const {
|
||||
if (_geom == (Geom *)NULL) {
|
||||
return _geom;
|
||||
}
|
||||
|
||||
// We always return a copy of the geom. That will allow the caller
|
||||
// to modify its vertices without fear of stomping on other copies;
|
||||
// it is also critical for the DynamicTextGlyph, which depends on
|
||||
// this behavior to properly count references to this glyph.
|
||||
return _geom->make_copy();
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ public:
|
||||
INLINE void operator = (const TextGlyph ©);
|
||||
virtual ~TextGlyph();
|
||||
|
||||
virtual PT(Geom) get_geom() const;
|
||||
INLINE PT(Geom) get_geom() const;
|
||||
INLINE const RenderState *get_state() const;
|
||||
INLINE float get_advance() const;
|
||||
|
||||
|
@ -202,6 +202,74 @@ get_line_height() const {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextNode::set_small_caps
|
||||
// Access: Published
|
||||
// Description: Sets the small_caps flag. When this is set,
|
||||
// lowercase letters are generated as scaled-down
|
||||
// versions of their uppercase equivalents. This is
|
||||
// particularly useful to set for fonts that do not have
|
||||
// lowercase letters.
|
||||
//
|
||||
// It is also a good idea to set this for a (dynamic)
|
||||
// font that has already implemented lowercase letters
|
||||
// as scaled-down versions of their uppercase
|
||||
// equivalents, since without this flag the texture
|
||||
// memory may needlessly duplicate equivalent glyphs for
|
||||
// upper and lowercase letters. Setting this flag
|
||||
// causes the texture memory to share the mixed-case
|
||||
// letters.
|
||||
//
|
||||
// The amount by which the lowercase letters are scaled
|
||||
// is specified by set_small_caps_scale().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void TextNode::
|
||||
set_small_caps(bool small_caps) {
|
||||
if (small_caps) {
|
||||
_flags |= F_small_caps;
|
||||
} else {
|
||||
_flags &= ~F_small_caps;
|
||||
}
|
||||
invalidate_with_measure();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextNode::get_small_caps
|
||||
// Access: Published
|
||||
// Description: Returns the small_caps flag. See set_small_caps().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool TextNode::
|
||||
get_small_caps() const {
|
||||
return (_flags & F_small_caps) != 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextNode::set_small_caps_scale
|
||||
// Access: Published
|
||||
// Description: Sets the scale factor applied to lowercase letters
|
||||
// from their uppercase equivalents, when the small_caps
|
||||
// flag is in effect. See set_small_caps(). Normally,
|
||||
// this will be a number less than one.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void TextNode::
|
||||
set_small_caps_scale(float small_caps_scale) {
|
||||
_small_caps_scale = small_caps_scale;
|
||||
invalidate_with_measure();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextNode::get_small_caps_scale
|
||||
// Access: Published
|
||||
// Description: Returns the scale factor applied to lowercase letters
|
||||
// from their uppercase equivalents, when the small_caps
|
||||
// flag is in effect. See set_small_caps() and
|
||||
// set_small_caps_scale().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE float TextNode::
|
||||
get_small_caps_scale() const {
|
||||
return _small_caps_scale;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextNode::set_slant
|
||||
// Access: Published
|
||||
@ -1156,6 +1224,30 @@ get_char(int index) const {
|
||||
return _wtext[index];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextNode::get_text_as_ascii
|
||||
// Access: Published
|
||||
// Description: Returns the text associated with the node, converted
|
||||
// as nearly as possible to a fully-ASCII
|
||||
// representation. This means replacing accented
|
||||
// letters with their unaccented ASCII equivalents.
|
||||
//
|
||||
// It is possible that some characters in the string
|
||||
// cannot be converted to ASCII. (The string may
|
||||
// involve symbols like the copyright symbol, for
|
||||
// instance, or it might involve letters in some other
|
||||
// alphabet such as Greek or Cyrillic, or even Latin
|
||||
// letters like thorn or eth that are not part of the
|
||||
// ASCII character set.) In this case, as much of the
|
||||
// string as possible will be converted to ASCII, and
|
||||
// the nonconvertible characters will remain encoded in
|
||||
// the encoding specified by set_encoding().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE string TextNode::
|
||||
get_text_as_ascii() const {
|
||||
return encode_wtext(get_wtext_as_ascii());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextNode::calc_width
|
||||
// Access: Published
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "fontPool.h"
|
||||
#include "default_font.h"
|
||||
#include "dynamicTextFont.h"
|
||||
#include "unicodeLatinMap.h"
|
||||
|
||||
#include "compose_matrix.h"
|
||||
#include "geom.h"
|
||||
@ -54,6 +55,13 @@ PT(TextFont) TextNode::_default_font;
|
||||
bool TextNode::_loaded_default_font = false;
|
||||
TextNode::Encoding TextNode::_default_encoding;
|
||||
|
||||
// This is the factor by which CP_tiny scales the character down.
|
||||
static const float tiny_accent_scale = 0.3f;
|
||||
|
||||
// This is the factor by which the advance is reduced for the first
|
||||
// character of a two-character ligature.
|
||||
static const float ligature_advance_scale = 0.6f;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextNode::Constructor
|
||||
// Access: Published
|
||||
@ -71,6 +79,11 @@ TextNode(const string &name) : PandaNode(name) {
|
||||
_align = A_left;
|
||||
_wordwrap_width = 1.0f;
|
||||
|
||||
if (text_small_caps) {
|
||||
_flags |= F_small_caps;
|
||||
}
|
||||
_small_caps_scale = text_small_caps_scale;
|
||||
|
||||
_text_color.set(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
_frame_color.set(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
_card_color.set(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
@ -397,6 +410,49 @@ generate() {
|
||||
return root;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextNode::get_wtext_as_ascii
|
||||
// Access: Published
|
||||
// Description: Returns the text associated with the node, converted
|
||||
// as nearly as possible to a fully-ASCII
|
||||
// representation. This means replacing accented
|
||||
// letters with their unaccented ASCII equivalents.
|
||||
//
|
||||
// It is possible that some characters in the string
|
||||
// cannot be converted to ASCII. (The string may
|
||||
// involve symbols like the copyright symbol, for
|
||||
// instance, or it might involve letters in some other
|
||||
// alphabet such as Greek or Cyrillic, or even Latin
|
||||
// letters like thorn or eth that are not part of the
|
||||
// ASCII character set.) In this case, as much of the
|
||||
// string as possible will be converted to ASCII, and
|
||||
// the nonconvertible characters will remain in their
|
||||
// original form.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
wstring TextNode::
|
||||
get_wtext_as_ascii() const {
|
||||
get_wtext();
|
||||
wstring result;
|
||||
wstring::const_iterator si;
|
||||
for (si = _wtext.begin(); si != _wtext.end(); ++si) {
|
||||
wchar_t character = (*si);
|
||||
|
||||
const UnicodeLatinMap::Entry *map_entry =
|
||||
UnicodeLatinMap::look_up(character);
|
||||
if (map_entry != NULL && map_entry->_ascii_equiv != 0) {
|
||||
result += (wchar_t)map_entry->_ascii_equiv;
|
||||
if (map_entry->_ascii_additional != 0) {
|
||||
result += (wchar_t)map_entry->_ascii_additional;
|
||||
}
|
||||
|
||||
} else {
|
||||
result += character;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextNode::encode_wchar
|
||||
// Access: Public
|
||||
@ -870,7 +926,8 @@ do_measure() {
|
||||
_ul3d = _ul3d * _transform;
|
||||
_lr3d = _lr3d * _transform;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifndef CPPPARSER // interrogate has a bit of trouble with wstring.
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -895,10 +952,18 @@ assemble_row(wstring::iterator &si, const wstring::iterator &send,
|
||||
|
||||
} else {
|
||||
// A printable character.
|
||||
|
||||
bool got_glyph;
|
||||
const TextGlyph *glyph;
|
||||
const TextGlyph *second_glyph;
|
||||
UnicodeLatinMap::AccentType accent_type;
|
||||
int additional_flags;
|
||||
float glyph_scale;
|
||||
if (!font->get_glyph(character, glyph, glyph_scale)) {
|
||||
float advance_scale;
|
||||
get_character_glyphs(character, font,
|
||||
got_glyph, glyph, second_glyph, accent_type,
|
||||
additional_flags, glyph_scale, advance_scale);
|
||||
|
||||
if (!got_glyph) {
|
||||
text_cat.warning()
|
||||
<< "No definition in " << font->get_name()
|
||||
<< " for character " << character;
|
||||
@ -910,35 +975,87 @@ assemble_row(wstring::iterator &si, const wstring::iterator &send,
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
// Build up a temporary array of the Geoms that go into this
|
||||
// character. Normally, there is only one Geom per character,
|
||||
// but it may involve multiple Geoms if we need to add cheesy
|
||||
// accents or ligatures.
|
||||
static const int max_geoms = 10;
|
||||
Geom *geom_array[max_geoms];
|
||||
int num_geoms = 0;
|
||||
int gi;
|
||||
|
||||
float advance = 0.0f;
|
||||
|
||||
if (glyph != (TextGlyph *)NULL) {
|
||||
PT(Geom) char_geom = glyph->get_geom();
|
||||
const RenderState *state = glyph->get_state();
|
||||
|
||||
if (char_geom != (Geom *)NULL) {
|
||||
LMatrix4f mat2 = LMatrix4f::scale_mat(glyph_scale);
|
||||
mat2.set_row(3, LVector3f(xpos, 0.0f, 0.0f));
|
||||
LMatrix4f xform = mat2 * mat;
|
||||
dest->add_geom(char_geom, glyph->get_state());
|
||||
geom_array[num_geoms++] = char_geom;
|
||||
}
|
||||
advance = glyph->get_advance() * advance_scale;
|
||||
}
|
||||
if (second_glyph != (TextGlyph *)NULL) {
|
||||
PT(Geom) second_char_geom = second_glyph->get_geom();
|
||||
if (second_char_geom != (Geom *)NULL) {
|
||||
second_char_geom->transform_vertices(LMatrix4f::translate_mat(advance, 0.0f, 0.0f));
|
||||
dest->add_geom(second_char_geom, second_glyph->get_state());
|
||||
geom_array[num_geoms++] = second_char_geom;
|
||||
}
|
||||
advance += second_glyph->get_advance();
|
||||
}
|
||||
|
||||
// Transform the vertices of the geom appropriately. We
|
||||
// assume the geom is non-indexed.
|
||||
PTA_Vertexf coords;
|
||||
PTA_ushort index;
|
||||
char_geom->get_coords(coords, index);
|
||||
PTA_Vertexf new_coords;
|
||||
new_coords.reserve(coords.size());
|
||||
PTA_Vertexf::const_iterator vi;
|
||||
for (vi = coords.begin(); vi != coords.end(); ++vi) {
|
||||
new_coords.push_back((*vi) * xform);
|
||||
}
|
||||
nassertr(new_coords.size() == coords.size(), false);
|
||||
char_geom->set_coords(new_coords);
|
||||
// Now compute the matrix that will transform the glyph (or
|
||||
// glyphs) into position.
|
||||
LMatrix4f glyph_xform = LMatrix4f::scale_mat(glyph_scale);
|
||||
|
||||
// Now add the geom to the destination node.
|
||||
dest->add_geom(char_geom, state);
|
||||
if (accent_type != UnicodeLatinMap::AT_none || additional_flags != 0) {
|
||||
// If we have some special handling to perform, do so now.
|
||||
// This will probably require the bounding volume of the
|
||||
// glyph, so go get that.
|
||||
LPoint3f min_vert, max_vert;
|
||||
bool found_any = false;
|
||||
for (gi = 0; gi < num_geoms; gi++) {
|
||||
geom_array[gi]->calc_tight_bounds(min_vert, max_vert, found_any);
|
||||
}
|
||||
|
||||
xpos += glyph->get_advance() * glyph_scale;
|
||||
if (found_any) {
|
||||
LPoint3f centroid = (min_vert + max_vert) / 2.0f;
|
||||
tack_on_accent(accent_type, min_vert, max_vert, centroid,
|
||||
font, dest, geom_array, num_geoms);
|
||||
|
||||
if ((additional_flags & UnicodeLatinMap::AF_turned) != 0) {
|
||||
// Invert the character. Should we also invert the accent
|
||||
// mark, so that an accent that would have been above the
|
||||
// glyph will now be below it? That's what we do here,
|
||||
// which is probably the right thing to do for n-tilde,
|
||||
// but not for most of the rest of the accent marks. For
|
||||
// now we'll assume there are no characters with accent
|
||||
// marks that also have the turned flag.
|
||||
|
||||
// We rotate the character around its centroid, which may
|
||||
// not always be the right point, but it's the best we've
|
||||
// got and it's probably pretty close.
|
||||
LMatrix4f rotate =
|
||||
LMatrix4f::translate_mat(-centroid) *
|
||||
LMatrix4f::rotate_mat_normaxis(180.0f, LVecBase3f(0.0f, 1.0f, 0.0f)) *
|
||||
LMatrix4f::translate_mat(centroid);
|
||||
glyph_xform *= rotate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glyph_xform(3, 0) += xpos;
|
||||
LMatrix4f net_xform = glyph_xform * mat;
|
||||
|
||||
// Finally, transform all the Geoms for this character into
|
||||
// place. Again, normally there is only one Geom per character;
|
||||
// there will only be multiple Geoms if we have added accents or
|
||||
// ligatures.
|
||||
for (gi = 0; gi < num_geoms; gi++) {
|
||||
geom_array[gi]->transform_vertices(net_xform);
|
||||
}
|
||||
|
||||
xpos += advance * glyph_scale;
|
||||
}
|
||||
++si;
|
||||
}
|
||||
@ -1035,13 +1152,27 @@ measure_row(wstring::iterator &si, const wstring::iterator &send,
|
||||
|
||||
} else {
|
||||
// A printable character.
|
||||
|
||||
bool got_glyph;
|
||||
const TextGlyph *glyph;
|
||||
const TextGlyph *second_glyph;
|
||||
UnicodeLatinMap::AccentType accent_type;
|
||||
int additional_flags;
|
||||
float glyph_scale;
|
||||
font->get_glyph(character, glyph, glyph_scale);
|
||||
float advance_scale;
|
||||
get_character_glyphs(character, font,
|
||||
got_glyph, glyph, second_glyph, accent_type,
|
||||
additional_flags, glyph_scale, advance_scale);
|
||||
|
||||
float advance = 0.0f;
|
||||
|
||||
if (glyph != (TextGlyph *)NULL) {
|
||||
xpos += glyph->get_advance() * glyph_scale;
|
||||
advance = glyph->get_advance() * advance_scale;
|
||||
}
|
||||
if (second_glyph != (TextGlyph *)NULL) {
|
||||
advance += second_glyph->get_advance();
|
||||
}
|
||||
|
||||
xpos += advance * glyph_scale;
|
||||
}
|
||||
++si;
|
||||
}
|
||||
@ -1092,6 +1223,356 @@ measure_text(wstring::iterator si, const wstring::iterator &send,
|
||||
}
|
||||
#endif // CPPPARSER
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextNode::get_character_glyphs
|
||||
// Access: Private
|
||||
// Description: Looks up the glyph(s) from the font for the
|
||||
// appropriate character. If the desired glyph isn't
|
||||
// available (especially in the case of an accented
|
||||
// letter), tries to find a suitable replacement.
|
||||
// Normally, only one glyph is returned per character,
|
||||
// but in the case we have to simulate a missing
|
||||
// ligature in the font, two glyphs might be returned.
|
||||
//
|
||||
// All parameters except the first two are output
|
||||
// parameters. got_glyph is set true if the glyph (or
|
||||
// an acceptable substitute) is successfully found,
|
||||
// false otherwise; but even if it is false, glyph might
|
||||
// still be non-NULL, indicating a stand-in glyph for a
|
||||
// missing character.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void TextNode::
|
||||
get_character_glyphs(int character, TextFont *font,
|
||||
bool &got_glyph, const TextGlyph *&glyph,
|
||||
const TextGlyph *&second_glyph,
|
||||
UnicodeLatinMap::AccentType &accent_type,
|
||||
int &additional_flags,
|
||||
float &glyph_scale, float &advance_scale) {
|
||||
got_glyph = false;
|
||||
glyph = NULL;
|
||||
second_glyph = NULL;
|
||||
accent_type = UnicodeLatinMap::AT_none;
|
||||
additional_flags = 0;
|
||||
glyph_scale = 1.0f;
|
||||
advance_scale = 1.0f;
|
||||
|
||||
// Maybe we should remap the character to something else--e.g. a
|
||||
// small capital.
|
||||
const UnicodeLatinMap::Entry *map_entry =
|
||||
UnicodeLatinMap::look_up(character);
|
||||
if (map_entry != NULL) {
|
||||
if (get_small_caps() && map_entry->_toupper_character != character) {
|
||||
character = map_entry->_toupper_character;
|
||||
map_entry = UnicodeLatinMap::look_up(character);
|
||||
glyph_scale = get_small_caps_scale();
|
||||
}
|
||||
}
|
||||
|
||||
got_glyph = font->get_glyph(character, glyph);
|
||||
if (!got_glyph && map_entry != NULL && map_entry->_ascii_equiv != 0) {
|
||||
// If we couldn't find the Unicode glyph, try the ASCII
|
||||
// equivalent (without the accent marks).
|
||||
got_glyph = font->get_glyph(map_entry->_ascii_equiv, glyph);
|
||||
|
||||
if (!got_glyph && map_entry->_toupper_character != character) {
|
||||
// If we still couldn't find it, try the uppercase
|
||||
// equivalent.
|
||||
character = map_entry->_toupper_character;
|
||||
map_entry = UnicodeLatinMap::look_up(character);
|
||||
if (map_entry != NULL) {
|
||||
got_glyph = font->get_glyph(map_entry->_ascii_equiv, glyph);
|
||||
}
|
||||
}
|
||||
|
||||
if (got_glyph) {
|
||||
accent_type = map_entry->_accent_type;
|
||||
additional_flags = map_entry->_additional_flags;
|
||||
|
||||
bool got_second_glyph = false;
|
||||
if (map_entry->_ascii_additional != 0) {
|
||||
// There's another character, too--probably a ligature.
|
||||
got_second_glyph =
|
||||
font->get_glyph(map_entry->_ascii_additional, second_glyph);
|
||||
}
|
||||
|
||||
if ((additional_flags & UnicodeLatinMap::AF_ligature) != 0 &&
|
||||
got_second_glyph) {
|
||||
// If we have two letters that are supposed to be in a
|
||||
// ligature, just jam them together.
|
||||
additional_flags &= ~UnicodeLatinMap::AF_ligature;
|
||||
advance_scale = ligature_advance_scale;
|
||||
}
|
||||
|
||||
if ((additional_flags & UnicodeLatinMap::AF_smallcap) != 0) {
|
||||
additional_flags &= ~UnicodeLatinMap::AF_smallcap;
|
||||
glyph_scale = get_small_caps_scale();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextNode::tack_on_accent
|
||||
// Access: Private
|
||||
// Description: This is a cheesy attempt to tack on an accent to an
|
||||
// ASCII letter for which we don't have the appropriate
|
||||
// already-accented glyph in the font.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void TextNode::
|
||||
tack_on_accent(UnicodeLatinMap::AccentType accent_type,
|
||||
const LPoint3f &min_vert, const LPoint3f &max_vert,
|
||||
const LPoint3f ¢roid,
|
||||
TextFont *font, GeomNode *dest,
|
||||
Geom *geom_array[], int &num_geoms) {
|
||||
switch (accent_type) {
|
||||
case UnicodeLatinMap::AT_grave:
|
||||
// We use the slash as the grave and acute accents. ASCII does
|
||||
// have a grave accent character, but a lot of fonts put the
|
||||
// reverse apostrophe there instead. And some fonts (particularly
|
||||
// fonts from mf) don't even do backslash.
|
||||
tack_on_accent('/', CP_above, CT_tiny_mirror_x, min_vert, max_vert, centroid,
|
||||
font, dest, geom_array, num_geoms);
|
||||
break;
|
||||
|
||||
case UnicodeLatinMap::AT_acute:
|
||||
tack_on_accent('/', CP_above, CT_tiny, min_vert, max_vert, centroid,
|
||||
font, dest, geom_array, num_geoms);
|
||||
break;
|
||||
|
||||
case UnicodeLatinMap::AT_breve:
|
||||
tack_on_accent(')', CP_above, CT_tiny_rotate_90, min_vert, max_vert, centroid,
|
||||
font, dest, geom_array, num_geoms);
|
||||
break;
|
||||
|
||||
case UnicodeLatinMap::AT_inverted_breve:
|
||||
tack_on_accent('(', CP_above, CT_tiny_rotate_90, min_vert, max_vert, centroid,
|
||||
font, dest, geom_array, num_geoms);
|
||||
break;
|
||||
|
||||
case UnicodeLatinMap::AT_circumflex:
|
||||
tack_on_accent('^', CP_above, CT_none, min_vert, max_vert, centroid,
|
||||
font, dest, geom_array, num_geoms);
|
||||
break;
|
||||
|
||||
case UnicodeLatinMap::AT_circumflex_below:
|
||||
tack_on_accent('^', CP_below, CT_none, min_vert, max_vert, centroid,
|
||||
font, dest, geom_array, num_geoms);
|
||||
break;
|
||||
|
||||
case UnicodeLatinMap::AT_caron:
|
||||
tack_on_accent('^', CP_above, CT_mirror_y, min_vert, max_vert, centroid,
|
||||
font, dest, geom_array, num_geoms);
|
||||
break;
|
||||
|
||||
case UnicodeLatinMap::AT_tilde:
|
||||
tack_on_accent('~', CP_above, CT_none, min_vert, max_vert, centroid,
|
||||
font, dest, geom_array, num_geoms);
|
||||
break;
|
||||
|
||||
case UnicodeLatinMap::AT_tilde_below:
|
||||
tack_on_accent('~', CP_below, CT_none, min_vert, max_vert, centroid,
|
||||
font, dest, geom_array, num_geoms);
|
||||
break;
|
||||
|
||||
case UnicodeLatinMap::AT_diaeresis:
|
||||
tack_on_accent(':', CP_above, CT_rotate_90, min_vert, max_vert, centroid,
|
||||
font, dest, geom_array, num_geoms);
|
||||
break;
|
||||
|
||||
case UnicodeLatinMap::AT_diaeresis_below:
|
||||
tack_on_accent(':', CP_below, CT_rotate_90, min_vert, max_vert, centroid,
|
||||
font, dest, geom_array, num_geoms);
|
||||
break;
|
||||
|
||||
case UnicodeLatinMap::AT_dot_above:
|
||||
tack_on_accent('.', CP_above, CT_none, min_vert, max_vert, centroid,
|
||||
font, dest, geom_array, num_geoms);
|
||||
break;
|
||||
|
||||
case UnicodeLatinMap::AT_dot_below:
|
||||
tack_on_accent('.', CP_below, CT_none, min_vert, max_vert, centroid,
|
||||
font, dest, geom_array, num_geoms);
|
||||
break;
|
||||
|
||||
case UnicodeLatinMap::AT_macron:
|
||||
tack_on_accent('-', CP_above, CT_none, min_vert, max_vert, centroid,
|
||||
font, dest, geom_array, num_geoms);
|
||||
break;
|
||||
|
||||
case UnicodeLatinMap::AT_line_below:
|
||||
tack_on_accent('-', CP_below, CT_none, min_vert, max_vert, centroid,
|
||||
font, dest, geom_array, num_geoms);
|
||||
break;
|
||||
|
||||
case UnicodeLatinMap::AT_ring_above:
|
||||
tack_on_accent('o', CP_top, CT_tiny, min_vert, max_vert, centroid,
|
||||
font, dest, geom_array, num_geoms);
|
||||
break;
|
||||
|
||||
case UnicodeLatinMap::AT_ring_below:
|
||||
tack_on_accent('o', CP_bottom, CT_tiny, min_vert, max_vert, centroid,
|
||||
font, dest, geom_array, num_geoms);
|
||||
break;
|
||||
|
||||
case UnicodeLatinMap::AT_cedilla:
|
||||
tack_on_accent(',', CP_bottom, CT_none, min_vert, max_vert, centroid,
|
||||
font, dest, geom_array, num_geoms);
|
||||
break;
|
||||
|
||||
case UnicodeLatinMap::AT_comma_below:
|
||||
tack_on_accent(',', CP_below, CT_none, min_vert, max_vert, centroid,
|
||||
font, dest, geom_array, num_geoms);
|
||||
break;
|
||||
|
||||
case UnicodeLatinMap::AT_ogonek:
|
||||
tack_on_accent(',', CP_bottom, CT_mirror_x, min_vert, max_vert, centroid,
|
||||
font, dest, geom_array, num_geoms);
|
||||
break;
|
||||
|
||||
case UnicodeLatinMap::AT_stroke:
|
||||
tack_on_accent('/', CP_within, CT_none, min_vert, max_vert, centroid,
|
||||
font, dest, geom_array, num_geoms);
|
||||
break;
|
||||
|
||||
default:
|
||||
// There are lots of other crazy kinds of accents. Forget 'em.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextNode::tack_on_accent
|
||||
// Access: Private
|
||||
// Description: Generates a cheesy accent mark above (or below, etc.)
|
||||
// the character.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void TextNode::
|
||||
tack_on_accent(char accent_mark, TextNode::CheesyPlacement placement,
|
||||
TextNode::CheesyTransform transform,
|
||||
const LPoint3f &min_vert, const LPoint3f &max_vert,
|
||||
const LPoint3f ¢roid,
|
||||
TextFont *font, GeomNode *dest,
|
||||
Geom *geom_array[], int &num_geoms) {
|
||||
|
||||
TextGlyph *accent_glyph;
|
||||
if (font->get_glyph(accent_mark, accent_glyph)) {
|
||||
PT(Geom) accent_geom = accent_glyph->get_geom();
|
||||
if (accent_geom != (Geom *)NULL) {
|
||||
LPoint3f min_accent, max_accent;
|
||||
bool found_any = false;
|
||||
accent_geom->calc_tight_bounds(min_accent, max_accent, found_any);
|
||||
if (found_any) {
|
||||
float t, u;
|
||||
LMatrix4f accent_mat;
|
||||
|
||||
switch (transform) {
|
||||
case CT_none:
|
||||
accent_mat = LMatrix4f::ident_mat();
|
||||
break;
|
||||
|
||||
case CT_mirror_x:
|
||||
accent_mat = LMatrix4f::scale_mat(-1.0f, 1.0f, 1.0f);
|
||||
|
||||
t = -min_accent[0];
|
||||
min_accent[0] = -max_accent[0];
|
||||
max_accent[0] = t;
|
||||
break;
|
||||
|
||||
case CT_mirror_y:
|
||||
accent_mat = LMatrix4f::scale_mat(1.0f, -1.0f, 1.0f);
|
||||
|
||||
t = -min_accent[2];
|
||||
min_accent[2] = -max_accent[2];
|
||||
max_accent[2] = t;
|
||||
break;
|
||||
|
||||
case CT_rotate_90:
|
||||
accent_mat =
|
||||
LMatrix4f::rotate_mat_normaxis(90.0f, LVecBase3f(0.0f, 1.0f, 0.0f));
|
||||
// rotate min, max
|
||||
t = min_accent[0];
|
||||
u = max_accent[0];
|
||||
min_accent[0] = min_accent[2];
|
||||
max_accent[0] = max_accent[2];
|
||||
min_accent[2] = -u;
|
||||
max_accent[2] = -t;
|
||||
break;
|
||||
|
||||
case CT_tiny:
|
||||
accent_mat = LMatrix4f::scale_mat(tiny_accent_scale);
|
||||
min_accent *= tiny_accent_scale;
|
||||
max_accent *= tiny_accent_scale;
|
||||
break;
|
||||
|
||||
case CT_tiny_mirror_x:
|
||||
accent_mat = LMatrix4f::scale_mat(-tiny_accent_scale, 1.0f, tiny_accent_scale);
|
||||
|
||||
t = -min_accent[0] * tiny_accent_scale;
|
||||
min_accent[0] = -max_accent[0] * tiny_accent_scale;
|
||||
max_accent[0] = t;
|
||||
break;
|
||||
|
||||
case CT_tiny_rotate_90:
|
||||
accent_mat =
|
||||
LMatrix4f::rotate_mat_normaxis(90.0f, LVecBase3f(0.0f, 1.0f, 0.0f)) *
|
||||
LMatrix4f::scale_mat(tiny_accent_scale);
|
||||
|
||||
// rotate min, max
|
||||
t = min_accent[0];
|
||||
u = max_accent[0];
|
||||
min_accent[0] = min_accent[2] * tiny_accent_scale;
|
||||
max_accent[0] = max_accent[2] * tiny_accent_scale;
|
||||
min_accent[2] = -u * tiny_accent_scale;
|
||||
max_accent[2] = -t * tiny_accent_scale;
|
||||
break;
|
||||
}
|
||||
|
||||
LPoint3f accent_centroid = (min_accent + max_accent) / 2.0f;
|
||||
float accent_height = max_accent[2] - min_accent[2];
|
||||
LVector3f trans;
|
||||
switch (placement) {
|
||||
case CP_above:
|
||||
// A little above the character.
|
||||
trans.set(centroid[0] - accent_centroid[0], 0.0f,
|
||||
max_vert[2] - accent_centroid[2] + accent_height * 0.5);
|
||||
break;
|
||||
|
||||
case CP_below:
|
||||
// A little below the character.
|
||||
trans.set(centroid[0] - accent_centroid[0], 0.0f,
|
||||
min_vert[2] - accent_centroid[2] - accent_height * 0.5);
|
||||
break;
|
||||
|
||||
case CP_top:
|
||||
// Touching the top of the character.
|
||||
trans.set(centroid[0] - accent_centroid[0], 0.0f,
|
||||
max_vert[2] - accent_centroid[2]);
|
||||
break;
|
||||
|
||||
case CP_bottom:
|
||||
// Touching the bottom of the character.
|
||||
trans.set(centroid[0] - accent_centroid[0], 0.0f,
|
||||
min_vert[2] - accent_centroid[2]);
|
||||
break;
|
||||
|
||||
case CP_within:
|
||||
// Centered within the character.
|
||||
trans.set(centroid[0] - accent_centroid[0], 0.0f,
|
||||
centroid[2] - accent_centroid[2]);
|
||||
break;
|
||||
}
|
||||
|
||||
accent_mat.set_row(3, trans);
|
||||
accent_geom->transform_vertices(accent_mat);
|
||||
|
||||
dest->add_geom(accent_geom, accent_glyph->get_state());
|
||||
geom_array[num_geoms++] = accent_geom;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextNode::make_frame
|
||||
// Access: Private
|
||||
|
@ -23,8 +23,8 @@
|
||||
|
||||
#include "config_text.h"
|
||||
#include "textFont.h"
|
||||
#include "unicodeLatinMap.h"
|
||||
#include "pandaNode.h"
|
||||
|
||||
#include "luse.h"
|
||||
|
||||
class StringDecoder;
|
||||
@ -89,6 +89,11 @@ PUBLISHED:
|
||||
|
||||
INLINE float get_line_height() const;
|
||||
|
||||
INLINE void set_small_caps(bool small_caps);
|
||||
INLINE bool get_small_caps() const;
|
||||
INLINE void set_small_caps_scale(float small_caps_scale);
|
||||
INLINE float get_small_caps_scale() const;
|
||||
|
||||
INLINE void set_slant(float slant);
|
||||
INLINE float get_slant() const;
|
||||
|
||||
@ -182,6 +187,7 @@ PUBLISHED:
|
||||
INLINE void append_char(int character);
|
||||
INLINE int get_num_chars() const;
|
||||
INLINE int get_char(int index) const;
|
||||
INLINE string get_text_as_ascii() const;
|
||||
|
||||
INLINE float calc_width(int character) const;
|
||||
INLINE float calc_width(const string &line) const;
|
||||
@ -213,6 +219,7 @@ public:
|
||||
INLINE void set_wtext(const wstring &wtext);
|
||||
INLINE const wstring &get_wtext() const;
|
||||
INLINE void append_wtext(const wstring &text);
|
||||
wstring get_wtext_as_ascii() const;
|
||||
|
||||
INLINE float calc_width(const wstring &line) const;
|
||||
INLINE wstring wordwrap_to(const wstring &wtext, float wordwrap_width,
|
||||
@ -262,6 +269,42 @@ private:
|
||||
LVector2f &ul, LVector2f &lr, int &num_rows);
|
||||
#endif // CPPPARSER
|
||||
|
||||
enum CheesyPlacement {
|
||||
CP_above,
|
||||
CP_below,
|
||||
CP_top,
|
||||
CP_bottom,
|
||||
CP_within,
|
||||
};
|
||||
enum CheesyTransform {
|
||||
CT_none,
|
||||
CT_mirror_x,
|
||||
CT_mirror_y,
|
||||
CT_rotate_90,
|
||||
CT_tiny,
|
||||
CT_tiny_mirror_x,
|
||||
CT_tiny_rotate_90,
|
||||
};
|
||||
|
||||
void get_character_glyphs(int character, TextFont *font,
|
||||
bool &got_glyph, const TextGlyph *&glyph,
|
||||
const TextGlyph *&second_glyph,
|
||||
UnicodeLatinMap::AccentType &accent_type,
|
||||
int &additional_flags,
|
||||
float &glyph_scale, float &advance_scale);
|
||||
|
||||
void tack_on_accent(UnicodeLatinMap::AccentType accent_type,
|
||||
const LPoint3f &min_vert, const LPoint3f &max_vert,
|
||||
const LPoint3f ¢roid,
|
||||
TextFont *font, GeomNode *dest,
|
||||
Geom *geom_array[], int &num_geoms);
|
||||
void tack_on_accent(char accent_mark, CheesyPlacement placement,
|
||||
CheesyTransform transform,
|
||||
const LPoint3f &min_vert, const LPoint3f &max_vert,
|
||||
const LPoint3f ¢roid,
|
||||
TextFont *font, GeomNode *dest,
|
||||
Geom *geom_array[], int &num_geoms);
|
||||
|
||||
PT(PandaNode) make_frame();
|
||||
PT(PandaNode) make_card();
|
||||
PT(PandaNode) make_card_with_border();
|
||||
@ -281,22 +324,23 @@ private:
|
||||
Colorf _card_color;
|
||||
|
||||
enum Flags {
|
||||
F_has_text_color = 0x0001,
|
||||
F_has_wordwrap = 0x0002,
|
||||
F_has_frame = 0x0004,
|
||||
F_frame_as_margin = 0x0008,
|
||||
F_has_card = 0x0010,
|
||||
F_card_as_margin = 0x0020,
|
||||
F_has_card_texture = 0x0040,
|
||||
F_has_shadow = 0x0080,
|
||||
F_frame_corners = 0x0100,
|
||||
F_card_transp = 0x0200,
|
||||
F_has_card_border = 0x0400,
|
||||
F_expand_amp = 0x0800,
|
||||
F_got_text = 0x1000,
|
||||
F_got_wtext = 0x2000,
|
||||
F_needs_rebuild = 0x4000,
|
||||
F_needs_measure = 0x8000,
|
||||
F_has_text_color = 0x00000001,
|
||||
F_has_wordwrap = 0x00000002,
|
||||
F_has_frame = 0x00000004,
|
||||
F_frame_as_margin = 0x00000008,
|
||||
F_has_card = 0x00000010,
|
||||
F_card_as_margin = 0x00000020,
|
||||
F_has_card_texture = 0x00000040,
|
||||
F_has_shadow = 0x00000080,
|
||||
F_frame_corners = 0x00000100,
|
||||
F_card_transp = 0x00000200,
|
||||
F_has_card_border = 0x00000400,
|
||||
F_expand_amp = 0x00000800,
|
||||
F_got_text = 0x00001000,
|
||||
F_got_wtext = 0x00002000,
|
||||
F_needs_rebuild = 0x00004000,
|
||||
F_needs_measure = 0x00008000,
|
||||
F_small_caps = 0x00010000,
|
||||
};
|
||||
|
||||
int _flags;
|
||||
@ -305,6 +349,7 @@ private:
|
||||
float _frame_width;
|
||||
float _card_border_size;
|
||||
float _card_border_uv_portion;
|
||||
float _small_caps_scale;
|
||||
|
||||
LVector2f _frame_ul, _frame_lr;
|
||||
LVector2f _card_ul, _card_lr;
|
||||
|
@ -9,3 +9,4 @@
|
||||
#include "stringDecoder.cxx"
|
||||
#include "textFont.cxx"
|
||||
#include "textGlyph.cxx"
|
||||
#include "unicodeLatinMap.cxx"
|
||||
|
1359
panda/src/text/unicodeLatinMap.cxx
Normal file
1359
panda/src/text/unicodeLatinMap.cxx
Normal file
File diff suppressed because it is too large
Load Diff
146
panda/src/text/unicodeLatinMap.h
Normal file
146
panda/src/text/unicodeLatinMap.h
Normal file
@ -0,0 +1,146 @@
|
||||
// Filename: unicodeLatinMap.h
|
||||
// Created by: drose (01Feb03)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 UNICODELATINMAP_H
|
||||
#define UNICODELATINMAP_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "pmap.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : UnicodeLatinMap
|
||||
// Description : This class mainly serves as a container for a largish
|
||||
// table of the subset of the Unicode character set that
|
||||
// corresponds to the Latin alphabet, with its various
|
||||
// accent marks and so on. Specifically, this table
|
||||
// indicates how to map between the Unicode accented
|
||||
// character and the corresponding ASCII equivalent
|
||||
// without the accent mark; as well as how to switch
|
||||
// case from upper to lower while retaining the Unicode
|
||||
// accent marks.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA UnicodeLatinMap {
|
||||
public:
|
||||
enum AccentType {
|
||||
AT_none,
|
||||
AT_acute,
|
||||
AT_acute_and_dot_above,
|
||||
AT_breve,
|
||||
AT_breve_and_acute,
|
||||
AT_breve_and_dot_below,
|
||||
AT_breve_and_grave,
|
||||
AT_breve_and_hook_above,
|
||||
AT_breve_and_tilde,
|
||||
AT_breve_below,
|
||||
AT_caron,
|
||||
AT_caron_and_dot_above,
|
||||
AT_cedilla,
|
||||
AT_cedilla_and_acute,
|
||||
AT_cedilla_and_breve,
|
||||
AT_circumflex,
|
||||
AT_circumflex_and_acute,
|
||||
AT_circumflex_and_dot_below,
|
||||
AT_circumflex_and_grave,
|
||||
AT_circumflex_and_hook_above,
|
||||
AT_circumflex_and_tilde,
|
||||
AT_circumflex_below,
|
||||
AT_comma_below,
|
||||
AT_curl,
|
||||
AT_diaeresis,
|
||||
AT_diaeresis_and_acute,
|
||||
AT_diaeresis_and_caron,
|
||||
AT_diaeresis_and_grave,
|
||||
AT_diaeresis_and_macron,
|
||||
AT_diaeresis_below,
|
||||
AT_dot_above,
|
||||
AT_dot_above_and_macron,
|
||||
AT_dot_below,
|
||||
AT_dot_below_and_dot_above,
|
||||
AT_dot_below_and_macron,
|
||||
AT_double_acute,
|
||||
AT_double_grave,
|
||||
AT_grave,
|
||||
AT_hook,
|
||||
AT_hook_above,
|
||||
AT_horn,
|
||||
AT_horn_and_acute,
|
||||
AT_horn_and_dot_below,
|
||||
AT_horn_and_grave,
|
||||
AT_horn_and_hook_above,
|
||||
AT_horn_and_tilde,
|
||||
AT_inverted_breve,
|
||||
AT_line_below,
|
||||
AT_macron,
|
||||
AT_macron_and_acute,
|
||||
AT_macron_and_diaeresis,
|
||||
AT_macron_and_grave,
|
||||
AT_ogonek,
|
||||
AT_ogonek_and_macron,
|
||||
AT_ring_above,
|
||||
AT_ring_above_and_acute,
|
||||
AT_ring_below,
|
||||
AT_stroke,
|
||||
AT_stroke_and_acute,
|
||||
AT_stroke_and_hook,
|
||||
AT_tilde,
|
||||
AT_tilde_and_acute,
|
||||
AT_tilde_and_diaeresis,
|
||||
AT_tilde_and_macron,
|
||||
AT_tilde_below,
|
||||
AT_topbar,
|
||||
};
|
||||
|
||||
enum AdditionalFlags {
|
||||
AF_ligature = 0x0001,
|
||||
AF_turned = 0x0002,
|
||||
AF_reversed = 0x0004,
|
||||
AF_smallcap = 0x0008,
|
||||
AF_dotless = 0x0010,
|
||||
};
|
||||
|
||||
enum CharType {
|
||||
CT_upper,
|
||||
CT_lower,
|
||||
CT_punct,
|
||||
};
|
||||
|
||||
class Entry {
|
||||
public:
|
||||
wchar_t _character;
|
||||
CharType _char_type;
|
||||
char _ascii_equiv;
|
||||
char _ascii_additional;
|
||||
wchar_t _tolower_character;
|
||||
wchar_t _toupper_character;
|
||||
AccentType _accent_type;
|
||||
int _additional_flags;
|
||||
};
|
||||
|
||||
static const Entry *look_up(wchar_t character);
|
||||
|
||||
private:
|
||||
static void init();
|
||||
static bool _initialized;
|
||||
|
||||
typedef pmap<wchar_t, const Entry *> ByCharacter;
|
||||
static ByCharacter _by_character;
|
||||
enum { max_direct_chars = 256 };
|
||||
static const Entry *_direct_chars[max_direct_chars];
|
||||
};
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user