00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
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
00043 void gluTBeginData(GLenum type, MMSFTGlyph *glyph) {
00044 glyph->tessBegin(type);
00045 }
00046
00047
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
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
00060 void gluTEndData(MMSFTGlyph *glyph) {
00061 glyph->tessEnd();
00062 }
00063
00064
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
00119
00120 for (unsigned int i = 0; i < this->contourCount; i++) {
00121 MMSFTContour *c1 = this->contourList[i];
00122
00123
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
00135
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
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
00171 c1->setParity(parity);
00172 }
00173 }
00174
00175
00176 bool MMSFTTesselator::generateGlyph(double zNormal, int outsetType, float outsetSize) {
00177 #ifdef __HAVE_GLU__
00178
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)
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
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 }