Panda3D
|
00001 // Filename: dynamicTextGlyph.cxx 00002 // Created by: drose (09Feb02) 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 #include "dynamicTextGlyph.h" 00016 00017 #ifdef HAVE_FREETYPE 00018 00019 #include "dynamicTextPage.h" 00020 #include "geomTextGlyph.h" 00021 #include "geomVertexData.h" 00022 #include "geomVertexFormat.h" 00023 #include "geomTriangles.h" 00024 #include "geomVertexWriter.h" 00025 #include "textureAttrib.h" 00026 #include "transparencyAttrib.h" 00027 #include "colorAttrib.h" 00028 #include "renderState.h" 00029 #include "config_gobj.h" 00030 00031 //////////////////////////////////////////////////////////////////// 00032 // Function: DynamicTextGlyph::Destructor 00033 // Access: Public, Virtual 00034 // Description: 00035 //////////////////////////////////////////////////////////////////// 00036 DynamicTextGlyph:: 00037 ~DynamicTextGlyph() { 00038 } 00039 00040 //////////////////////////////////////////////////////////////////// 00041 // Function: DynamicTextGlyph::get_row 00042 // Access: Public 00043 // Description: Returns a pointer to the first byte in the pixel 00044 // buffer associated with the leftmost pixel in the 00045 // indicated row, where 0 is the topmost row and _y_size 00046 // - _margin * 2 - 1 is the bottommost row. 00047 //////////////////////////////////////////////////////////////////// 00048 unsigned char *DynamicTextGlyph:: 00049 get_row(int y) { 00050 nassertr(y >= 0 && y < _y_size - _margin * 2, (unsigned char *)NULL); 00051 nassertr(_page != (DynamicTextPage *)NULL, (unsigned char *)NULL); 00052 00053 // First, offset y by the glyph's start. 00054 y += _y + _margin; 00055 // Also, get the x start. 00056 int x = _x + _margin; 00057 00058 // Invert y. 00059 y = _page->get_y_size() - 1 - y; 00060 00061 int offset = (y * _page->get_x_size()) + x; 00062 int pixel_width = _page->get_num_components() * _page->get_component_width(); 00063 00064 return _page->modify_ram_image() + offset * pixel_width; 00065 } 00066 00067 //////////////////////////////////////////////////////////////////// 00068 // Function: DynamicTextGlyph::erase 00069 // Access: Public 00070 // Description: Erases the glyph from the texture map. 00071 //////////////////////////////////////////////////////////////////// 00072 void DynamicTextGlyph:: 00073 erase(DynamicTextFont *font) { 00074 nassertv(_page != (DynamicTextPage *)NULL); 00075 nassertv(_page->has_ram_image()); 00076 00077 // The glyph covers the pixels from (_x, _y) over the rectangle 00078 // (_x_size, _y_size), but it doesn't include _margin pixels around 00079 // the interior of the rectangle. Erase all the pixels that the 00080 // glyph covers. 00081 _page->fill_region(_x + _margin, 00082 _page->get_y_size() - (_y + _y_size - _margin), 00083 _x_size - _margin * 2, _y_size - _margin * 2, 00084 font->get_bg()); 00085 } 00086 00087 //////////////////////////////////////////////////////////////////// 00088 // Function: DynamicTextGlyph::make_geom 00089 // Access: Public 00090 // Description: Creates the actual geometry for the glyph. The 00091 // parameters bitmap_top and bitmap_left are from 00092 // FreeType, and indicate the position of the top left 00093 // corner of the bitmap relative to the glyph's origin. 00094 // The advance number represents the number of pixels 00095 // the pen should be advanced after drawing this glyph. 00096 //////////////////////////////////////////////////////////////////// 00097 void DynamicTextGlyph:: 00098 make_geom(int bitmap_top, int bitmap_left, PN_stdfloat advance, PN_stdfloat poly_margin, 00099 PN_stdfloat tex_x_size, PN_stdfloat tex_y_size, 00100 PN_stdfloat font_pixels_per_unit, PN_stdfloat tex_pixels_per_unit) { 00101 nassertv(_page != (DynamicTextPage *)NULL); 00102 00103 // This function should not be called twice. 00104 nassertv(_geom_count == 0); 00105 00106 tex_x_size += _margin * 2; 00107 tex_y_size += _margin * 2; 00108 00109 // Determine the corners of the rectangle in geometric units. 00110 PN_stdfloat tex_poly_margin = poly_margin / tex_pixels_per_unit; 00111 PN_stdfloat origin_y = bitmap_top / font_pixels_per_unit; 00112 PN_stdfloat origin_x = bitmap_left / font_pixels_per_unit; 00113 PN_stdfloat top = origin_y + tex_poly_margin; 00114 PN_stdfloat left = origin_x - tex_poly_margin; 00115 PN_stdfloat bottom = origin_y - tex_y_size / tex_pixels_per_unit - tex_poly_margin; 00116 PN_stdfloat right = origin_x + tex_x_size / tex_pixels_per_unit + tex_poly_margin; 00117 00118 // And the corresponding corners in UV units. We add 0.5f to center 00119 // the UV in the middle of its texel, to minimize roundoff errors 00120 // when we are close to 1-to-1 pixel size. 00121 PN_stdfloat uv_top = 1.0f - ((PN_stdfloat)(_y - poly_margin) + 0.5f) / _page->get_y_size(); 00122 PN_stdfloat uv_left = ((PN_stdfloat)(_x - poly_margin) + 0.5f) / _page->get_x_size(); 00123 PN_stdfloat uv_bottom = 1.0f - ((PN_stdfloat)(_y + poly_margin + tex_y_size) + 0.5f) / _page->get_y_size(); 00124 PN_stdfloat uv_right = ((PN_stdfloat)(_x + poly_margin + tex_x_size) + 0.5f) / _page->get_x_size(); 00125 // Create a corresponding triangle pair. We use a pair of indexed 00126 // triangles rather than a single triangle strip, to avoid the bad 00127 // vertex duplication behavior with lots of two-triangle strips. 00128 PT(GeomVertexData) vdata = new GeomVertexData 00129 (string(), GeomVertexFormat::get_v3t2(), 00130 Geom::UH_static); 00131 GeomVertexWriter vertex(vdata, InternalName::get_vertex()); 00132 GeomVertexWriter texcoord(vdata, InternalName::get_texcoord()); 00133 00134 vertex.add_data3(left, 0, top); 00135 vertex.add_data3(left, 0, bottom); 00136 vertex.add_data3(right, 0, top); 00137 vertex.add_data3(right, 0, bottom); 00138 00139 texcoord.add_data2(uv_left, uv_top); 00140 texcoord.add_data2(uv_left, uv_bottom); 00141 texcoord.add_data2(uv_right, uv_top); 00142 texcoord.add_data2(uv_right, uv_bottom); 00143 00144 PT(GeomTriangles) tris = new GeomTriangles(Geom::UH_static); 00145 tris->add_vertex(0); 00146 tris->add_vertex(1); 00147 tris->add_vertex(2); 00148 tris->close_primitive(); 00149 tris->add_vertex(2); 00150 tris->add_vertex(1); 00151 tris->add_vertex(3); 00152 tris->close_primitive(); 00153 00154 PT(Geom) geom = new GeomTextGlyph(this, vdata); 00155 geom->add_primitive(tris); 00156 _geom = geom; 00157 00158 // The above will increment our _geom_count to 1. Reset it back 00159 // down to 0, since our own internal Geom doesn't count. 00160 nassertv(_geom_count == 1); 00161 _geom_count--; 00162 00163 _state = RenderState::make(TextureAttrib::make(_page), 00164 TransparencyAttrib::make(TransparencyAttrib::M_alpha)); 00165 _state = _state->add_attrib(ColorAttrib::make_flat(LColor(1.0f, 1.0f, 1.0f, 1.0f)), -1); 00166 00167 _advance = advance / font_pixels_per_unit; 00168 } 00169 00170 00171 //////////////////////////////////////////////////////////////////// 00172 // Function: DynamicTextGlyph::set_geom 00173 // Access: Public 00174 // Description: Sets the geom from a pre-built object. 00175 //////////////////////////////////////////////////////////////////// 00176 void DynamicTextGlyph:: 00177 set_geom(GeomVertexData *vdata, GeomPrimitive *prim, 00178 const RenderState *state) { 00179 // This function is called when _geom_count = 1, because it was 00180 // constructed via the empty Glyph constructor. 00181 nassertv(_geom_count == 1); 00182 _geom_count--; 00183 00184 PT(Geom) geom = new GeomTextGlyph(this, vdata); 00185 geom->add_primitive(prim); 00186 _geom = geom; 00187 00188 // The above will increment our _geom_count to 1. Reset it back 00189 // down to 0, since our own internal Geom doesn't count. 00190 nassertv(_geom_count == 1); 00191 _geom_count--; 00192 00193 _state = state; 00194 } 00195 00196 //////////////////////////////////////////////////////////////////// 00197 // Function: DynamicTextGlyph::is_whitespace 00198 // Access: Public, Virtual 00199 // Description: Returns true if this glyph represents invisible 00200 // whitespace, or false if it corresponds to some 00201 // visible character. 00202 //////////////////////////////////////////////////////////////////// 00203 bool DynamicTextGlyph:: 00204 is_whitespace() const { 00205 return (_page == (DynamicTextPage *)NULL); 00206 } 00207 00208 00209 #endif // HAVE_FREETYPE