Panda3D
|
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 ©); 00050 void operator = (const TextAssembler ©); 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 ©); 00135 INLINE void operator = (const TextCharacter ©); 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 ©); 00148 INLINE void operator = (const TextRow ©); 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 ©); 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 ¢roid, 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 ¢roid, 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