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

mmsftcontour.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/mmsftcontour.h"
00034 #include <math.h>
00035 
00036 static const unsigned int BEZIER_STEPS = 5;
00037 
00038 MMSFTContour::MMSFTContour(FT_Vector *outlineVertexList, char *outlineVertexTags, unsigned int outlineNumVertices) {
00039 
00040     MMSFTVertex prev, cur(outlineVertexList[(outlineNumVertices - 1) % outlineNumVertices]), next(outlineVertexList[0]);
00041     MMSFTVertex a;
00042     double olddir, dir = atan2((next - cur).Y(), (next - cur).X());
00043     double angle = 0.0;
00044 
00045     // See http://freetype.sourceforge.net/freetype2/docs/glyphs/glyphs-6.html
00046     // for a full description of FreeType tags.
00047     for(unsigned int i = 0; i < outlineNumVertices; i++) {
00048         prev = cur;
00049         cur = next;
00050         next = MMSFTVertex(outlineVertexList[(i + 1) % outlineNumVertices]);
00051         olddir = dir;
00052         dir = atan2((next - cur).Y(), (next - cur).X());
00053 
00054         // Compute our path's new direction.
00055         double t = dir - olddir;
00056         if(t < -M_PI) t += 2 * M_PI;
00057         if(t > M_PI) t -= 2 * M_PI;
00058         angle += t;
00059 
00060         // Only process point tags we know.
00061         if (outlineNumVertices < 2 || FT_CURVE_TAG(outlineVertexTags[i]) == FT_Curve_Tag_On) {
00062             AddVertex(cur);
00063         }
00064         else
00065         if (FT_CURVE_TAG(outlineVertexTags[i]) == FT_Curve_Tag_Conic) {
00066             MMSFTVertex prev2 = prev, next2 = next;
00067 //printf("FT_Curve_Tag_Conic\n");
00068             // Previous point is either the real previous point (an "on"
00069             // point), or the midpoint between the current one and the
00070             // previous "conic off" point.
00071             if (FT_CURVE_TAG(outlineVertexTags[(i - 1 + outlineNumVertices) % outlineNumVertices]) == FT_Curve_Tag_Conic) {
00072                 prev2 = (cur + prev) * 0.5;
00073                 AddVertex(prev2);
00074             }
00075 
00076             // Next point is either the real next point or the midpoint.
00077             if(FT_CURVE_TAG(outlineVertexTags[(i + 1) % outlineNumVertices]) == FT_Curve_Tag_Conic) {
00078                 next2 = (cur + next) * 0.5;
00079             }
00080 
00081             evaluateQuadraticCurve(prev2, cur, next2);
00082         }
00083         else
00084         if (FT_CURVE_TAG(outlineVertexTags[i]) == FT_Curve_Tag_Cubic
00085           &&FT_CURVE_TAG(outlineVertexTags[(i + 1) % outlineNumVertices]) == FT_Curve_Tag_Cubic) {
00086 //printf("FT_Curve_Tag_Cubic\n");
00087             evaluateCubicCurve(prev, cur, next, MMSFTVertex(outlineVertexList[(i + 2) % outlineNumVertices]));
00088         }
00089     }
00090 
00091     // If final angle is positive (+2PI), it's an anti-clockwise contour,
00092     // otherwise (-2PI) it's clockwise.
00093     clockwise = (angle < 0.0);
00094 }
00095 
00096 
00097 MMSFTContour::~MMSFTContour() {
00098     this->vertexList.clear();
00099     this->outsetVertexList.clear();
00100     this->frontVertexList.clear();
00101     this->backVertexList.clear();
00102 }
00103 
00104 
00105 void MMSFTContour::AddVertex(MMSFTVertex vertex) {
00106     if(vertexList.empty() || (vertex != vertexList[vertexList.size() - 1] && vertex != vertexList[0])) {
00107         vertexList.push_back(vertex);
00108     }
00109 }
00110 
00111 
00112 void MMSFTContour::AddOutsetVertex(MMSFTVertex vertex) {
00113     outsetVertexList.push_back(vertex);
00114 }
00115 
00116 
00117 void MMSFTContour::AddFrontVertex(MMSFTVertex vertex) {
00118     frontVertexList.push_back(vertex);
00119 }
00120 
00121 
00122 void MMSFTContour::AddBackVertex(MMSFTVertex vertex) {
00123     backVertexList.push_back(vertex);
00124 }
00125 
00126 
00127 void MMSFTContour::evaluateQuadraticCurve(MMSFTVertex A, MMSFTVertex B, MMSFTVertex C) {
00128     for(unsigned int i = 1; i < BEZIER_STEPS; i++)
00129     {
00130         double t = static_cast<double>(i) / BEZIER_STEPS;
00131 
00132         MMSFTVertex U = (1.0f - t) * A + t * B;
00133         MMSFTVertex V = (1.0f - t) * B + t * C;
00134 
00135         AddVertex((1.0f - t) * U + t * V);
00136     }
00137 }
00138 
00139 
00140 void MMSFTContour::evaluateCubicCurve(MMSFTVertex A, MMSFTVertex B, MMSFTVertex C, MMSFTVertex D) {
00141     for(unsigned int i = 0; i < BEZIER_STEPS; i++)
00142     {
00143         double t = static_cast<double>(i) / BEZIER_STEPS;
00144 
00145         MMSFTVertex U = (1.0f - t) * A + t * B;
00146         MMSFTVertex V = (1.0f - t) * B + t * C;
00147         MMSFTVertex W = (1.0f - t) * C + t * D;
00148 
00149         MMSFTVertex M = (1.0f - t) * U + t * V;
00150         MMSFTVertex N = (1.0f - t) * V + t * W;
00151 
00152         AddVertex((1.0f - t) * M + t * N);
00153     }
00154 }
00155 
00156 
00157 // This function is a bit tricky. Given a path ABC, it returns the
00158 // coordinates of the outset point facing B on the left at a distance
00159 // of 64.0.
00160 //                                         M
00161 //                            - - - - - - X
00162 //                             ^         / '
00163 //                             | 64.0   /   '
00164 //  X---->-----X     ==>    X--v-------X     '
00165 // A          B \          A          B \   .>'
00166 //               \                       <'  64.0
00167 //                \                       \                  .
00168 //                 \                       \                 .
00169 //                C X                     C X
00170 //
00171 MMSFTVertex MMSFTContour::ComputeOutsetVertex(MMSFTVertex A, MMSFTVertex B, MMSFTVertex C) {
00172     /* Build the rotation matrix from 'ba' vector */
00173     MMSFTVertex ba = (A - B).Normalise();
00174     MMSFTVertex bc = C - B;
00175 
00176     /* Rotate bc to the left */
00177     MMSFTVertex tmp(bc.X() * -ba.X() + bc.Y() * -ba.Y(),
00178                 bc.X() * ba.Y() + bc.Y() * -ba.X());
00179 
00180     /* Compute the vector bisecting 'abc' */
00181     double norm = sqrt(tmp.X() * tmp.X() + tmp.Y() * tmp.Y());
00182     double dist = 64.0 * sqrt((norm - tmp.X()) / (norm + tmp.X()));
00183     tmp.X(tmp.Y() < 0.0 ? dist : -dist);
00184     tmp.Y(64.0);
00185 
00186     /* Rotate the new bc to the right */
00187     return MMSFTVertex(tmp.X() * -ba.X() + tmp.Y() * ba.Y(),
00188                    tmp.X() * -ba.Y() + tmp.Y() * -ba.X());
00189 }
00190 
00191 
00192 void MMSFTContour::setParity(int parity) {
00193     unsigned int size = getVertexCount();
00194     MMSFTVertex vOutset;
00195 
00196     if(((parity & 1) && clockwise) || (!(parity & 1) && !clockwise)) {
00197         // Contour orientation is wrong! We must reverse all points.
00198         // FIXME: could it be worth writing FTVector::reverse() for this?
00199         for(unsigned int i = 0; i < size / 2; i++) {
00200             MMSFTVertex tmp = vertexList[i];
00201             vertexList[i] = vertexList[size - 1 - i];
00202             vertexList[size - 1 -i] = tmp;
00203         }
00204 
00205         clockwise = !clockwise;
00206     }
00207 
00208     for(unsigned int i = 0; i < size; i++) {
00209         unsigned int prev, cur, next;
00210 
00211         prev = (i + size - 1) % size;
00212         cur = i;
00213         next = (i + size + 1) % size;
00214 
00215         vOutset = ComputeOutsetVertex(Vertex(prev), Vertex(cur), Vertex(next));
00216         AddOutsetVertex(vOutset);
00217     }
00218 }
00219 
00220 
00221 void MMSFTContour::buildFrontOutset(double outset) {
00222     for (unsigned int i = 0; i < getVertexCount(); i++) {
00223         AddFrontVertex(Vertex(i) + Outset(i) * outset);
00224     }
00225 }
00226 
00227 
00228 void MMSFTContour::buildBackOutset(double outset) {
00229     for (unsigned int i = 0; i < getVertexCount(); i++) {
00230         AddBackVertex(Vertex(i) + Outset(i) * outset);
00231     }
00232 }
00233 

Generated by doxygen