Logo
  • Main Page
  • Related Pages
  • Modules
  • Classes
  • Files

mmsfttesselator.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2005-2007 Stefan Schwarzer, Jens Schneider,             *
00003  *                           Matthias Hardt, Guido Madaus                  *
00004  *                                                                         *
00005  *   Copyright (C) 2007-2008 BerLinux Solutions GbR                        *
00006  *                           Stefan Schwarzer & Guido Madaus               *
00007  *                                                                         *
00008  *   Copyright (C) 2009-2011 BerLinux Solutions GmbH                       *
00009  *                                                                         *
00010  *   Authors:                                                              *
00011  *      Stefan Schwarzer   <stefan.schwarzer@diskohq.org>,                 *
00012  *      Matthias Hardt     <matthias.hardt@diskohq.org>,                   *
00013  *      Jens Schneider     <jens.schneider@diskohq.org>,                   *
00014  *      Guido Madaus       <guido.madaus@diskohq.org>,                     *
00015  *      Patrick Helterhoff <patrick.helterhoff@diskohq.org>,               *
00016  *      René Bählkow       <rene.baehlkow@diskohq.org>                     *
00017  *                                                                         *
00018  *   This library is free software; you can redistribute it and/or         *
00019  *   modify it under the terms of the GNU Lesser General Public            *
00020  *   License version 2.1 as published by the Free Software Foundation.     *
00021  *                                                                         *
00022  *   This library is distributed in the hope that it will be useful,       *
00023  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00024  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00025  *   Lesser General Public License for more details.                       *
00026  *                                                                         *
00027  *   You should have received a copy of the GNU Lesser General Public      *
00028  *   License along with this library; if not, write to the                 *
00029  *   Free Software Foundation, Inc.,                                       *
00030  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
00031  **************************************************************************/
00032 
00033 #include "mmsgui/ft/mmsfttesselator.h"
00034 
00035 #include <stdlib.h>
00036 #include <stdio.h>
00037 #include <assert.h>
00038 
00039 #ifdef __HAVE_GLU__
00040 #include <GL/glu.h>
00041 
00042 // GLU_TESS_BEGIN_DATA callback
00043 void gluTBeginData(GLenum type, MMSFTGlyph *glyph) {
00044     glyph->tessBegin(type);
00045 }
00046 
00047 // GLU_TESS_VERTEX_DATA callback
00048 void gluTVertexData(void *data, MMSFTGlyph *glyph) {
00049     double* vertex = static_cast<double*>(data);
00050     glyph->tessVertex(vertex[0], vertex[1], vertex[2]);
00051 }
00052 
00053 // GLU_TESS_COMBINE_DATA callback
00054 void gluTCombineData(double coords[3], void *vertex_data[4], GLfloat weight[4], void **outData, MMSFTGlyph *glyph) {
00055     const double *vertex = static_cast<const double*>(coords);
00056     *outData = const_cast<double*>(glyph->tessCombine(vertex[0], vertex[1], vertex[2]));
00057 }
00058 
00059 // GLU_TESS_END_DATA callback
00060 void gluTEndData(MMSFTGlyph *glyph) {
00061     glyph->tessEnd();
00062 }
00063 
00064 // GLU_TESS_ERROR_DATA callback
00065 void gluTErrorData(GLenum errCode, MMSFTGlyph *glyph) {
00066     glyph->tessError(errCode);
00067 }
00068 #endif
00069 
00070 
00071 MMSFTTesselator::MMSFTTesselator(const FT_GlyphSlot glyph) {
00072     this->glyph = NULL;
00073     this->contourList = NULL;
00074     this->contourCount = 0;
00075 
00076     if (!glyph) return;
00077 
00078     this->outline = glyph->outline;
00079 
00080     this->contourCount= outline.n_contours;
00081     this->contourList = NULL;
00082     this->contourFlag = outline.flags;
00083 
00084     processContours();
00085 }
00086 
00087 
00088 MMSFTTesselator::~MMSFTTesselator() {
00089     for (unsigned int c = 0; c < this->contourCount; c++) {
00090         delete this->contourList[c];
00091     }
00092     delete [] this->contourList;
00093     delete this->glyph;
00094 }
00095 
00096 
00097 void MMSFTTesselator::processContours() {
00098     int contourLength = 0;
00099     int startIndex = 0;
00100     int endIndex = 0;
00101 
00102     this->contourList = new MMSFTContour*[this->contourCount];
00103 
00104     for (unsigned int i = 0; i < this->contourCount; i++) {
00105         FT_Vector* pointList = &outline.points[startIndex];
00106         char* tagList = &outline.tags[startIndex];
00107 
00108         endIndex = outline.contours[i];
00109         contourLength =  (endIndex - startIndex) + 1;
00110 
00111         MMSFTContour* contour = new MMSFTContour(pointList, tagList, contourLength);
00112 
00113         contourList[i] = contour;
00114 
00115         startIndex = endIndex + 1;
00116     }
00117 
00118     // Compute each contour's parity.
00119     // FIXME: see if FT_Outline_Get_Orientation can do it for us.
00120     for (unsigned int i = 0; i < this->contourCount; i++) {
00121         MMSFTContour *c1 = this->contourList[i];
00122 
00123         // 1. Find the leftmost point.
00124         MMSFTVertex leftmost(65536.0, 0.0);
00125 
00126         for (unsigned int n = 0; n < c1->getVertexCount(); n++) {
00127             MMSFTVertex p = c1->Vertex(n);
00128             if(p.X() < leftmost.X())
00129             {
00130                 leftmost = p;
00131             }
00132         }
00133 
00134         // 2. Count how many other contours we cross when going further to
00135         // the left.
00136         int parity = 0;
00137 
00138         for (unsigned int j = 0; j < this->contourCount; j++) {
00139             if (j == i) continue;
00140 
00141             MMSFTContour *c2 = this->contourList[j];
00142 
00143             for (unsigned int n = 0; n < c2->getVertexCount(); n++) {
00144                 MMSFTVertex p1 = c2->Vertex(n);
00145                 MMSFTVertex p2 = c2->Vertex((n + 1) % c2->getVertexCount());
00146 
00147                 /* FIXME: combinations of >= > <= and < do not seem stable */
00148                 if((p1.Y() < leftmost.Y() && p2.Y() < leftmost.Y())
00149                     || (p1.Y() >= leftmost.Y() && p2.Y() >= leftmost.Y())
00150                     || (p1.X() > leftmost.X() && p2.X() > leftmost.X()))
00151                 {
00152                     continue;
00153                 }
00154                 else if(p1.X() < leftmost.X() && p2.X() < leftmost.X())
00155                 {
00156                     parity++;
00157                 }
00158                 else
00159                 {
00160                     MMSFTVertex a = p1 - leftmost;
00161                     MMSFTVertex b = p2 - leftmost;
00162                     if(b.X() * a.Y() > b.Y() * a.X())
00163                     {
00164                         parity++;
00165                     }
00166                 }
00167             }
00168         }
00169 
00170         // 3. Make sure the glyph has the proper parity.
00171         c1->setParity(parity);
00172     }
00173 }
00174 
00175 
00176 bool MMSFTTesselator::generateGlyph(double zNormal, int outsetType, float outsetSize) {
00177 #ifdef __HAVE_GLU__
00178     // new glyph
00179     if (this->glyph) delete this->glyph;
00180     this->glyph = new MMSFTGlyph();
00181 
00182     GLUtesselator* tobj = gluNewTess();
00183 
00184     gluTessCallback(tobj, GLU_TESS_BEGIN_DATA,     (_GLUfuncptr)gluTBeginData);
00185     gluTessCallback(tobj, GLU_TESS_VERTEX_DATA,    (_GLUfuncptr)gluTVertexData);
00186     gluTessCallback(tobj, GLU_TESS_COMBINE_DATA,   (_GLUfuncptr)gluTCombineData);
00187     gluTessCallback(tobj, GLU_TESS_END_DATA,       (_GLUfuncptr)gluTEndData);
00188     gluTessCallback(tobj, GLU_TESS_ERROR_DATA,     (_GLUfuncptr)gluTErrorData);
00189 
00190     if(contourFlag & ft_outline_even_odd_fill) // ft_outline_reverse_fill
00191     {
00192         gluTessProperty(tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);
00193     }
00194     else
00195     {
00196         gluTessProperty(tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO);
00197     }
00198 
00199     gluTessProperty(tobj, GLU_TESS_TOLERANCE, 0);
00200     gluTessNormal(tobj, 0.0f, 0.0f, zNormal);
00201     gluTessBeginPolygon(tobj, this->glyph);
00202 
00203     for (unsigned int c = 0; c < this->contourCount; c++) {
00204         switch(outsetType) {
00205             case 1:
00206                 contourList[c]->buildFrontOutset(outsetSize);
00207                 break;
00208             case 2:contourList[c]->buildBackOutset(outsetSize);
00209                 break;
00210         }
00211         const MMSFTContour* contour = contourList[c];
00212 
00213         gluTessBeginContour(tobj);
00214 
00215         for (unsigned int p = 0; p < contour->getVertexCount(); p++) {
00216             const double* d;
00217             switch(outsetType) {
00218                 case 1:
00219                     d = contour->FrontVertex(p);
00220                     break;
00221                 case 2:
00222                     d = contour->BackVertex(p);
00223                     break;
00224                 case 0:
00225                 default:
00226                     d = contour->Vertex(p);
00227                     break;
00228             }
00229 
00230             gluTessVertex(tobj, (GLdouble *)d, (GLvoid *)d);
00231         }
00232 
00233         gluTessEndContour(tobj);
00234     }
00235 
00236     gluTessEndPolygon(tobj);
00237     gluDeleteTess(tobj);
00238 
00239     if (this->glyph->getErrorCode()) {
00240         // failed
00241         delete this->glyph;
00242         this->glyph = NULL;
00243         return false;
00244     }
00245 
00246     return true;
00247 #else
00248     return false;
00249 #endif
00250 }
00251 
00252 const MMSFTGlyph* const MMSFTTesselator::getGlyph() const {
00253     return this->glyph;
00254 }
00255 
00256 unsigned int MMSFTTesselator::getContourCount() {
00257     return this->contourCount;
00258 }
00259 
00260 MMSFTContour *MMSFTTesselator::getContour(unsigned int index) {
00261     if (!this->contourList) return NULL;
00262     if (index >= this->contourCount) return NULL;
00263     return this->contourList[index];
00264 }

Generated by doxygen