Panda3D
 All Classes Functions Variables Enumerations
dynamicTextGlyph.cxx
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
 All Classes Functions Variables Enumerations