Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

OSGTextVectorGlyph.cpp

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002  *                                OpenSG                                     *
00003  *                                                                           *
00004  *                                                                           *
00005  *             Copyright (C) 2000-2002 by the OpenSG Forum                   *
00006  *                                                                           *
00007  *                            www.opensg.org                                 *
00008  *                                                                           *
00009  *   contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de          *
00010  *                                                                           *
00011 \*---------------------------------------------------------------------------*/
00012 /*---------------------------------------------------------------------------*\
00013  *                                License                                    *
00014  *                                                                           *
00015  * This library is free software; you can redistribute it and/or modify it   *
00016  * under the terms of the GNU Library General Public License as published    *
00017  * by the Free Software Foundation, version 2.                               *
00018  *                                                                           *
00019  * This library is distributed in the hope that it will be useful, but       *
00020  * WITHOUT ANY WARRANTY; without even the implied warranty of                *
00021  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU         *
00022  * Library General Public License for more details.                          *
00023  *                                                                           *
00024  * You should have received a copy of the GNU Library General Public         *
00025  * License along with this library; if not, write to the Free Software       *
00026  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                 *
00027  *                                                                           *
00028 \*---------------------------------------------------------------------------*/
00029 /*---------------------------------------------------------------------------*\
00030  *                                Changes                                    *
00031  *                                                                           *
00032  *                                                                           *
00033  *                                                                           *
00034  *                                                                           *
00035  *                                                                           *
00036  *                                                                           *
00037 \*---------------------------------------------------------------------------*/
00038 
00039 #ifdef _MSC_VER
00040 # pragma warning (disable: 4786)
00041 #endif
00042 
00043 #include "OSGTextVectorGlyph.h"
00044 
00045 #include <OSGGLU.h>
00046 
00047 #ifdef __sgi
00048 # include <assert.h>
00049 # include <math.h>
00050 #else
00051 # include <cassert>
00052 # include <cmath>
00053 #endif
00054 
00055 
00056 using namespace std;
00057 
00058 
00059 OSG_BEGIN_NAMESPACE
00060 
00061 
00062 //----------------------------------------------------------------------
00063 // Destructor
00064 // Author: pdaehne
00065 //----------------------------------------------------------------------
00066 TextVectorGlyph::~TextVectorGlyph() {}
00067 
00068 
00069 //----------------------------------------------------------------------
00070 // Returns the width of the glyph
00071 // Author: pdaehne
00072 //----------------------------------------------------------------------
00073 Real32 TextVectorGlyph::getWidth() const
00074 { return _width; }
00075 
00076 
00077 //----------------------------------------------------------------------
00078 // Returns the height of the glyph
00079 // Author: pdaehne
00080 //----------------------------------------------------------------------
00081 Real32 TextVectorGlyph::getHeight() const
00082 { return _height; }
00083 
00084 
00085 //----------------------------------------------------------------------
00086 // Returns the x bearing of the glyph for horizontal layout
00087 // Author: pdaehne
00088 //----------------------------------------------------------------------
00089 Real32 TextVectorGlyph::getHoriBearingX() const
00090 { return _horiBearingX; }
00091 
00092 
00093 //----------------------------------------------------------------------
00094 // Returns the y bearing of the glyph for horizontal layout
00095 // Author: pdaehne
00096 //----------------------------------------------------------------------
00097 Real32 TextVectorGlyph::getHoriBearingY() const
00098 { return _horiBearingY; }
00099 
00100 
00101 //----------------------------------------------------------------------
00102 // Returns the x bearing of the glyph for vertical layout
00103 // Author: pdaehne
00104 //----------------------------------------------------------------------
00105 Real32 TextVectorGlyph::getVertBearingX() const
00106 { return _vertBearingX; }
00107 
00108 
00109 //----------------------------------------------------------------------
00110 // Returns the y bearing of the glyph for vertical layout
00111 // Author: pdaehne
00112 //----------------------------------------------------------------------
00113 Real32 TextVectorGlyph::getVertBearingY() const
00114 { return _vertBearingY; }
00115 
00116 
00117 //----------------------------------------------------------------------
00118 // Evalutes a quadratic bezier curve via "forward differencing" (i.e. taylor
00119 // expansion) in a non-adaptive way.
00120 // The output is written into the specified PolygonContour &polygonContour.
00121 //
00122 // Note: The last point is not written into the polygonContour.
00123 //
00124 // Author: afischle
00125 //----------------------------------------------------------------------
00126 static void evalCubicBezierCurve(const Vec2f &pt1, const Vec2f &pt2, const Vec2f &pt3, const Vec2f &pt4,
00127                                  const UInt32 level, vector<Vec2f> &coords)
00128 {
00129     // granularity for the detail level
00130     const UInt32 knotsPerLevel = 3;
00131     // number of points generated for detail level n
00132     const UInt32 steps = knotsPerLevel * (level + 1) - 1;
00133 
00134     const Real32 h = 1.0f / steps;
00135     const Real32 hh = h * h; // h squared
00136     const Real32 hhh = h * hh; // h cube
00137 
00138     // initialize taylor coefficients for a bezier curve f at x=0
00139     // f = f, f' = df, f'' = ddf, f''' = dddf
00140     Vec2f f = pt1;
00141     Vec2f df = (pt2 - pt1) * 3.0f * h;
00142 
00143     Vec2f ddf_div_2 = (pt1 - pt2  * 2.0f + pt3) * 3.0f * hh;
00144     Vec2f ddf = ddf_div_2 + ddf_div_2;
00145 
00146     const Vec2f dddf_div_2 = ((pt2 - pt3) * 3.0f + pt4 - pt1) * 3.0f * hhh;
00147     const Vec2f dddf = dddf_div_2 + dddf_div_2;
00148     const Vec2f dddf_div_6 = dddf_div_2 * (1.0f / 3.0f);
00149 
00150     // sum up the taylor coefficients to obtain f(x+h)
00151     UInt32 i;
00152     for (i = steps; i > 0; --i)
00153     {
00154         coords.push_back(f);
00155         // taylor series of a cubic bezier curve (i.e. polynomial) f
00156         // and its derivatives f', f''
00157         f   += df + ddf_div_2 + dddf_div_6;
00158         df  += ddf + dddf_div_2;
00159         ddf += dddf;
00160         ddf_div_2 += dddf_div_2;
00161     }
00162 }
00163 
00164 
00165 //----------------------------------------------------------------------
00166 // Evalutes a quadratic bezier curve via "forward differencing" (i.e. taylor
00167 // expansion) in a non-adaptive way.
00168 // The output is written into the specified PolygonContour &polygonContour.
00169 //
00170 // Note: The last point is not written into the polygonContour.
00171 //
00172 // Author: afischle
00173 //----------------------------------------------------------------------
00174 static void evalQuadraticBezierCurve(const Vec2f &pt1, const Vec2f &pt2, const Vec2f &pt3,
00175                                      const UInt32 level, vector<Vec2f> &coords)
00176 {
00177     const UInt32 knotsPerLevel = 3;
00178     // determines the number of points generated for level n
00179     const UInt32 steps = knotsPerLevel * (level + 1) - 1;
00180 
00181     const Real32 h = 1.0f / steps;
00182     const Real32 hh = h * h;
00183 
00184     // f(0)
00185     Vec2f f = pt1;
00186 
00187     // df(0) = -2*P_0 + 2P_1
00188     Vec2f df = (pt2 - pt1) * 2.f * h;
00189 
00190     // ddf(0) = 2*P_0 - 4*P_1 + 2*P_2
00191     const Vec2f ddf_div_2 = (pt1 - pt2 * 2.f + pt3) * hh;
00192     const Vec2f ddf = ddf_div_2 + ddf_div_2;
00193 
00194     // sum up the taylor coefficients to obtain f(x+h)
00195     UInt32 i;
00196     for (i = steps; i > 0; --i)
00197     {
00198         coords.push_back(f);
00199         // taylor series of a quadratic bezier curve (i.e polynomial) f
00200         f  += df + ddf_div_2;
00201         df += ddf;
00202     }
00203 }
00204 
00205 
00206 //----------------------------------------------------------------------
00207 // Selects the bezier curve evaluation function for the specified order
00208 // and evaluates the bezier curve.
00209 //
00210 // returns a PolygonOutline containing the rendered polygon outline.
00211 //
00212 // Author: afischle
00213 //----------------------------------------------------------------------
00214 static void evalBezierCurve(const TextVectorGlyph::Contour &contour, UInt32 &index,
00215                             const UInt32 level,
00216                             vector<Vec2f> &coords)
00217 {
00218     assert(index + 1 < contour.size());
00219     switch (contour[index + 1].type)
00220     {
00221         // linear segment - copy first point only
00222         case TextVectorGlyph::Point::PT_ON:
00223             assert(index < contour.size());
00224             coords.push_back(contour[index].pos);
00225             ++index;
00226             break;
00227             // quadratic segment - last point point omitted by evaluation function
00228         case TextVectorGlyph::Point::PT_QUAD:
00229             assert(index + 2 < contour.size());
00230             evalQuadraticBezierCurve(contour[index].pos, contour[index + 1].pos, contour[index + 2].pos, level, coords);
00231             index += 2;
00232             break;
00233             // cubic segment - last point point omitted by evaluation function
00234         case TextVectorGlyph::Point::PT_CUBIC:
00235             assert(index + 3 < contour.size());
00236             evalCubicBezierCurve(contour[index].pos, contour[index + 1].pos, contour[index + 2].pos, contour[index + 3].pos, level, coords);
00237             index += 3;
00238             break;
00239         default:
00240             assert(false);
00241             break;
00242     }
00243 }
00244 
00245 
00246 //----------------------------------------------------------------------
00247 // Tesselation callback function - Called at the beginning of a primitive
00248 // Author: afischle, pdaehne
00249 //----------------------------------------------------------------------
00250 static void OSG_APIENTRY gluTessBeginDataCB(GLenum type, void *polygonData)
00251 {
00252     TextVectorGlyph::PolygonOutline *outline = reinterpret_cast<TextVectorGlyph::PolygonOutline*>(polygonData);
00253     assert(outline != 0);
00254     outline->types.push_back(TextVectorGlyph::PolygonOutline::TypeIndex(type, 0));
00255 }
00256 
00257 
00258 //----------------------------------------------------------------------
00259 // Tesselation callback function - Called at the ned of a primitive
00260 // Author: afischle, pdaehne
00261 //----------------------------------------------------------------------
00262 static void OSG_APIENTRY gluTessEndDataCB(void *polygonData)
00263 {
00264     TextVectorGlyph::PolygonOutline *outline = reinterpret_cast<TextVectorGlyph::PolygonOutline*>(polygonData);
00265     assert(outline != 0);
00266     assert(outline->types.empty() == false);
00267     outline->types.back().second = outline->indices.size();
00268 }
00269 
00270 
00271 //----------------------------------------------------------------------
00272 // Vertex data handler: Receives the triangle vertex indices from the
00273 //                      GLU Tesselator
00274 // Author: afischle, pdaehne
00275 //----------------------------------------------------------------------
00276 static void OSG_APIENTRY gluTessVertexDataCB(void *vertexData, void *polygonData)
00277 {
00278     TextVectorGlyph::PolygonOutline *outline = reinterpret_cast<TextVectorGlyph::PolygonOutline*>(polygonData);
00279 #ifdef __sgi
00280     // the reinterpret_cast doesn't compile on irix with mips pro 7.4 compiler ...
00281     char str[20];
00282     sprintf(str, "%p", vertexData);
00283     UInt64 value;
00284     sscanf(str, "%llx", &value);
00285     UInt32 coordIndex = UInt32(value);
00286 #else
00287     UInt32 coordIndex = (UInt32)vertexData;
00288 #endif
00289     assert(outline != 0);
00290     outline->indices.push_back(coordIndex);
00291 }
00292 
00293 
00294 //----------------------------------------------------------------------
00295 // Combine data handler: Linearly combines vertices in case of self intersections
00296 //                       and inserts them into the frontFace and vertexIndices
00297 //                       structures.
00298 // Author: afischle, pdaehne
00299 //----------------------------------------------------------------------
00300 static void OSG_APIENTRY gluTessCombineDataCB(GLdouble coords[3], void *vertexData[4],
00301                                  GLfloat weight[4], void **outDatab,
00302                                  void *polygonData)
00303 {
00304     TextVectorGlyph::PolygonOutline *outline = reinterpret_cast<TextVectorGlyph::PolygonOutline*>(polygonData);
00305     assert(outDatab != 0);
00306     *outDatab = reinterpret_cast<void*>(outline->coords.size());
00307     assert(outline != 0);
00308     outline->coords.push_back(Vec2f(coords[0], coords[1]));
00309 }
00310 
00311 
00312 //----------------------------------------------------------------------
00313 // Returns a PolygonOutline containing only on-curve points with the specified
00314 // detail level. The contours contained in this outline are not closed!
00315 // Author: afischle, pdaehne
00316 //----------------------------------------------------------------------
00317 const TextVectorGlyph::PolygonOutline &TextVectorGlyph::getLines(UInt32 level) const
00318 {
00319     // Try to find the polygon outline of the specified detail level in the
00320     // cache map
00321     PolygonOutlineMap::const_iterator it = _polygonOutlineMap.find(level);
00322     if (it != _polygonOutlineMap.end())
00323         // We already have that level - return the corresponding outline
00324         return it->second;
00325 
00326     // We did not find that level, so we have to create it
00327     PolygonOutline &newOutline = _polygonOutlineMap.insert(PolygonOutlineMap::value_type(level, PolygonOutline())).first->second;
00328 
00329     // Calculate the bezier curves for this level
00330     Outline::const_iterator oIt;
00331     for (oIt = _outline.begin(); oIt != _outline.end(); ++oIt)
00332     {
00333         UInt32 size = oIt->size();
00334         if (size > 0)
00335         {
00336             size -= 1;
00337             UInt32 index = 0;
00338             while (index < size)
00339                 evalBezierCurve(*oIt, index, level, newOutline.coords);
00340             newOutline.contours.push_back(newOutline.coords.size());
00341         }
00342     }
00343 
00344     // Calculate the faces
00345 
00346     // Create a new GLU tesselator object
00347     GLUtesselator *tess = gluNewTess();
00348     if (tess == 0)
00349         return newOutline;
00350 
00351     // hint to the GLU tesselator that all points lie in the xy-plane
00352     gluTessNormal(tess, 0.0, 0.0, 1.0);
00353     // set the winding rule
00354     gluTessProperty(tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);
00355 
00356     // register GLU Tesselator callback methods
00357     gluTessCallback(tess,
00358                     GLU_TESS_BEGIN_DATA,
00359                     reinterpret_cast<OSGGLUfuncptr>(gluTessBeginDataCB));
00360     gluTessCallback(tess,
00361                     GLU_TESS_END_DATA,
00362                     reinterpret_cast<OSGGLUfuncptr>(gluTessEndDataCB));
00363     gluTessCallback(tess,
00364                     GLU_TESS_COMBINE_DATA,
00365                     reinterpret_cast<OSGGLUfuncptr>(gluTessCombineDataCB));
00366     gluTessCallback(tess,
00367                     GLU_TESS_VERTEX_DATA,
00368                     reinterpret_cast<OSGGLUfuncptr>(gluTessVertexDataCB));
00369 
00370     // make shared data structure available to callbacks */
00371     gluTessBeginPolygon(tess, &newOutline);
00372 
00373     vector<UInt32>::const_iterator cIt;
00374     UInt32 coordIndex = 0;
00375     for (cIt = newOutline.contours.begin(); cIt != newOutline.contours.end(); ++cIt)
00376     {
00377         // begin new contour
00378         gluTessBeginContour(tess);
00379 
00380         while (coordIndex < *cIt)
00381         {
00382             GLdouble coords[3];
00383             assert(coordIndex < newOutline.coords.size());
00384             coords[0] = newOutline.coords[coordIndex].x();
00385             coords[1] = newOutline.coords[coordIndex].y();
00386             coords[2] = 0.f;
00387             gluTessVertex(tess, coords, reinterpret_cast<void*>(coordIndex++));
00388         }
00389 
00390         // end of contour
00391         gluTessEndContour(tess);
00392     }
00393 
00394     // trigger tesselator action
00395     gluTessEndPolygon(tess);
00396 
00397     // clean up
00398     gluDeleteTess(tess);
00399 
00400     return newOutline;
00401 }
00402 
00403 
00404 //----------------------------------------------------------------------
00405 // the next edge normal is computed as a pi/2 clockwise rotation of
00406 // the direction from this point to the next one. The edge normals
00407 // do thus point to the left of the path.
00408 // Author: afischle
00409 //----------------------------------------------------------------------
00410 static Vec2f computeEdgeNormal(const Vec2f &a, const Vec2f &b, bool cw)
00411 {
00412     Vec2f d = b - a;
00413     d.normalize();
00414     return cw == true ? Vec2f(d.y(), -d.x()) : Vec2f(-d.y(), d.x());
00415 }
00416 
00417 
00418 //----------------------------------------------------------------------
00419 // Returns a normal outline containining normal contours. These normal contours
00420 // contain GlyphVertexNormal structs providing the normals of the adjacent edges,
00421 // the mean normal and the angle enclosed by the edge normals.
00422 //
00423 // Author: afischle
00424 //----------------------------------------------------------------------
00425 const TextVectorGlyph::Normals &TextVectorGlyph::getNormals(UInt32 level) const
00426 {
00427     // Try to find the normal outline of the specified detail level in the
00428     // cache map
00429     NormalMap::const_iterator it = _normalMap.find(level);
00430     if (it != _normalMap.end())
00431         // We already have that level - return the corresponding outline
00432         return it->second;
00433 
00434     // We did not find that level, so we have to create it
00435     Normals &normals = _normalMap.insert(NormalMap::value_type(level, Normals())).first->second;
00436 
00437     // get the polygon outline of this glyph at the desired detail level
00438     // The contours of this outline are not closed!
00439     const PolygonOutline &outline = getLines(level);
00440 
00441     // compute the contour orientations when they are not available
00442     if (_contourOrientations.empty())
00443         computeContourOrientations();
00444 
00445     UInt32 start = 0, end, index = 0;
00446     vector<UInt32>::const_iterator iIt;
00447     vector<Orientation>::const_iterator oriIt = _contourOrientations.begin();
00448     for (iIt = outline.contours.begin(); iIt != outline.contours.end(); ++iIt, ++oriIt)
00449     {
00450         end = *iIt;
00451 
00452         assert(end - 1 < outline.coords.size());
00453         assert(start < outline.coords.size());
00454         assert(oriIt != _contourOrientations.end());
00455         Vec2f prevEdgeNormal = computeEdgeNormal(outline.coords[end - 1],
00456                                                  outline.coords[start],
00457                                                  (*oriIt) == CW);
00458         while (index < end)
00459         {
00460             UInt32 nextIndex = index + 1;
00461             if (nextIndex >= end)
00462                 nextIndex = start;
00463 
00464             assert(index < outline.coords.size());
00465             assert(nextIndex < outline.coords.size());
00466             Vec2f nextEdgeNormal = computeEdgeNormal(outline.coords[index], outline.coords[nextIndex], (*oriIt) == CW);
00467             Vec2f meanEdgeNormal = prevEdgeNormal + nextEdgeNormal;
00468             meanEdgeNormal.normalize();
00469             Real32 edgeAngle = osgacos(osgabs(prevEdgeNormal.dot(nextEdgeNormal)));
00470             normals.push_back(VertexNormal(nextEdgeNormal, meanEdgeNormal, edgeAngle));
00471 
00472             //the outgoing edge of this vertex is the incoming of the next vertex
00473             prevEdgeNormal = nextEdgeNormal;
00474 
00475             ++index;
00476         }
00477 
00478         start = end;
00479     }
00480 
00481     return normals;
00482 }
00483 
00484 
00485 //----------------------------------------------------------------------
00486 // Returns the orientations of the outlines
00487 // Author: pdaehne
00488 //----------------------------------------------------------------------
00489 const vector<TextVectorGlyph::Orientation> &TextVectorGlyph::getContourOrientations() const
00490 {
00491     // compute the contour orientations when they are not available
00492     if (_contourOrientations.empty())
00493         computeContourOrientations();
00494     return _contourOrientations;
00495 }
00496 
00497 
00498 //----------------------------------------------------------------------
00499 // returns true if the given goint lies in the left half plane of the
00500 // oriented line AB.
00501 // Author: afischle
00502 //----------------------------------------------------------------------
00503 static bool isLeft(const Vec2f &a, const Vec2f &b, const Vec2f &point)
00504 {
00505     // compute the normal pointing into the left half plane of the oriented
00506     // line
00507     Vec2f n = computeEdgeNormal(a, b, false);
00508     // the dot product is >0 when two vectors point into the same direction
00509     return n.dot(point - a) > 0.f;
00510 }
00511 
00512 
00513 //----------------------------------------------------------------------
00514 // returns the winding number of the given contour with respect to the point
00515 // by counting how often the infinite line f(x) = point.y was crossed by the
00516 // contour
00517 // Author: afischle
00518 //----------------------------------------------------------------------
00519 static Int32 calcWindingNumber(const vector<Vec2f> &coords, UInt32 start, UInt32 end, const Vec2f &point)
00520 {
00521     Int32 windingNumber = 0;
00522     assert(end - 1 < coords.size());
00523     const Vec2f *prevPoint = &(coords[end - 1]);
00524     UInt32 i;
00525     for (i = start; i < end; ++i)
00526     {
00527         assert(i < coords.size());
00528         const Vec2f *curPoint = &(coords[i]);
00529         if (prevPoint->y() <= point.y())
00530         {
00531             // upward crossing
00532             if (curPoint->y() > point.y())
00533             {
00534                 if (isLeft(*prevPoint, *curPoint, point) == true)
00535                     windingNumber++;
00536             }
00537         }
00538         else // prevPoint->y() > point.y()
00539         {
00540             // downward crossing
00541             if (curPoint->y() < point.y())
00542             {
00543                 if (isLeft(*prevPoint, *curPoint, point) == false)
00544                     windingNumber--;
00545             }
00546         }
00547         prevPoint = curPoint;
00548     }
00549 
00550     return windingNumber;
00551 }
00552 
00553 
00554 //----------------------------------------------------------------------
00555 // Checks if a point lies inside the glyph
00556 // Author: afischle
00557 //----------------------------------------------------------------------
00558 static bool isInteriorPoint(const Vec2f &point, const TextVectorGlyph::PolygonOutline &outline, GLenum windingRule)
00559 {
00560     Int32 totalWindingNumber = 0;
00561     UInt32 start = 0, end;
00562     vector<UInt32>::const_iterator it;
00563     for (it = outline.contours.begin(); it != outline.contours.end(); ++it)
00564     {
00565         end = *it;
00566         totalWindingNumber += calcWindingNumber(outline.coords, start, end, point);
00567         start = end;
00568     }
00569 
00570     switch(windingRule)
00571     {
00572         case GLU_TESS_WINDING_NONZERO:
00573             return totalWindingNumber != 0;
00574         case GLU_TESS_WINDING_ODD:
00575             return totalWindingNumber % 2;
00576         default:
00577             return false;
00578     }
00579 }
00580 
00581 
00582 //----------------------------------------------------------------------
00583 // Calculates the orientations of the contours
00584 // Author: afischle
00585 //----------------------------------------------------------------------
00586 void TextVectorGlyph::computeContourOrientations() const
00587 {
00588     // get the simplest outline available as it should suffice for the
00589     // orientation check
00590     const PolygonOutline &outline = getLines(0);
00591     UInt32 start = 0, end;
00592     vector<UInt32>::const_iterator it;
00593     for (it = outline.contours.begin(); it != outline.contours.end(); ++it)
00594     {
00595         end = *it;
00596 
00597         // return value does not matter
00598         if (end - start < 3)
00599             _contourOrientations.push_back(CCW);
00600 
00601         assert(start + 2 < outline.coords.size());
00602         Vec2f en1 = computeEdgeNormal(outline.coords[start], outline.coords[start + 1], false);
00603         Vec2f en2 = computeEdgeNormal(outline.coords[start + 1], outline.coords[start + 2], false);
00604         // compute the mean of the edge normals at vertex 0.
00605         Vec2f testNormal = en1 + en2;
00606         testNormal.normalize();
00607         // calculate the displacement of vertex 0 along its mean edge normal
00608         Vec2f testPoint = outline.coords[start + 1] + testNormal * (1000.f * Eps);
00609 
00610         if (isInteriorPoint(testPoint, outline, GLU_TESS_WINDING_NONZERO))
00611             _contourOrientations.push_back(CW);
00612         else
00613             _contourOrientations.push_back(CCW);
00614 
00615         start = end;
00616     }
00617 }
00618 
00619 
00620 OSG_END_NAMESPACE
00621 
00622 
00623 /*------------------------------------------------------------------------*/
00624 /*                              cvs id's                                  */
00625 
00626 #ifdef OSG_SGI_CC
00627 #pragma set woff 1174
00628 #endif
00629 
00630 #ifdef OSG_LINUX_ICC
00631 #pragma warning( disable : 177 )
00632 #endif
00633 
00634 namespace
00635 {
00636     static OSG::Char8 cvsid_cpp[] = "@(#)$Id: OSGTextVectorGlyph.cpp,v 1.9 2005/04/25 11:45:24 jbehr Exp $";
00637     static OSG::Char8 cvsid_hpp[] = OSGTEXTVECTORGLYPH_HEADER_CVSID;
00638     static OSG::Char8 cvsid_inl[] = OSGTEXTVECTORGLYPH_INLINE_CVSID;
00639 }
00640 
00641 #ifdef __sgi
00642 #pragma reset woff 1174
00643 #endif

Generated on Thu Aug 25 04:11:38 2005 for OpenSG by  doxygen 1.4.3