Panda3D
 All Classes Functions Variables Enumerations
textAssembler.h
00001 // Filename: textAssembler.h
00002 // Created by:  drose (06Apr04)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #ifndef TEXTASSEMBLER_H
00016 #define TEXTASSEMBLER_H
00017 
00018 #include "pandabase.h"
00019 
00020 #include "textProperties.h"
00021 #include "textFont.h"
00022 #include "unicodeLatinMap.h"
00023 #include "geomNode.h"
00024 #include "pointerTo.h"
00025 #include "geomTextGlyph.h"
00026 #include "textPropertiesManager.h"
00027 #include "textEncoder.h"
00028 #include "geomVertexRewriter.h"
00029 
00030 #include "pmap.h"
00031 
00032 
00033 class TextEncoder;
00034 class TextGraphic;
00035 class TextAssembler;
00036 
00037 ////////////////////////////////////////////////////////////////////
00038 //       Class : TextAssembler
00039 // Description : This class is not normally used directly by user
00040 //               code, but is used by the TextNode to lay out a block
00041 //               of text and convert it into rows of Geoms according
00042 //               to the TextProperties.  However, user code may take
00043 //               advantage of it, if desired, for very low-level text
00044 //               operations.
00045 ////////////////////////////////////////////////////////////////////
00046 class EXPCL_PANDA_TEXT TextAssembler {
00047 PUBLISHED:
00048   TextAssembler(TextEncoder *encoder);
00049   TextAssembler(const TextAssembler &copy);
00050   void operator = (const TextAssembler &copy);
00051   ~TextAssembler();
00052 
00053   void clear();
00054 
00055   INLINE void set_usage_hint(Geom::UsageHint usage_hint);
00056   INLINE Geom::UsageHint get_usage_hint() const;
00057 
00058   INLINE void set_max_rows(int max_rows);
00059   INLINE int get_max_rows() const;
00060 
00061   INLINE void set_dynamic_merge(bool dynamic_merge);
00062   INLINE bool get_dynamic_merge() const;
00063 
00064   INLINE void set_multiline_mode(bool flag);
00065   INLINE bool get_multiline_mode() const;
00066 
00067   INLINE void set_properties(const TextProperties &properties);
00068   INLINE const TextProperties &get_properties() const;
00069 
00070   bool set_wtext(const wstring &wtext);
00071   bool set_wsubstr(const wstring &wtext, int start, int count);
00072 
00073   wstring get_plain_wtext() const;
00074   wstring get_wordwrapped_plain_wtext() const;
00075   wstring get_wtext() const;
00076   wstring get_wordwrapped_wtext() const;
00077 
00078   bool calc_r_c(int &r, int &c, int n) const;
00079   INLINE int calc_r(int n) const;
00080   INLINE int calc_c(int n) const;
00081   int calc_index(int r, int c) const;
00082 
00083   INLINE int get_num_characters() const;
00084   INLINE wchar_t get_character(int n) const;
00085   INLINE const TextGraphic *get_graphic(int n) const;
00086   INLINE const TextProperties &get_properties(int n) const;
00087   INLINE PN_stdfloat get_width(int n) const;
00088 
00089   INLINE int get_num_rows() const;
00090   INLINE int get_num_cols(int r) const;
00091   INLINE wchar_t get_character(int r, int c) const;
00092   INLINE const TextGraphic *get_graphic(int r, int c) const;
00093   INLINE const TextProperties &get_properties(int r, int c) const;
00094   INLINE PN_stdfloat get_width(int r, int c) const;
00095   PN_stdfloat get_xpos(int r, int c) const;
00096   INLINE PN_stdfloat get_ypos(int r, int c) const;
00097 
00098   PT(PandaNode) assemble_text();
00099 
00100   INLINE const LVector2 &get_ul() const;
00101   INLINE const LVector2 &get_lr() const;
00102 
00103   static PN_stdfloat calc_width(wchar_t character, const TextProperties &properties);
00104   static PN_stdfloat calc_width(const TextGraphic *graphic, const TextProperties &properties);
00105 
00106   static bool has_exact_character(wchar_t character, const TextProperties &properties);
00107   static bool has_character(wchar_t character, const TextProperties &properties);
00108   static bool is_whitespace(wchar_t character, const TextProperties &properties);
00109 
00110 private:
00111   class ComputedProperties : public ReferenceCount {
00112   public:
00113     INLINE ComputedProperties(const TextProperties &orig_properties);
00114     INLINE ComputedProperties(ComputedProperties *based_on, 
00115                               const wstring &wname, TextEncoder *encoder);
00116     void append_delta(wstring &wtext, ComputedProperties *other);
00117 
00118     PT(ComputedProperties) _based_on;
00119     int _depth;
00120     wstring _wname;
00121     TextProperties _properties;
00122   };
00123 
00124   // These structures are built up and operated on by scan_wtext() and
00125   // wordwrap_text().  It represents the unrolling of the embedded \1
00126   // .. \2 sequences embedded in the string into a TextProperties
00127   // pointer associated with each character.
00128   class TextCharacter {
00129   public:
00130     INLINE TextCharacter(wchar_t character, ComputedProperties *cprops);
00131     INLINE TextCharacter(const TextGraphic *graphic, 
00132                          const wstring &graphic_wname,
00133                          ComputedProperties *cprops);
00134     INLINE TextCharacter(const TextCharacter &copy);
00135     INLINE void operator = (const TextCharacter &copy);
00136 
00137     wchar_t _character;
00138     const TextGraphic *_graphic;
00139     wstring _graphic_wname;
00140     PT(ComputedProperties) _cprops;
00141   };
00142   typedef pvector<TextCharacter> TextString;
00143 
00144   class TextRow {
00145   public:
00146     INLINE TextRow(int row_start);
00147     INLINE TextRow(const TextRow &copy);
00148     INLINE void operator = (const TextRow &copy);
00149 
00150     TextString _string;
00151     int _row_start;
00152     bool _got_soft_hyphens;
00153     PN_stdfloat _xpos;
00154     PN_stdfloat _ypos;
00155     PT(ComputedProperties) _eol_cprops;
00156   };
00157   typedef pvector<TextRow> TextBlock;
00158 
00159   PT(ComputedProperties) _initial_cprops;
00160 
00161   // This is the string, unwordwrapped.
00162   TextString _text_string;
00163 
00164   // And here it is, wordwrapped.
00165   TextBlock _text_block;
00166 
00167 #ifndef CPPPARSER  // interrogate has a bit of trouble with wstring iterators.
00168   void scan_wtext(TextString &output_string,
00169                   wstring::const_iterator &si, 
00170                   const wstring::const_iterator &send,
00171                   ComputedProperties *current_cprops);
00172 #endif  // CPPPARSER
00173 
00174   bool wordwrap_text();
00175 
00176   INLINE static PN_stdfloat calc_width(const TextCharacter &tch);
00177   static PN_stdfloat calc_hyphen_width(const TextCharacter &tch);
00178 
00179   // These structures are built up by assemble_paragraph() and
00180   // assemble_row().  They represent the actual Geoms as laid out in a
00181   // paragraph.
00182   
00183   class Piece {
00184   public:
00185     PT(Geom) _geom;
00186     CPT(RenderState) _state;
00187   };
00188   typedef pvector<Piece> Pieces;
00189 
00190   class GeomCollectorKey {
00191   public:
00192     INLINE GeomCollectorKey(const RenderState *state, const GeomVertexFormat *format);
00193     INLINE bool operator < (const GeomCollectorKey &other) const;
00194 
00195     CPT(RenderState) _state;
00196     CPT(GeomVertexFormat) _format;
00197   };
00198 
00199   typedef pmap<int, int> VertexIndexMap;
00200 
00201   class GeomCollector {
00202   public:
00203     GeomCollector(const GeomVertexFormat *format);
00204     GeomCollector(const GeomCollector &copy);
00205 
00206     INLINE void count_geom(const Geom *geom);
00207     GeomPrimitive *get_primitive(TypeHandle prim_type);
00208     int append_vertex(const GeomVertexData *orig_vdata, int orig_row,
00209                       const LMatrix4 &xform);
00210     void append_geom(GeomNode *geom_node, const RenderState *state);
00211 
00212   private:
00213     PT(GeomVertexData) _vdata;
00214     PT(GeomTextGlyph) _geom;
00215     PT(GeomTriangles) _triangles;
00216     PT(GeomLines) _lines;
00217     PT(GeomPoints) _points;
00218   };
00219   typedef pmap<GeomCollectorKey, GeomCollector> GeomCollectorMap;
00220 
00221   class GlyphPlacement : public MemoryBase {
00222   public:
00223     INLINE void add_piece(Geom *geom, const RenderState *state);
00224     void calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
00225                            bool &found_any, Thread *current_thread) const;
00226     void assign_to(GeomNode *geom_node, const RenderState *state) const;
00227     void assign_copy_to(GeomNode *geom_node, const RenderState *state, 
00228                         const LMatrix4 &extra_xform) const;
00229 
00230     void assign_append_to(GeomCollectorMap &geom_collector_map, const RenderState *state,
00231                           const LMatrix4 &extra_xform) const;
00232     void copy_graphic_to(PandaNode *node, const RenderState *state,
00233                          const LMatrix4 &extra_xform) const;
00234 
00235     Pieces _pieces;
00236     PT(PandaNode) _graphic_model;
00237     LMatrix4 _xform;
00238     const TextProperties *_properties;
00239   };
00240   typedef pvector<GlyphPlacement *> PlacedGlyphs;
00241 
00242   void assemble_paragraph(PlacedGlyphs &placed_glyphs);
00243   void assemble_row(TextRow &row,
00244                     PlacedGlyphs &row_placed_glyphs,
00245                     PN_stdfloat &row_width, PN_stdfloat &line_height, 
00246                     TextProperties::Alignment &align, PN_stdfloat &wordwrap);
00247 
00248   // These interfaces are for implementing cheesy accent marks and
00249   // ligatures when the font doesn't support them.
00250   enum CheesyPosition {
00251     CP_above,
00252     CP_below,
00253     CP_top,
00254     CP_bottom,
00255     CP_within,
00256   };
00257   enum CheesyTransform {
00258     CT_none,
00259     CT_mirror_x,
00260     CT_mirror_y,
00261     CT_rotate_90,
00262     CT_rotate_180,
00263     CT_rotate_270,
00264     CT_squash,
00265     CT_squash_mirror_y,
00266     CT_squash_mirror_diag,
00267     CT_small_squash,
00268     CT_small_squash_mirror_y,
00269     CT_small_squash_mirror_diag,
00270     CT_small,
00271     CT_small_rotate_270,
00272     CT_tiny,
00273     CT_tiny_mirror_x,
00274     CT_tiny_rotate_270,
00275   };
00276 
00277   static void
00278   draw_underscore(TextAssembler::PlacedGlyphs &row_placed_glyphs,
00279                   PN_stdfloat underscore_start, PN_stdfloat underscore_end, 
00280                   const TextProperties *underscore_properties);
00281 
00282   static void
00283   get_character_glyphs(int character, const TextProperties *properties,
00284                        bool &got_glyph, const TextGlyph *&glyph,
00285                        const TextGlyph *&second_glyph,
00286                        UnicodeLatinMap::AccentType &accent_type,
00287                        int &additional_flags,
00288                        PN_stdfloat &glyph_scale, PN_stdfloat &advance_scale);
00289 
00290   void
00291   tack_on_accent(UnicodeLatinMap::AccentType accent_type,
00292                  const LPoint3 &min_vert, const LPoint3 &max_vert,
00293                  const LPoint3 &centroid,
00294                  const TextProperties *properties, GlyphPlacement *placement) const;
00295   bool 
00296   tack_on_accent(char accent_mark, CheesyPosition position,
00297                  CheesyTransform transform,
00298                  const LPoint3 &min_vert, const LPoint3 &max_vert,
00299                  const LPoint3 &centroid,
00300                  const TextProperties *properties, GlyphPlacement *placement) const;
00301 
00302   // These are filled in by assemble_paragraph().
00303   LVector2 _ul;
00304   LVector2 _lr;
00305   PN_stdfloat _next_row_ypos;
00306 
00307   TextEncoder *_encoder;
00308   Geom::UsageHint _usage_hint;
00309   int _max_rows;
00310   bool _dynamic_merge;
00311   bool _multiline_mode;
00312 
00313 };
00314 
00315 #include "textAssembler.I"
00316 
00317 #endif
00318 
 All Classes Functions Variables Enumerations