Panda3D
dynamicTextGlyph.cxx
1 // Filename: dynamicTextGlyph.cxx
2 // Created by: drose (09Feb02)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "dynamicTextGlyph.h"
16 
17 #ifdef HAVE_FREETYPE
18 
19 #include "dynamicTextFont.h"
20 #include "dynamicTextPage.h"
21 #include "geomTextGlyph.h"
22 #include "geomVertexData.h"
23 #include "geomVertexFormat.h"
24 #include "geomTriangles.h"
25 #include "geomVertexWriter.h"
26 #include "textureAttrib.h"
27 #include "transparencyAttrib.h"
28 #include "colorAttrib.h"
29 #include "renderState.h"
30 #include "config_gobj.h"
31 
32 TypeHandle DynamicTextGlyph::_type_handle;
33 
34 ////////////////////////////////////////////////////////////////////
35 // Function: DynamicTextGlyph::Destructor
36 // Access: Public, Virtual
37 // Description:
38 ////////////////////////////////////////////////////////////////////
39 DynamicTextGlyph::
40 ~DynamicTextGlyph() {
41 }
42 
43 ////////////////////////////////////////////////////////////////////
44 // Function: DynamicTextGlyph::get_row
45 // Access: Public
46 // Description: Returns a pointer to the first byte in the pixel
47 // buffer associated with the leftmost pixel in the
48 // indicated row, where 0 is the topmost row and _y_size
49 // - _margin * 2 - 1 is the bottommost row.
50 ////////////////////////////////////////////////////////////////////
51 unsigned char *DynamicTextGlyph::
52 get_row(int y) {
53  nassertr(y >= 0 && y < _y_size - _margin * 2, (unsigned char *)NULL);
54  nassertr(_page != (DynamicTextPage *)NULL, (unsigned char *)NULL);
55 
56  // First, offset y by the glyph's start.
57  y += _y + _margin;
58  // Also, get the x start.
59  int x = _x + _margin;
60 
61  // Invert y.
62  y = _page->get_y_size() - 1 - y;
63 
64  int offset = (y * _page->get_x_size()) + x;
65  int pixel_width = _page->get_num_components() * _page->get_component_width();
66 
67  return _page->modify_ram_image() + offset * pixel_width;
68 }
69 
70 ////////////////////////////////////////////////////////////////////
71 // Function: DynamicTextGlyph::erase
72 // Access: Public
73 // Description: Erases the glyph from the texture map.
74 ////////////////////////////////////////////////////////////////////
75 void DynamicTextGlyph::
76 erase(DynamicTextFont *font) {
77  nassertv(_page != (DynamicTextPage *)NULL);
78  nassertv(_page->has_ram_image());
79 
80  // The glyph covers the pixels from (_x, _y) over the rectangle
81  // (_x_size, _y_size), but it doesn't include _margin pixels around
82  // the interior of the rectangle. Erase all the pixels that the
83  // glyph covers.
84  _page->fill_region(_x + _margin,
85  _page->get_y_size() - (_y + _y_size - _margin),
86  _x_size - _margin * 2, _y_size - _margin * 2,
87  font->get_bg());
88 }
89 
90 ////////////////////////////////////////////////////////////////////
91 // Function: DynamicTextGlyph::make_geom
92 // Access: Public
93 // Description: Creates the actual geometry for the glyph. The
94 // parameters bitmap_top and bitmap_left are from
95 // FreeType, and indicate the position of the top left
96 // corner of the bitmap relative to the glyph's origin.
97 // The advance number represents the number of pixels
98 // the pen should be advanced after drawing this glyph.
99 ////////////////////////////////////////////////////////////////////
100 void DynamicTextGlyph::
101 make_geom(int bitmap_top, int bitmap_left, PN_stdfloat advance, PN_stdfloat poly_margin,
102  PN_stdfloat tex_x_size, PN_stdfloat tex_y_size,
103  PN_stdfloat font_pixels_per_unit, PN_stdfloat tex_pixels_per_unit) {
104  nassertv(_page != (DynamicTextPage *)NULL);
105 
106  // This function should not be called twice.
107  nassertv(_geom_count == 0);
108 
109  tex_x_size += _margin * 2;
110  tex_y_size += _margin * 2;
111 
112  // Determine the corners of the rectangle in geometric units.
113  PN_stdfloat tex_poly_margin = poly_margin / tex_pixels_per_unit;
114  PN_stdfloat origin_y = bitmap_top / font_pixels_per_unit;
115  PN_stdfloat origin_x = bitmap_left / font_pixels_per_unit;
116  _top = origin_y + tex_poly_margin;
117  _left = origin_x - tex_poly_margin;
118  _bottom = origin_y - tex_y_size / tex_pixels_per_unit - tex_poly_margin;
119  _right = origin_x + tex_x_size / tex_pixels_per_unit + tex_poly_margin;
120 
121  // And the corresponding corners in UV units. We add 0.5f to center
122  // the UV in the middle of its texel, to minimize roundoff errors
123  // when we are close to 1-to-1 pixel size.
124  _uv_top = 1.0f - ((PN_stdfloat)(_y - poly_margin) + 0.5f) / _page->get_y_size();
125  _uv_left = ((PN_stdfloat)(_x - poly_margin) + 0.5f) / _page->get_x_size();
126  _uv_bottom = 1.0f - ((PN_stdfloat)(_y + poly_margin + tex_y_size) + 0.5f) / _page->get_y_size();
127  _uv_right = ((PN_stdfloat)(_x + poly_margin + tex_x_size) + 0.5f) / _page->get_x_size();
128 
129  // Create a corresponding triangle pair. We use a pair of indexed
130  // triangles rather than a single triangle strip, to avoid the bad
131  // vertex duplication behavior with lots of two-triangle strips.
132  PT(GeomVertexData) vdata = new GeomVertexData
133  (string(), GeomVertexFormat::get_v3t2(),
134  Geom::UH_static);
135  vdata->unclean_set_num_rows(4);
136 
137  GeomVertexWriter vertex(vdata, InternalName::get_vertex());
138  GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
139 
140  vertex.add_data3(_left, 0, _top);
141  vertex.add_data3(_left, 0, _bottom);
142  vertex.add_data3(_right, 0, _top);
143  vertex.add_data3(_right, 0, _bottom);
144 
145  texcoord.add_data2(_uv_left, _uv_top);
146  texcoord.add_data2(_uv_left, _uv_bottom);
147  texcoord.add_data2(_uv_right, _uv_top);
148  texcoord.add_data2(_uv_right, _uv_bottom);
149 
150  PT(GeomTriangles) tris = new GeomTriangles(Geom::UH_static);
151  tris->reserve_num_vertices(6);
152  tris->add_vertex(0);
153  tris->add_vertex(1);
154  tris->add_vertex(2);
155  tris->close_primitive();
156  tris->add_vertex(2);
157  tris->add_vertex(1);
158  tris->add_vertex(3);
159  tris->close_primitive();
160 
161  PT(Geom) geom = new GeomTextGlyph(this, vdata);
162  geom->add_primitive(tris);
163  _geom = geom;
164 
165  // The above will increment our _geom_count to 1. Reset it back
166  // down to 0, since our own internal Geom doesn't count.
167  nassertv(_geom_count == 1);
168  _geom_count--;
169 
170  _state = RenderState::make(TextureAttrib::make(_page),
171  TransparencyAttrib::make(TransparencyAttrib::M_alpha));
172  _state = _state->add_attrib(ColorAttrib::make_flat(LColor(1.0f, 1.0f, 1.0f, 1.0f)), -1);
173 
174  _advance = advance / font_pixels_per_unit;
175 }
176 
177 ////////////////////////////////////////////////////////////////////
178 // Function: DynamicTextGlyph::set_geom
179 // Access: Public
180 // Description: Sets the geom from a pre-built object.
181 ////////////////////////////////////////////////////////////////////
182 void DynamicTextGlyph::
183 set_geom(GeomVertexData *vdata, GeomPrimitive *prim,
184  const RenderState *state) {
185  // This function is called when _geom_count = 1, because it was
186  // constructed via the empty Glyph constructor.
187  nassertv(_geom_count == 1);
188  _geom_count--;
189 
190  PT(Geom) geom = new GeomTextGlyph(this, vdata);
191  geom->add_primitive(prim);
192  _geom = geom;
193 
194  // The above will increment our _geom_count to 1. Reset it back
195  // down to 0, since our own internal Geom doesn't count.
196  nassertv(_geom_count == 1);
197  _geom_count--;
198 
199  _state = state;
200 }
201 
202 ////////////////////////////////////////////////////////////////////
203 // Function: DynamicTextGlyph::is_whitespace
204 // Access: Public, Virtual
205 // Description: Returns true if this glyph represents invisible
206 // whitespace, or false if it corresponds to some
207 // visible character.
208 ////////////////////////////////////////////////////////////////////
209 bool DynamicTextGlyph::
210 is_whitespace() const {
211  return (_page == (DynamicTextPage *)NULL);
212 }
213 
214 #endif // HAVE_FREETYPE
This object provides a high-level interface for quickly writing a sequence of numeric values from a v...
bool unclean_set_num_rows(int n)
This method behaves like set_num_rows(), except the new data is not initialized.
This is an abstract base class for a family of classes that represent the fundamental geometry primit...
Definition: geomPrimitive.h:63
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
A container for geometry primitives.
Definition: geom.h:58
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
Definition: renderState.h:53
This is the base class for all three-component vectors and points.
Definition: lvecBase4.h:111
Defines a series of disconnected triangles.
Definition: geomTriangles.h:25
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85