]> Shamusworld >> Repos - ttedit/blobdiff - src/glyphpoints.cpp
Added rectangle point selection, canvas zooming.
[ttedit] / src / glyphpoints.cpp
index d0402f6fe041ddc800a29b03db00a24c53d9439f..4ae01e5d5d8630c0d9dcec1cfd0d6cb0689db0f4 100755 (executable)
@@ -10,7 +10,7 @@
 // JLH = James L. Hammons <jlhamm@acm.org>
 //
 // Who  When        What
-// ---  ----------  ------------------------------------------------------------
+// ---  ----------  -----------------------------------------------------------
 // JLH  ??/??/200?  Created this file
 // JLH  05/18/2004  Added pure point adding, inserting, better polygon handling
 //
@@ -22,6 +22,8 @@
 #ifdef DEBUG
 #include "debug.h"
 #endif
+#include <math.h>
+
 
 /*GlyphPoints::GlyphPoints(void)
 {
 }*/
 
 GlyphPoints::GlyphPoints(int nPts/*=0*/, int nPlys/*=0*/, int * xa/*=null*/, int * ya/*=null*/,
-       bool * oca/*=null*/, uint16 * pa/*=null*/): x(NULL), y(NULL), onCurve(NULL), polyEnd(NULL)
+       bool * oca/*=null*/, uint16_t * pa/*=null*/): x(NULL), y(NULL), onCurve(NULL), polyEnd(NULL)
 //GlyphPoints::GlyphPoints(int nPts, int nPlys/*=0*/, int * xa/*=null*/, int * ya/*=null*/,
-//     bool * oca/*=null*/, uint16 * pa/*=null*/): x(NULL), y(NULL), onCurve(NULL), polyEnd(NULL)
+//     bool * oca/*=null*/, uint16_t * pa/*=null*/): x(NULL), y(NULL), onCurve(NULL), polyEnd(NULL)
 {
        AllocateAndCopy(nPts, nPlys, xa, ya, oca, pa);
 
        if (nPlys == 0)
        {
                numPolys = 1;
-               polyEnd = new uint16[numPolys];
+               polyEnd = new uint16_t[numPolys];
                polyEnd[0] = numPoints - 1;
        }
 #ifdef DEBUG
@@ -46,6 +48,7 @@ WriteLogMsg("GlyphPoints: Default constructor. %u points, %u polys.\n", numPoint
 #endif
 }
 
+
 GlyphPoints::GlyphPoints(int xx, int yy, bool oc)
 {
 //Hmm. What to do with this...?
@@ -55,6 +58,7 @@ WriteLogMsg("GlyphPoints: Single point constructor. %u points, %u polys.\n", num
 #endif
 }
 
+
 // Copy constructor (needed for deep copying)
 
 //GlyphPoints::GlyphPoints(GlyphPoints &c): x(NULL), y(NULL), onCurve(NULL), polyEnd(NULL)
@@ -66,8 +70,11 @@ WriteLogMsg("GlyphPoints: Copy constructor. %u points, %u polys.\n", numPoints,
 #endif
 }
 
+
 GlyphPoints::~GlyphPoints()
 {
+       FreeAllocatedMemory();
+#if 0
        if (x)
                delete[] x;
 
@@ -79,9 +86,11 @@ GlyphPoints::~GlyphPoints()
 
        if (polyEnd)
                delete[] polyEnd;
+#endif
 }
 
-void GlyphPoints::AllocateAndCopy(int nPts, int nPlys, int * xa, int * ya, bool * oca, uint16 * pa)
+
+void GlyphPoints::AllocateAndCopy(int nPts, int nPlys, int * xa, int * ya, bool * oca, uint16_t * pa)
 {
        numPoints = nPts, numPolys = nPlys;
 
@@ -106,7 +115,7 @@ void GlyphPoints::AllocateAndCopy(int nPts, int nPlys, int * xa, int * ya, bool
 
        if (numPolys)
        {
-               polyEnd = new uint16[numPolys];
+               polyEnd = new uint16_t[numPolys];
 
                if (pa)                                                                 // Copy poly ends in if they're passed in...
                        for(int i=0; i<nPlys; i++)
@@ -114,11 +123,9 @@ void GlyphPoints::AllocateAndCopy(int nPts, int nPlys, int * xa, int * ya, bool
        }
 }
 
-GlyphPoints& GlyphPoints::operator=(const GlyphPoints &c)
-{
-       if (this == &c)
-               return *this;                                                   // Take care of self-assignment
 
+void GlyphPoints::FreeAllocatedMemory(void)
+{
        if (x)
                delete[] x;
 
@@ -130,12 +137,21 @@ GlyphPoints& GlyphPoints::operator=(const GlyphPoints &c)
 
        if (polyEnd)
                delete[] polyEnd;
+}
+
+
+GlyphPoints& GlyphPoints::operator=(const GlyphPoints &c)
+{
+       if (this == &c)
+               return *this;                                                   // Take care of self-assignment
 
+       FreeAllocatedMemory();
        AllocateAndCopy(c.numPoints, c.numPolys, c.x, c.y, c.onCurve, c.polyEnd);
 
        return *this;
 }
 
+
 // Add another GlyphPoints' points to this one...
 
 GlyphPoints GlyphPoints::operator+(const GlyphPoints &c)
@@ -145,7 +161,7 @@ GlyphPoints GlyphPoints::operator+(const GlyphPoints &c)
        int * totX = new int[totPoints];
        int * totY = new int[totPoints];
        bool * totOnCurve = new bool[totPoints];
-       uint16 * totPolyEnd = new uint16[totPolys];
+       uint16_t * totPolyEnd = new uint16_t[totPolys];
 
        for(int i=0; i<numPoints; i++)
        {
@@ -177,6 +193,7 @@ GlyphPoints GlyphPoints::operator+(const GlyphPoints &c)
        return retVal;
 }
 
+
 // Add a point to this GlyphPoints...
 
 GlyphPoints GlyphPoints::operator+(const IPoint &c)
@@ -185,7 +202,7 @@ GlyphPoints GlyphPoints::operator+(const IPoint &c)
        int * totX = new int[numPoints + 1];
        int * totY = new int[numPoints + 1];
        bool * totOnCurve = new bool[numPoints + 1];
-       uint16 * totPolyEnd = new uint16[numPolys];
+       uint16_t * totPolyEnd = new uint16_t[numPolys];
 
        for(int i=0; i<numPoints; i++)
                totX[i] = x[i], totY[i] = y[i], totOnCurve[i] = onCurve[i];
@@ -205,6 +222,7 @@ GlyphPoints GlyphPoints::operator+(const IPoint &c)
        return retVal;
 }
 
+
 GlyphPoints& GlyphPoints::operator+=(const IPoint &p)
 {
        InsertPoint(numPoints, p.x, p.y, p.onCurve);
@@ -212,8 +230,24 @@ GlyphPoints& GlyphPoints::operator+=(const IPoint &p)
        return *this;
 }
 
-void GlyphPoints::InsertPoint(uint16 pt, int xx, int yy, bool oc)
+
+void GlyphPoints::Clear(void)
 {
+       FreeAllocatedMemory();
+       x = y = NULL;
+       onCurve = NULL;
+       polyEnd = NULL;
+       numPoints = numPolys = pointsAllocated = polysAllocated = 0;
+
+       numPolys = 1;
+       polyEnd = new uint16_t[numPolys];
+       polyEnd[0] = numPoints - 1;
+}
+
+
+void GlyphPoints::InsertPoint(uint16_t pt, int xx, int yy, bool oc)
+{
+//wouldn't it be better to treat this case as inserting at the end?
        if (pt > numPoints)                                                     // > because we can insert at end...!
                throw GP_OUT_OF_RANGE;
 
@@ -230,11 +264,10 @@ void GlyphPoints::InsertPoint(uint16 pt, int xx, int yy, bool oc)
 
        totX[pt] = xx, totY[pt] = yy, totOnCurve[pt] = oc;
 
-//A way to fix the kludge in GetPoly() would be to put a check here to see if 
+//A way to fix the kludge in GetPoly() would be to put a check here to see if
 //we're adding to the end of the structure: [DONE, below]
        int polyInsert = (pt == numPoints ? numPolys - 1 : GetPoly(pt));
        for(int i=polyInsert; i<numPolys; i++)
-//     for(int i=GetPoly(pt); i<numPolys; i++)
                polyEnd[i]++;                                                   // Bump polygons' end point
 
        numPoints++;
@@ -246,21 +279,23 @@ void GlyphPoints::InsertPoint(uint16 pt, int xx, int yy, bool oc)
        x = totX, y = totY, onCurve = totOnCurve;
 }
 
-void GlyphPoints::InsertPoint(uint16 pt, const IPoint &p)
+
+void GlyphPoints::InsertPoint(uint16_t pt, const IPoint &p)
 {
        InsertPoint(pt, p.x, p.y, p.onCurve);
 }
 
+
 //
 // Delete a point from the glyph
 // Note that we don't bother to reallocate anything here, just bump the
 // size counters down as needed. In the future, we'll keep track so we
 // don't have to reallocate *every* damn time a point is added...
 //
-void GlyphPoints::DeletePoint(uint16 pt)
+void GlyphPoints::DeletePoint(uint16_t pt)
 {
        // Adjust polygon ends appropriately
-       uint16 poly = GetPoly(pt);
+       uint16_t poly = GetPoly(pt);
 
        for(int i=poly; i<numPolys; i++)
                polyEnd[i]--;
@@ -283,17 +318,19 @@ void GlyphPoints::DeletePoint(uint16 pt)
                x[i] = x[i + 1], y[i] = y[i + 1], onCurve[i] = onCurve[i + 1];
 }
 
-uint16 GlyphPoints::GetNumPoints(void)
+
+uint16_t GlyphPoints::GetNumPoints(void)
 {
        return numPoints;
 }
 
-uint16 GlyphPoints::GetNumPoints(uint16 poly)
+
+uint16_t GlyphPoints::GetNumPoints(uint16_t poly)
 {
        if (poly >= numPolys)
 #ifdef DEBUG
 {
-WriteLogMsg("Exception: GetNumPoints(uint16). poly=%u, numPolys=%u\xD\xA", poly, numPolys);
+WriteLogMsg("Exception: GetNumPoints(uint16_t). poly=%u, numPolys=%u\xD\xA", poly, numPolys);
 #endif
                throw GP_OUT_OF_RANGE;
 #ifdef DEBUG
@@ -303,17 +340,19 @@ WriteLogMsg("Exception: GetNumPoints(uint16). poly=%u, numPolys=%u\xD\xA", poly,
        return polyEnd[poly] - (poly == 0 ? -1 : polyEnd[poly - 1]);
 }
 
-uint16 GlyphPoints::GetNumPolys(void)
+
+uint16_t GlyphPoints::GetNumPolys(void)
 {
        return numPolys;
 }
 
-int GlyphPoints::GetX(uint16 pt)
+
+int GlyphPoints::GetX(uint16_t pt)
 {
        if (pt >= numPoints)
 #ifdef DEBUG
 {
-WriteLogMsg("Exception: GetX(uint16). pt=%u, numPoints=%u\xD\xA", pt, numPoints);
+WriteLogMsg("Exception: GetX(uint16_t). pt=%u, numPoints=%u\xD\xA", pt, numPoints);
 #endif
                throw GP_OUT_OF_RANGE;
 #ifdef DEBUG
@@ -323,12 +362,13 @@ WriteLogMsg("Exception: GetX(uint16). pt=%u, numPoints=%u\xD\xA", pt, numPoints)
        return x[pt];
 }
 
-int GlyphPoints::GetY(uint16 pt)
+
+int GlyphPoints::GetY(uint16_t pt)
 {
        if (pt >= numPoints)
 #ifdef DEBUG
 {
-WriteLogMsg("Exception: GetY(uint16). pt=%u, numPoints=%u\xD\xA", pt, numPoints);
+WriteLogMsg("Exception: GetY(uint16_t). pt=%u, numPoints=%u\xD\xA", pt, numPoints);
 #endif
                throw GP_OUT_OF_RANGE;
 #ifdef DEBUG
@@ -338,12 +378,29 @@ WriteLogMsg("Exception: GetY(uint16). pt=%u, numPoints=%u\xD\xA", pt, numPoints)
        return y[pt];
 }
 
-bool GlyphPoints::GetOnCurve(uint16 pt)
+
+Vector GlyphPoints::GetXY(uint16_t pt)
 {
        if (pt >= numPoints)
 #ifdef DEBUG
 {
-WriteLogMsg("Exception: GetOnCurve(uint16). pt=%u, numPoints=%u\xD\xA", pt, numPoints);
+WriteLogMsg("Exception: GetXY(uint16_t). pt=%u, numPoints=%u\xD\xA", pt, numPoints);
+#endif
+               throw GP_OUT_OF_RANGE;
+#ifdef DEBUG
+}
+#endif
+
+       return Vector(x[pt], y[pt]);
+}
+
+
+bool GlyphPoints::GetOnCurve(uint16_t pt)
+{
+       if (pt >= numPoints)
+#ifdef DEBUG
+{
+WriteLogMsg("Exception: GetOnCurve(uint16_t). pt=%u, numPoints=%u\xD\xA", pt, numPoints);
 #endif
                throw GP_OUT_OF_RANGE;
 #ifdef DEBUG
@@ -353,12 +410,13 @@ WriteLogMsg("Exception: GetOnCurve(uint16). pt=%u, numPoints=%u\xD\xA", pt, numP
        return onCurve[pt];
 }
 
-int GlyphPoints::GetX(uint16 poly, uint16 pt)
+
+int GlyphPoints::GetX(uint16_t poly, uint16_t pt)
 {
        if (pt >= GetNumPoints(poly))
 #ifdef DEBUG
 {
-WriteLogMsg("Exception: GetX(uint16, uint16). poly= %u, pt=%u, numPoints=%u\xD\xA", poly, pt, numPoints);
+WriteLogMsg("Exception: GetX(uint16_t, uint16_t). poly= %u, pt=%u, numPoints=%u\xD\xA", poly, pt, numPoints);
 #endif
                throw GP_OUT_OF_RANGE;
 #ifdef DEBUG
@@ -368,12 +426,19 @@ WriteLogMsg("Exception: GetX(uint16, uint16). poly= %u, pt=%u, numPoints=%u\xD\x
        return x[pt + (poly == 0 ? 0 : polyEnd[poly - 1] + 1)];
 }
 
-int GlyphPoints::GetY(uint16 poly, uint16 pt)
+
+int GlyphPoints::GetNextX(uint16_t poly, uint16_t pt)
+{
+       return GetX(poly, GetNext(poly, pt));
+}
+
+
+int GlyphPoints::GetY(uint16_t poly, uint16_t pt)
 {
        if (pt >= GetNumPoints(poly))
 #ifdef DEBUG
 {
-WriteLogMsg("Exception: GetY(uint16, uint16). poly= %u, pt=%u, numPoints=%u\xD\xA", poly, pt, numPoints);
+WriteLogMsg("Exception: GetY(uint16_t, uint16_t). poly= %u, pt=%u, numPoints=%u\xD\xA", poly, pt, numPoints);
 #endif
                throw GP_OUT_OF_RANGE;
 #ifdef DEBUG
@@ -383,12 +448,34 @@ WriteLogMsg("Exception: GetY(uint16, uint16). poly= %u, pt=%u, numPoints=%u\xD\x
        return y[pt + (poly == 0 ? 0 : polyEnd[poly - 1] + 1)];
 }
 
-bool GlyphPoints::GetOnCurve(uint16 poly, uint16 pt)
+
+int GlyphPoints::GetNextY(uint16_t poly, uint16_t pt)
+{
+       return GetY(poly, GetNext(poly, pt));
+}
+
+
+IPoint GlyphPoints::GetPoint(uint16_t poly, uint16_t pt)
+{
+       return IPoint(GetX(poly, pt), GetY(poly, pt), GetOnCurve(poly, pt));
+}
+
+
+IPoint GlyphPoints::GetPoint(uint16_t pointNumber)
+{
+       if (pointNumber > numPoints)
+               throw GP_OUT_OF_RANGE;
+
+       return IPoint(x[pointNumber], y[pointNumber], onCurve[pointNumber]);
+}
+
+
+bool GlyphPoints::GetOnCurve(uint16_t poly, uint16_t pt)
 {
        if (pt >= GetNumPoints(poly))
 #ifdef DEBUG
 {
-WriteLogMsg("Exception: GetOnCurve(uint16, uint16). poly= %u, pt=%u, numPoints=%u\xD\xA", poly, pt, numPoints);
+WriteLogMsg("Exception: GetOnCurve(uint16_t, uint16_t). poly= %u, pt=%u, numPoints=%u\xD\xA", poly, pt, numPoints);
 #endif
                throw GP_OUT_OF_RANGE;
 #ifdef DEBUG
@@ -398,12 +485,42 @@ WriteLogMsg("Exception: GetOnCurve(uint16, uint16). poly= %u, pt=%u, numPoints=%
        return onCurve[pt + (poly == 0 ? 0 : polyEnd[poly - 1] + 1)];
 }
 
-uint16 GlyphPoints::GetPolyEnd(uint16 poly)
+
+bool GlyphPoints::GetPrevOnCurve(uint16_t poly, uint16_t pt)
+{
+       return GetOnCurve(poly, GetPrev(poly, pt));
+}
+
+
+bool GlyphPoints::GetNextOnCurve(uint16_t poly, uint16_t pt)
+{
+       return GetOnCurve(poly, GetNext(poly, pt));
+}
+
+
+uint16_t GlyphPoints::GetPolyStart(uint16_t poly)
+{
+       if (poly >= numPolys)
+#ifdef DEBUG
+{
+WriteLogMsg("Exception: GetPolyEnd(uint16_t). poly=%u, numPolys=%u\xD\xA", poly, numPolys);
+#endif
+               throw GP_OUT_OF_RANGE;
+#ifdef DEBUG
+}
+#endif
+
+       // If it's poly 0, return 0. Otherwise, get the previous poly's end & add one to it
+       return (poly == 0 ? 0 : polyEnd[poly - 1] + 1);
+}
+
+
+uint16_t GlyphPoints::GetPolyEnd(uint16_t poly)
 {
        if (poly >= numPolys)
 #ifdef DEBUG
 {
-WriteLogMsg("Exception: GetPolyEnd(uint16). poly=%u, numPolys=%u\xD\xA", poly, numPolys);
+WriteLogMsg("Exception: GetPolyEnd(uint16_t). poly=%u, numPolys=%u\xD\xA", poly, numPolys);
 #endif
                throw GP_OUT_OF_RANGE;
 #ifdef DEBUG
@@ -413,33 +530,36 @@ WriteLogMsg("Exception: GetPolyEnd(uint16). poly=%u, numPolys=%u\xD\xA", poly, n
        return polyEnd[poly];
 }
 
+
 void GlyphPoints::OffsetPoints(int xOff, int yOff)
 {
        for(int i=0; i<numPoints; i++)
                x[i] += xOff, y[i] += yOff;
 }
 
+
 //
 // Offset only a specific polygon in the glyph
 //
-void GlyphPoints::OffsetPoly(uint16 poly, int32 xOff, int32 yOff)
+void GlyphPoints::OffsetPoly(uint16_t poly, int32_t xOff, int32_t yOff)
 {
        if (poly >= numPolys)
 #ifdef DEBUG
 {
-WriteLogMsg("Exception: GetPolyEnd(uint16). poly=%u, numPolys=%u\xD\xA", poly, numPolys);
+WriteLogMsg("Exception: GetPolyEnd(uint16_t). poly=%u, numPolys=%u\xD\xA", poly, numPolys);
 #endif
                throw GP_OUT_OF_RANGE;
 #ifdef DEBUG
 }
 #endif
 
-       uint16 polyStart = (poly == 0 ? 0 : polyEnd[poly - 1] + 1);
+       uint16_t polyStart = (poly == 0 ? 0 : polyEnd[poly - 1] + 1);
 
        for(int i=0; i<GetNumPoints(poly); i++)
                x[polyStart + i] += xOff, y[polyStart + i] += yOff;
 }
 
+
 void GlyphPoints::ScalePoints(float sc)
 {
        for(int i=0; i<numPoints; i++)
@@ -447,12 +567,13 @@ void GlyphPoints::ScalePoints(float sc)
                y[i] = (int)(((float)y[i] * sc) + 0.5f);
 }
 
-void GlyphPoints::SetXY(uint16 pt, int xx, int yy)
+
+void GlyphPoints::SetXY(uint16_t pt, int xx, int yy)
 {
        if (pt >= numPoints)
 #ifdef DEBUG
 {
-WriteLogMsg("Exception: SetXY(uint16, int, int). pt=%u, numPoints=%u\xD\xA", pt, numPoints);
+WriteLogMsg("Exception: SetXY(uint16_t, int, int). pt=%u, numPoints=%u\xD\xA", pt, numPoints);
 #endif
                throw GP_OUT_OF_RANGE;
 #ifdef DEBUG
@@ -462,12 +583,13 @@ WriteLogMsg("Exception: SetXY(uint16, int, int). pt=%u, numPoints=%u\xD\xA", pt,
        x[pt] = xx, y[pt] = yy;
 }
 
-void GlyphPoints::SetOnCurve(uint16 pt, bool oc)
+
+void GlyphPoints::SetOnCurve(uint16_t pt, bool oc)
 {
        if (pt >= numPoints)
 #ifdef DEBUG
 {
-WriteLogMsg("Exception: SetOnCurve(uint16, bool). pt=%u, numPoints=%u\xD\xA", pt, numPoints);
+WriteLogMsg("Exception: SetOnCurve(uint16_t, bool). pt=%u, numPoints=%u\xD\xA", pt, numPoints);
 #endif
                throw GP_OUT_OF_RANGE;
 #ifdef DEBUG
@@ -477,10 +599,27 @@ WriteLogMsg("Exception: SetOnCurve(uint16, bool). pt=%u, numPoints=%u\xD\xA", pt
        onCurve[pt] = oc;
 }
 
-uint16 GlyphPoints::GetPrev(uint16 pt)
+
+void GlyphPoints::SetPoint(const uint16_t pointNum, const IPoint point)
+{
+       if (pointNum >= numPoints)
+#ifdef DEBUG
+{
+WriteLogMsg("Exception: SetPoint(uint16_t, IPoint). pt=%u, numPoints=%u\xD\xA", pointNum, numPoints);
+#endif
+               throw GP_OUT_OF_RANGE;
+#ifdef DEBUG
+}
+#endif
+
+       x[pointNum] = point.x, y[pointNum] = point.y, onCurve[pointNum] = point.onCurve;
+}
+
+
+uint16_t GlyphPoints::GetPrev(uint16_t pt)
 {
 // pt = 7, polyEnd = 4, 9, 15
-       uint16 min = 0, max = numPoints - 1;
+       uint16_t min = 0, max = numPoints - 1;
 
        for(int i=0; i<numPolys; i++)
        {
@@ -494,7 +633,7 @@ uint16 GlyphPoints::GetPrev(uint16 pt)
                }
        }
 
-       uint16 retVal = pt - 1;
+       uint16_t retVal = pt - 1;
 
        if (pt == min)
                retVal = max;
@@ -502,9 +641,10 @@ uint16 GlyphPoints::GetPrev(uint16 pt)
        return retVal;
 }
 
-uint16 GlyphPoints::GetNext(uint16 pt)
+
+uint16_t GlyphPoints::GetNext(uint16_t pt)
 {
-       uint16 min = 0, max = numPoints - 1;
+       uint16_t min = 0, max = numPoints - 1;
 
        for(int i=0; i<numPolys; i++)
        {
@@ -518,7 +658,7 @@ uint16 GlyphPoints::GetNext(uint16 pt)
                }
        }
 
-       uint16 retVal = pt + 1;
+       uint16_t retVal = pt + 1;
 
        if (pt == max)
                retVal = min;
@@ -526,30 +666,34 @@ uint16 GlyphPoints::GetNext(uint16 pt)
        return retVal;
 }
 
+
 //
 // Get previous point for this polygon using wraparound.
 // Note that pt is a zero-based index!
 //
-uint16 GlyphPoints::GetPrev(uint16 poly, uint16 pt)
+uint16_t GlyphPoints::GetPrev(uint16_t poly, uint16_t pt)
 {
        return (pt == 0 ? GetNumPoints(poly) - 1 : pt - 1);
 }
 
+
 //
 // Get next point for this polygon using wraparound.
 // Note that pt is a zero-based index!
 //
-uint16 GlyphPoints::GetNext(uint16 poly, uint16 pt)
+uint16_t GlyphPoints::GetNext(uint16_t poly, uint16_t pt)
 {
        return (pt == GetNumPoints(poly) - 1 ? 0 : pt + 1);
 }
 
-uint16 GlyphPoints::GetPoly(uint16 pt)
+
+#warning "!!! This function returns incorrect results !!!"
+uint16_t GlyphPoints::GetPoly(uint16_t pt)
 {
        if (pt >= numPoints)
 #ifdef DEBUG
 {
-WriteLogMsg("Exception: GetPoly(uint16). pt=%u, numPoints=%u\xD\xA", pt, numPoints);
+WriteLogMsg("Exception: GetPoly(uint16_t). pt=%u, numPoints=%u\xD\xA", pt, numPoints);
 #endif
                throw GP_OUT_OF_RANGE;
 #ifdef DEBUG
@@ -560,17 +704,18 @@ WriteLogMsg("Exception: GetPoly(uint16). pt=%u, numPoints=%u\xD\xA", pt, numPoin
                if (pt <= polyEnd[i])
                        return i;
 
-       return (uint16)-1;
+       return (uint16_t)-1;
 }
 
+
 void GlyphPoints::AddNewPolyAtEnd(void)
 {
        if (numPoints == 0)                                                     // By default, we already *have* a poly
                return;
 
-       uint16 * newPolyEnd = new uint16[numPolys + 1];
+       uint16_t * newPolyEnd = new uint16_t[numPolys + 1];
 
-       for(uint16 i=0; i<numPolys; i++)
+       for(uint16_t i=0; i<numPolys; i++)
                newPolyEnd[i] = polyEnd[i];
 
        newPolyEnd[numPolys] = newPolyEnd[numPolys - 1];
@@ -579,3 +724,244 @@ void GlyphPoints::AddNewPolyAtEnd(void)
        polyEnd = newPolyEnd;
 }
 
+
+IPoint GlyphPoints::GetMidpointToPrev(uint16_t poly, uint16_t pt)
+{
+       uint16_t prev = GetPrev(poly, pt);
+
+       int32_t x1 = GetX(poly, pt), y1 = GetY(poly, pt);
+       int32_t x2 = GetX(poly, prev), y2 = GetY(poly, prev);
+
+       return IPoint((x1 + x2) / 2.0f, (y1 + y2) / 2.0f);
+}
+
+
+IPoint GlyphPoints::GetMidpointToNext(uint16_t poly, uint16_t pt)
+{
+       uint16_t next = GetNext(poly, pt);
+
+       int32_t x1 = GetX(poly, pt), y1 = GetY(poly, pt);
+       int32_t x2 = GetX(poly, next), y2 = GetY(poly, next);
+
+       return IPoint((x1 + x2) / 2.0f, (y1 + y2) / 2.0f);
+}
+
+
+IPoint GlyphPoints::GetPrevPoint(uint16_t poly, uint16_t pt)
+{
+       uint16_t prevPt = GetPrev(poly, pt);
+
+       return IPoint(GetX(poly, prevPt), GetY(poly, prevPt));
+}
+
+
+IPoint GlyphPoints::GetNextPoint(uint16_t poly, uint16_t pt)
+{
+       uint16_t nextPt = GetNext(poly, pt);
+
+       return IPoint(GetX(poly, nextPt), GetY(poly, nextPt));
+}
+
+
+uint16_t GlyphPoints::GetPolyForPoint(IPoint point)
+{
+       uint16_t poly = 0;
+
+       for(uint16_t i=0; i<numPoints; i++)
+       {
+               if (i > polyEnd[poly])
+                       poly++;
+
+               if (IPoint(x[i], y[i]) == point)
+                       return poly;
+       }
+
+       return 0xFFFF;
+}
+
+
+uint16_t GlyphPoints::GetPolyForPointNumber(uint16_t pointNumber)
+{
+       // If there's only one poly, we know where the point is...
+       if (numPolys <= 1)
+               return 0;
+
+       // Otherwise, do a linear search through the polys to find the right one
+       for(uint16_t i=0; i<numPolys; i++)
+       {
+               if (pointNumber >= GetPolyStart(i) && pointNumber <= polyEnd[i])
+                       return i;
+       }
+
+       return 0xFFFF;
+}
+
+
+//
+// Rotate a point by "angle" around point "center"
+//
+IPoint GlyphPoints::RotatePoint(const double angle, const IPoint point, const IPoint center)
+{
+       // Translate the point to the origin
+       double xt = (double)(point.x - center.x);
+       double yt = (double)(point.y - center.y);
+
+       // Rotate the point by angle
+       double xr = (xt * cos(angle)) - (yt * sin(angle));
+       double yr = (xt * sin(angle)) + (yt * cos(angle));
+
+       // Translate it back...
+       IPoint rotated;
+       rotated.x = (int)(xr + 0.5) + center.x;
+       rotated.y = (int)(yr + 0.5) + center.y;
+       return rotated;
+}
+
+
+//
+// Rotate all points in the glyph by "angle" around point "pt"
+//
+void GlyphPoints::RotatePoints(const double angle, const IPoint pt)
+{
+       for(int i=0; i<numPoints; i++)
+       {
+               // Translate the point to the origin
+               double xt = (double)(x[i] - pt.x);
+               double yt = (double)(y[i] - pt.y);
+
+               // Rotate the point by angle
+               double xr = (xt * cos(angle)) - (yt * sin(angle));
+               double yr = (xt * sin(angle)) + (yt * cos(angle));
+
+               // Put it back...
+               x[i] = (int)(xr + 0.5) + pt.x;
+               y[i] = (int)(yr + 0.5) + pt.y;
+       }
+}
+
+
+IPoint GlyphPoints::GetPolyCentroid(const int16_t poly)
+{
+       // We should throw an exception here, but meh
+       // (this actually short circuits the exception handling in all the GetPolyXXX() functions)
+       // [now we do!]
+       if (poly >= numPolys)
+               throw GP_OUT_OF_RANGE;
+//             return IPoint(0, 0);
+
+//     if (poly >= numPolys)
+//#ifdef DEBUG
+//{
+//WriteLogMsg("Exception: GetPolyEnd(uint16_t). poly=%u, numPolys=%u\xD\xA", poly, numPolys);
+//#endif
+//             throw GP_OUT_OF_RANGE;
+//#ifdef DEBUG
+//}
+//#endif
+
+       IPoint centroid;                                                                // Initializes to (0, 0)
+       uint16_t numPointsInPoly = GetNumPoints(poly);
+
+       for(uint16_t i=GetPolyStart(poly); i<=GetPolyEnd(poly); i++)
+       {
+               centroid.x += x[i];
+               centroid.y += y[i];
+       }
+
+       centroid.x /= numPointsInPoly;
+       centroid.y /= numPointsInPoly;
+
+       return centroid;
+}
+
+
+void GlyphPoints::RotatePolyAroundCentroid(const int16_t poly, const double angle)
+{
+       if (poly >= numPolys)
+               return;
+
+       IPoint centroid = GetPolyCentroid(poly);
+
+       for(uint16_t i=GetPolyStart(poly); i<=GetPolyEnd(poly); i++)
+       {
+               IPoint rotated = RotatePoint(angle, IPoint(x[i], y[i]), centroid);
+               x[i] = rotated.x;
+               y[i] = rotated.y;
+       }
+}
+
+
+void GlyphPoints::InvertPolyDrawSequence(const uint16_t poly)
+{
+       if (poly >= numPolys)
+               throw GP_OUT_OF_RANGE;
+
+       uint16_t pointNum1 = GetPolyStart(poly);
+       uint16_t pointNum2 = GetPolyEnd(poly);
+
+       // Algorithm: Step through points in the polygon, swapping 1st and last, then
+       // 2nd and (last - 1), 3rd and (last - 2), etc. We only do this for half the
+       // points, as doing it for all would undo the swapping we did in the 1st half.
+       for(uint16_t i=0; i<GetNumPoints(poly)/2; i++)
+       {
+               IPoint point1 = GetPoint(pointNum1 + i);
+               IPoint point2 = GetPoint(pointNum2 - i);
+               SetPoint(pointNum2 - i, point1);
+               SetPoint(pointNum1 + i, point2);
+       }
+}
+
+
+// really need to do checking on the results from fscanf...
+bool GlyphPoints::LoadGlyphFromFile(FILE * file)
+{
+       char line[512];
+       float version;
+
+       FreeAllocatedMemory();
+
+       fscanf(file, "%s V%f", line, &version);
+       fscanf(file, "%s %u", line, &numPoints);
+       x = new int[numPoints];
+       y = new int[numPoints];
+       onCurve = new bool[numPoints];
+
+       for(int i=0; i<numPoints; i++)
+       {
+               fscanf(file, "%d %d %s", &x[i], &y[i], (char *)&line);
+               onCurve[i] = (line[0] == 'T' ? true : false);
+       }
+
+       fscanf(file, "%s %u", line, &numPolys);
+       polyEnd = new uint16_t[numPolys];
+
+       for(int i=0; i<numPolys; i++)
+       {
+               fscanf(file, "%u", &polyEnd[i]);
+       }
+
+       return true;
+}
+
+
+bool GlyphPoints::SaveGlyphToFile(FILE * file)
+{
+//     GlyphPoints glyph = editWnd->pts;
+       fprintf(file, "TTEGLYPH V1.0\n");
+       fprintf(file, "POINTS %u\n", numPoints);
+
+       for(int i=0; i<numPoints; i++)
+       {
+               fprintf(file, "%d %d %s\n", x[i], y[i], (onCurve[i] ? "T" : "F")); 
+       }
+
+       fprintf(file, "POLYS %u\n", numPolys);
+
+       for(int i=0; i<numPolys; i++)
+       {
+               fprintf(file, "%u\n", polyEnd[i]); 
+       }
+
+       return true;
+}
+