Browse Source

has_character, is_whitespace

David Rose 17 years ago
parent
commit
cb50a97b20

+ 2 - 2
panda/src/text/dynamicTextGlyph.I

@@ -16,7 +16,7 @@
 
 ////////////////////////////////////////////////////////////////////
 //     Function: DynamicTextGlyph::Constructor
-//       Access: Publiic
+//       Access: Public
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 INLINE DynamicTextGlyph::
@@ -33,7 +33,7 @@ DynamicTextGlyph(int character, DynamicTextPage *page, int x, int y,
 
 ////////////////////////////////////////////////////////////////////
 //     Function: DynamicTextGlyph::Constructor
-//       Access: Publiic
+//       Access: Public
 //  Description: This constructor makes an empty glyph, whose only
 //               purpose is to remember its width.  It has no bitmap
 //               and no Geom.

+ 12 - 0
panda/src/text/dynamicTextGlyph.cxx

@@ -191,5 +191,17 @@ set_geom(GeomVertexData *vdata, GeomPrimitive *prim,
   _state = state;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DynamicTextGlyph::is_whitespace
+//       Access: Public, Virtual
+//  Description: Returns true if this glyph represents invisible
+//               whitespace, or false if it corresponds to some
+//               visible character.
+////////////////////////////////////////////////////////////////////
+bool DynamicTextGlyph::
+is_whitespace() const {
+  return (_page == (DynamicTextPage *)NULL);
+}
+
 
 #endif  // HAVE_FREETYPE

+ 1 - 0
panda/src/text/dynamicTextGlyph.h

@@ -51,6 +51,7 @@ public:
                  float font_pixels_per_unit, float tex_pixels_per_unit);
   void set_geom(GeomVertexData *vdata, GeomPrimitive *prim, 
                 const RenderState *state);
+  virtual bool is_whitespace() const;
 
   DynamicTextPage *_page;
   int _geom_count;

+ 109 - 2
panda/src/text/textAssembler.cxx

@@ -626,7 +626,7 @@ assemble_text() {
 
 ////////////////////////////////////////////////////////////////////
 //     Function: TextAssembler::calc_width
-//       Access: Private, Static
+//       Access: Published, Static
 //  Description: Returns the width of a single character, according to
 //               its associated font.  This also correctly calculates
 //               the width of cheesy ligatures and accented
@@ -668,7 +668,7 @@ calc_width(wchar_t character, const TextProperties &properties) {
 
 ////////////////////////////////////////////////////////////////////
 //     Function: TextAssembler::calc_width
-//       Access: Private, Static
+//       Access: Published, Static
 //  Description: Returns the width of a single TextGraphic image.
 ////////////////////////////////////////////////////////////////////
 float TextAssembler::
@@ -677,6 +677,113 @@ calc_width(const TextGraphic *graphic, const TextProperties &properties) {
   return (frame[1] - frame[0]) * properties.get_glyph_scale() * properties.get_text_scale();
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: TextAssembler::has_exact_character
+//       Access: Published, Static
+//  Description: Returns true if the named character exists in the
+//               font exactly as named, false otherwise.  Note that
+//               because Panda can assemble glyphs together
+//               automatically using cheesy accent marks, this is not
+//               a reliable indicator of whether a suitable glyph can
+//               be rendered for the character.  For that, use
+//               has_character() instead.
+//
+//               This returns true for whitespace and Unicode
+//               whitespace characters (if they exist in the font),
+//               but returns false for characters that would render
+//               with the "invalid glyph".  It also returns false for
+//               characters that would be synthesized within Panda,
+//               but see has_character().
+////////////////////////////////////////////////////////////////////
+bool TextAssembler::
+has_exact_character(wchar_t character, const TextProperties &properties) {
+  if (character == ' ' || character == '\n') {
+    // A space is a special case.  Every font implicitly has a space.
+    // We also treat newlines specially.
+    return true;
+  }
+
+  TextFont *font = properties.get_font();
+  nassertr(font != (TextFont *)NULL, false);
+
+  const TextGlyph *glyph = NULL;
+  return font->get_glyph(character, glyph);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TextAssembler::has_character
+//       Access: Published, Static
+//  Description: Returns true if the named character exists in the
+//               font or can be synthesized by Panda, false otherwise.
+//               (Panda can synthesize some accented characters by
+//               combining similar-looking glyphs from the font.)
+//
+//               This returns true for whitespace and Unicode
+//               whitespace characters (if they exist in the font),
+//               but returns false for characters that would render
+//               with the "invalid glyph".
+////////////////////////////////////////////////////////////////////
+bool TextAssembler::
+has_character(wchar_t character, const TextProperties &properties) {
+  if (character == ' ' || character == '\n') {
+    // A space is a special case.  Every font implicitly has a space.
+    // We also treat newlines specially.
+    return true;
+  }
+
+  bool got_glyph;
+  const TextGlyph *first_glyph = NULL;
+  const TextGlyph *second_glyph = NULL;
+  UnicodeLatinMap::AccentType accent_type;
+  int additional_flags;
+  float glyph_scale;
+  float advance_scale;
+  get_character_glyphs(character, &properties, 
+                       got_glyph, first_glyph, second_glyph, accent_type,
+                       additional_flags, glyph_scale, advance_scale);
+  return got_glyph;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TextAssembler::is_whitespace
+//       Access: Published, Static
+//  Description: Returns true if the indicated character represents
+//               whitespace in the font, or false if anything visible
+//               will be rendered for it.
+//
+//               This returns true for whitespace and Unicode
+//               whitespace characters (if they exist in the font),
+//               and returns false for any other characters, including
+//               characters that do not exist in the font (these would
+//               be rendered with the "invalid glyph", which is
+//               visible).
+//
+//               Note that this function can be reliably used to
+//               identify Unicode whitespace characters only if the
+//               font has all of the whitespace characters defined.
+//               It will return false for any character not in the
+//               font, even if it is an official Unicode whitespace
+//               character.
+////////////////////////////////////////////////////////////////////
+bool TextAssembler::
+is_whitespace(wchar_t character, const TextProperties &properties) {
+  if (character == ' ' || character == '\n') {
+    // A space or a newline is a special case.
+    return true;
+  }
+
+
+  TextFont *font = properties.get_font();
+  nassertr(font != (TextFont *)NULL, false);
+
+  const TextGlyph *glyph = NULL;
+  if (!font->get_glyph(character, glyph)) {
+    return false;
+  }
+
+  return glyph->is_whitespace();
+}
+
 #ifndef CPPPARSER  // interrogate has a bit of trouble with wstring.
 ////////////////////////////////////////////////////////////////////
 //     Function: TextAssembler::scan_wtext

+ 4 - 0
panda/src/text/textAssembler.h

@@ -93,6 +93,10 @@ PUBLISHED:
   static float calc_width(wchar_t character, const TextProperties &properties);
   static float calc_width(const TextGraphic *graphic, const TextProperties &properties);
 
+  static bool has_exact_character(wchar_t character, const TextProperties &properties);
+  static bool has_character(wchar_t character, const TextProperties &properties);
+  static bool is_whitespace(wchar_t character, const TextProperties &properties);
+
 private:
   class ComputedProperties : public ReferenceCount {
   public:

+ 14 - 0
panda/src/text/textGlyph.cxx

@@ -22,3 +22,17 @@
 TextGlyph::
 ~TextGlyph() {
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: TextGlyph::is_whitespace
+//       Access: Public, Virtual
+//  Description: Returns true if this glyph represents invisible
+//               whitespace, or false if it corresponds to some
+//               visible character.
+////////////////////////////////////////////////////////////////////
+bool TextGlyph::
+is_whitespace() const {
+  // In a static font, there is no explicit glyph for whitespace, so
+  // all glyphs are non-whitespace.
+  return false;
+}

+ 2 - 0
panda/src/text/textGlyph.h

@@ -42,6 +42,8 @@ public:
   INLINE const RenderState *get_state() const;
   INLINE float get_advance() const;
 
+  virtual bool is_whitespace() const;
+
 protected:
   int _character;
   CPT(Geom) _geom;

+ 1 - 1
panda/src/text/textNode.I

@@ -1161,7 +1161,7 @@ append_text(const string &text) {
 //               Unicode.
 ////////////////////////////////////////////////////////////////////
 INLINE void TextNode::
-append_unicode_char(int character) {
+append_unicode_char(wchar_t character) {
   TextEncoder::append_unicode_char(character);
   invalidate_with_measure();
 }

+ 83 - 1
panda/src/text/textNode.cxx

@@ -179,7 +179,7 @@ TextNode::
 //               wide character (greater than 255).
 ////////////////////////////////////////////////////////////////////
 float TextNode::
-calc_width(int character) const {
+calc_width(wchar_t character) const {
   TextFont *font = get_font();
   if (font == (TextFont *)NULL) {
     return 0.0f;
@@ -188,6 +188,88 @@ calc_width(int character) const {
   return TextAssembler::calc_width(character, *this);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: TextNode::has_exact_character
+//       Access: Published
+//  Description: Returns true if the named character exists in the
+//               font exactly as named, false otherwise.  Note that
+//               because Panda can assemble glyphs together
+//               automatically using cheesy accent marks, this is not
+//               a reliable indicator of whether a suitable glyph can
+//               be rendered for the character.  For that, use
+//               has_character() instead.
+//
+//               This returns true for whitespace and Unicode
+//               whitespace characters (if they exist in the font),
+//               but returns false for characters that would render
+//               with the "invalid glyph".  It also returns false for
+//               characters that would be synthesized within Panda,
+//               but see has_character().
+////////////////////////////////////////////////////////////////////
+bool TextNode::
+has_exact_character(wchar_t character) const {
+  TextFont *font = get_font();
+  if (font == (TextFont *)NULL) {
+    return false;
+  }
+
+  return TextAssembler::has_exact_character(character, *this);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TextNode::has_character
+//       Access: Published
+//  Description: Returns true if the named character exists in the
+//               font or can be synthesized by Panda, false otherwise.
+//               (Panda can synthesize some accented characters by
+//               combining similar-looking glyphs from the font.)
+//
+//               This returns true for whitespace and Unicode
+//               whitespace characters (if they exist in the font),
+//               but returns false for characters that would render
+//               with the "invalid glyph".
+////////////////////////////////////////////////////////////////////
+bool TextNode::
+has_character(wchar_t character) const {
+  TextFont *font = get_font();
+  if (font == (TextFont *)NULL) {
+    return false;
+  }
+
+  return TextAssembler::has_character(character, *this);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TextNode::is_whitespace
+//       Access: Published
+//  Description: Returns true if the indicated character represents
+//               whitespace in the font, or false if anything visible
+//               will be rendered for it.
+//
+//               This returns true for whitespace and Unicode
+//               whitespace characters (if they exist in the font),
+//               and returns false for any other characters, including
+//               characters that do not exist in the font (these would
+//               be rendered with the "invalid glyph", which is
+//               visible).
+//
+//               Note that this function can be reliably used to
+//               identify Unicode whitespace characters only if the
+//               font has all of the whitespace characters defined.
+//               It will return false for any character not in the
+//               font, even if it is an official Unicode whitespace
+//               character.
+////////////////////////////////////////////////////////////////////
+bool TextNode::
+is_whitespace(wchar_t character) const {
+  TextFont *font = get_font();
+  if (font == (TextFont *)NULL) {
+    return false;
+  }
+
+  return TextAssembler::is_whitespace(character, *this);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: TextNode::calc_width
 //       Access: Published

+ 6 - 2
panda/src/text/textNode.h

@@ -183,7 +183,7 @@ PUBLISHED:
   INLINE void set_text(const string &text, Encoding encoding);
   INLINE void clear_text();
   INLINE void append_text(const string &text);
-  INLINE void append_unicode_char(int character);
+  INLINE void append_unicode_char(wchar_t character);
 
   // After the text has been set, you can query this to determine how
   // it will be wordwrapped.
@@ -191,8 +191,12 @@ PUBLISHED:
 
   // These methods calculate the width of a single character or a line
   // of text in the current font.
-  float calc_width(int character) const;
+  float calc_width(wchar_t character) const;
   INLINE float calc_width(const string &line) const;
+  
+  bool has_exact_character(wchar_t character) const;
+  bool has_character(wchar_t character) const;
+  bool is_whitespace(wchar_t character) const;
 
   // Direct support for wide-character strings.
   INLINE void set_wtext(const wstring &wtext);