-//\r
-// GLYPHPOINTS.CPP\r
-//\r
-// Class implementation. Nothing too inexplicable going on here. Fairly\r
-// straightforward stuff.\r
-//\r
-// by James L. Hammons\r
-// (C) 2004 Underground Software\r
-//\r
-// JLH = James L. Hammons <jlhamm@acm.org>\r
-//\r
-// Who When What\r
-// --- ---------- ------------------------------------------------------------\r
-// JLH ??/??/200? Created this file\r
-// JLH 05/18/2004 Added pure point adding, inserting, better polygon handling\r
-//\r
-\r
-// Uncomment this for debugging...\r
-#define DEBUG\r
-\r
-#include "glyphpoints.h"\r
-#ifdef DEBUG\r
-#include "debug.h"\r
-#endif\r
-\r
-/*GlyphPoints::GlyphPoints(void)\r
-{\r
- GlyphPoints(0, 0, NULL, NULL, NULL, NULL);\r
-}*/\r
-\r
-GlyphPoints::GlyphPoints(int nPts/*=0*/, int nPlys/*=0*/, int * xa/*=null*/, int * ya/*=null*/,\r
- bool * oca/*=null*/, uint16 * pa/*=null*/): x(NULL), y(NULL), onCurve(NULL), polyEnd(NULL)\r
-//GlyphPoints::GlyphPoints(int nPts, int nPlys/*=0*/, int * xa/*=null*/, int * ya/*=null*/,\r
-// bool * oca/*=null*/, uint16 * pa/*=null*/): x(NULL), y(NULL), onCurve(NULL), polyEnd(NULL)\r
-{\r
- AllocateAndCopy(nPts, nPlys, xa, ya, oca, pa);\r
-\r
- if (nPlys == 0)\r
- {\r
- numPolys = 1;\r
- polyEnd = new uint16[numPolys];\r
- polyEnd[0] = numPoints - 1;\r
- }\r
-#ifdef DEBUG\r
-WriteLogMsg("GlyphPoints: Default constructor. %u points, %u polys.\n", numPoints, numPolys);\r
-#endif\r
-}\r
-\r
-GlyphPoints::GlyphPoints(int xx, int yy, bool oc)\r
-{\r
-//Hmm. What to do with this...?\r
- AllocateAndCopy(1, 0, &xx, &yy, &oc, NULL);\r
-#ifdef DEBUG\r
-WriteLogMsg("GlyphPoints: Single point constructor. %u points, %u polys.\n", numPoints, numPolys);\r
-#endif\r
-}\r
-\r
-// Copy constructor (needed for deep copying)\r
-\r
-//GlyphPoints::GlyphPoints(GlyphPoints &c): x(NULL), y(NULL), onCurve(NULL), polyEnd(NULL)\r
-GlyphPoints::GlyphPoints(const GlyphPoints &c): x(NULL), y(NULL), onCurve(NULL), polyEnd(NULL)\r
-{\r
- *this = c; // Use overloaded operator=\r
-#ifdef DEBUG\r
-WriteLogMsg("GlyphPoints: Copy constructor. %u points, %u polys.\n", numPoints, numPolys);\r
-#endif\r
-}\r
-\r
-GlyphPoints::~GlyphPoints()\r
-{\r
- if (x)\r
- delete[] x;\r
-\r
- if (y)\r
- delete[] y;\r
-\r
- if (onCurve)\r
- delete[] onCurve;\r
-\r
- if (polyEnd)\r
- delete[] polyEnd;\r
-}\r
-\r
-void GlyphPoints::AllocateAndCopy(int nPts, int nPlys, int * xa, int * ya, bool * oca, uint16 * pa)\r
-{\r
- numPoints = nPts, numPolys = nPlys;\r
-\r
- if (nPts)\r
- {\r
- x = new int[numPoints];\r
- y = new int[numPoints];\r
- onCurve = new bool[numPoints];\r
-\r
- if (xa) // Copy points in if they're passed in...\r
- for(int i=0; i<nPts; i++)\r
- x[i] = xa[i];\r
-\r
- if (ya)\r
- for(int i=0; i<nPts; i++)\r
- y[i] = ya[i];\r
-\r
- if (oca)\r
- for(int i=0; i<nPts; i++)\r
- onCurve[i] = oca[i];\r
- }\r
-\r
- if (numPolys)\r
- {\r
- polyEnd = new uint16[numPolys];\r
-\r
- if (pa) // Copy poly ends in if they're passed in...\r
- for(int i=0; i<nPlys; i++)\r
- polyEnd[i] = pa[i];\r
- }\r
-}\r
-\r
-GlyphPoints& GlyphPoints::operator=(const GlyphPoints &c)\r
-{\r
- if (this == &c)\r
- return *this; // Take care of self-assignment\r
-\r
- if (x)\r
- delete[] x;\r
-\r
- if (y)\r
- delete[] y;\r
-\r
- if (onCurve)\r
- delete[] onCurve;\r
-\r
- if (polyEnd)\r
- delete[] polyEnd;\r
-\r
- AllocateAndCopy(c.numPoints, c.numPolys, c.x, c.y, c.onCurve, c.polyEnd);\r
-\r
- return *this;\r
-}\r
-\r
-// Add another GlyphPoints' points to this one...\r
-\r
-GlyphPoints GlyphPoints::operator+(const GlyphPoints &c)\r
-{\r
- int totPoints = numPoints + c.numPoints, totPolys = numPolys + c.numPolys;\r
-\r
- int * totX = new int[totPoints];\r
- int * totY = new int[totPoints];\r
- bool * totOnCurve = new bool[totPoints];\r
- uint16 * totPolyEnd = new uint16[totPolys];\r
-\r
- for(int i=0; i<numPoints; i++)\r
- {\r
- totX[i] = x[i];\r
- totY[i] = y[i];\r
- totOnCurve[i] = onCurve[i];\r
- }\r
-\r
- for(int i=0; i<numPolys; i++)\r
- totPolyEnd[i] = polyEnd[i];\r
-\r
- for(int i=0; i<c.numPoints; i++)\r
- {\r
- totX[numPoints+i] = c.x[i];\r
- totY[numPoints+i] = c.y[i];\r
- totOnCurve[numPoints+i] = c.onCurve[i];\r
- }\r
-\r
- for(int i=0; i<c.numPolys; i++)\r
- totPolyEnd[numPolys+i] = numPoints + c.polyEnd[i]; // Need to adjust the "added in"\r
- // poly's end points...\r
-\r
- GlyphPoints retVal(totPoints, totPolys, totX, totY, totOnCurve, totPolyEnd);\r
- delete[] totX;\r
- delete[] totY;\r
- delete[] totOnCurve;\r
- delete[] totPolyEnd;\r
-\r
- return retVal;\r
-}\r
-\r
-// Add a point to this GlyphPoints...\r
-\r
-GlyphPoints GlyphPoints::operator+(const IPoint &c)\r
-{\r
-//This is kinda silly. We can do better than this! !!! FIX !!!\r
- int * totX = new int[numPoints + 1];\r
- int * totY = new int[numPoints + 1];\r
- bool * totOnCurve = new bool[numPoints + 1];\r
- uint16 * totPolyEnd = new uint16[numPolys];\r
-\r
- for(int i=0; i<numPoints; i++)\r
- totX[i] = x[i], totY[i] = y[i], totOnCurve[i] = onCurve[i];\r
-\r
- totX[numPoints] = c.x, totY[numPoints] = c.y, totOnCurve[numPoints] = c.onCurve;\r
-\r
- for(int i=0; i<numPolys; i++)\r
- totPolyEnd[i] = polyEnd[i];\r
-\r
- totPolyEnd[numPolys - 1]++; // Bump polygon's end point\r
- GlyphPoints retVal(numPoints + 1, numPolys, totX, totY, totOnCurve, totPolyEnd);\r
-\r
- delete[] totX;\r
- delete[] totY;\r
- delete[] totOnCurve;\r
-\r
- return retVal;\r
-}\r
-\r
-GlyphPoints& GlyphPoints::operator+=(const IPoint &p)\r
-{\r
- InsertPoint(numPoints, p.x, p.y, p.onCurve);\r
-\r
- return *this;\r
-}\r
-\r
-void GlyphPoints::InsertPoint(uint16 pt, int xx, int yy, bool oc)\r
-{\r
- if (pt > numPoints) // > because we can insert at end...!\r
- throw GP_OUT_OF_RANGE;\r
-\r
-//This is kinda silly. We can do better than this! !!! FIX !!!\r
- int * totX = new int[numPoints + 1];\r
- int * totY = new int[numPoints + 1];\r
- bool * totOnCurve = new bool[numPoints + 1];\r
-\r
- for(int i=0; i<pt; i++)\r
- totX[i] = x[i], totY[i] = y[i], totOnCurve[i] = onCurve[i];\r
-\r
- for(int i=pt; i<numPoints; i++)\r
- totX[i + 1] = x[i], totY[i + 1] = y[i], totOnCurve[i + 1] = onCurve[i];\r
-\r
- totX[pt] = xx, totY[pt] = yy, totOnCurve[pt] = oc;\r
-\r
-//A way to fix the kludge in GetPoly() would be to put a check here to see if \r
-//we're adding to the end of the structure: [DONE, below]\r
- int polyInsert = (pt == numPoints ? numPolys - 1 : GetPoly(pt));\r
- for(int i=polyInsert; i<numPolys; i++)\r
-// for(int i=GetPoly(pt); i<numPolys; i++)\r
- polyEnd[i]++; // Bump polygons' end point\r
-\r
- numPoints++;\r
-\r
- delete[] x;\r
- delete[] y;\r
- delete[] onCurve;\r
-\r
- x = totX, y = totY, onCurve = totOnCurve;\r
-}\r
-\r
-void GlyphPoints::InsertPoint(uint16 pt, const IPoint &p)\r
-{\r
- InsertPoint(pt, p.x, p.y, p.onCurve);\r
-}\r
-\r
-//\r
-// Delete a point from the glyph\r
-// Note that we don't bother to reallocate anything here, just bump the\r
-// size counters down as needed. In the future, we'll keep track so we\r
-// don't have to reallocate *every* damn time a point is added...\r
-//\r
-void GlyphPoints::DeletePoint(uint16 pt)\r
-{\r
- // Adjust polygon ends appropriately\r
- uint16 poly = GetPoly(pt);\r
-\r
- for(int i=poly; i<numPolys; i++)\r
- polyEnd[i]--;\r
-\r
-//Need to check here if we're deleting the last point in the glyph or not.\r
-//!!! FIX !!! [DONE]\r
- if (GetNumPoints(poly) == 0 && numPoints > 0)\r
- {\r
- numPolys--;\r
-\r
- for(int i=poly; i<numPolys; i++)\r
- polyEnd[i] = polyEnd[i + 1];\r
- }\r
-\r
-//This causes a crash becuz GetPoly() uses numPoints... !!! FIX !!! [DONE by switching poly delete & point delete]\r
- // Close up the gap left by the current point\r
- numPoints--;\r
-\r
- for(int i=pt; i<numPoints; i++)\r
- x[i] = x[i + 1], y[i] = y[i + 1], onCurve[i] = onCurve[i + 1];\r
-}\r
-\r
-uint16 GlyphPoints::GetNumPoints(void)\r
-{\r
- return numPoints;\r
-}\r
-\r
-uint16 GlyphPoints::GetNumPoints(uint16 poly)\r
-{\r
- if (poly >= numPolys)\r
-#ifdef DEBUG\r
-{\r
-WriteLogMsg("Exception: GetNumPoints(uint16). poly=%u, numPolys=%u\xD\xA", poly, numPolys);\r
-#endif\r
- throw GP_OUT_OF_RANGE;\r
-#ifdef DEBUG\r
-}\r
-#endif\r
-\r
- return polyEnd[poly] - (poly == 0 ? -1 : polyEnd[poly - 1]);\r
-}\r
-\r
-uint16 GlyphPoints::GetNumPolys(void)\r
-{\r
- return numPolys;\r
-}\r
-\r
-int GlyphPoints::GetX(uint16 pt)\r
-{\r
- if (pt >= numPoints)\r
-#ifdef DEBUG\r
-{\r
-WriteLogMsg("Exception: GetX(uint16). pt=%u, numPoints=%u\xD\xA", pt, numPoints);\r
-#endif\r
- throw GP_OUT_OF_RANGE;\r
-#ifdef DEBUG\r
-}\r
-#endif\r
-\r
- return x[pt];\r
-}\r
-\r
-int GlyphPoints::GetY(uint16 pt)\r
-{\r
- if (pt >= numPoints)\r
-#ifdef DEBUG\r
-{\r
-WriteLogMsg("Exception: GetY(uint16). pt=%u, numPoints=%u\xD\xA", pt, numPoints);\r
-#endif\r
- throw GP_OUT_OF_RANGE;\r
-#ifdef DEBUG\r
-}\r
-#endif\r
-\r
- return y[pt];\r
-}\r
-\r
-bool GlyphPoints::GetOnCurve(uint16 pt)\r
-{\r
- if (pt >= numPoints)\r
-#ifdef DEBUG\r
-{\r
-WriteLogMsg("Exception: GetOnCurve(uint16). pt=%u, numPoints=%u\xD\xA", pt, numPoints);\r
-#endif\r
- throw GP_OUT_OF_RANGE;\r
-#ifdef DEBUG\r
-}\r
-#endif\r
-\r
- return onCurve[pt];\r
-}\r
-\r
-int GlyphPoints::GetX(uint16 poly, uint16 pt)\r
-{\r
- if (pt >= GetNumPoints(poly))\r
-#ifdef DEBUG\r
-{\r
-WriteLogMsg("Exception: GetX(uint16, uint16). poly= %u, pt=%u, numPoints=%u\xD\xA", poly, pt, numPoints);\r
-#endif\r
- throw GP_OUT_OF_RANGE;\r
-#ifdef DEBUG\r
-}\r
-#endif\r
-\r
- return x[pt + (poly == 0 ? 0 : polyEnd[poly - 1] + 1)];\r
-}\r
-\r
-int GlyphPoints::GetY(uint16 poly, uint16 pt)\r
-{\r
- if (pt >= GetNumPoints(poly))\r
-#ifdef DEBUG\r
-{\r
-WriteLogMsg("Exception: GetY(uint16, uint16). poly= %u, pt=%u, numPoints=%u\xD\xA", poly, pt, numPoints);\r
-#endif\r
- throw GP_OUT_OF_RANGE;\r
-#ifdef DEBUG\r
-}\r
-#endif\r
-\r
- return y[pt + (poly == 0 ? 0 : polyEnd[poly - 1] + 1)];\r
-}\r
-\r
-bool GlyphPoints::GetOnCurve(uint16 poly, uint16 pt)\r
-{\r
- if (pt >= GetNumPoints(poly))\r
-#ifdef DEBUG\r
-{\r
-WriteLogMsg("Exception: GetOnCurve(uint16, uint16). poly= %u, pt=%u, numPoints=%u\xD\xA", poly, pt, numPoints);\r
-#endif\r
- throw GP_OUT_OF_RANGE;\r
-#ifdef DEBUG\r
-}\r
-#endif\r
-\r
- return onCurve[pt + (poly == 0 ? 0 : polyEnd[poly - 1] + 1)];\r
-}\r
-\r
-uint16 GlyphPoints::GetPolyEnd(uint16 poly)\r
-{\r
- if (poly >= numPolys)\r
-#ifdef DEBUG\r
-{\r
-WriteLogMsg("Exception: GetPolyEnd(uint16). poly=%u, numPolys=%u\xD\xA", poly, numPolys);\r
-#endif\r
- throw GP_OUT_OF_RANGE;\r
-#ifdef DEBUG\r
-}\r
-#endif\r
-\r
- return polyEnd[poly];\r
-}\r
-\r
-void GlyphPoints::OffsetPoints(int xOff, int yOff)\r
-{\r
- for(int i=0; i<numPoints; i++)\r
- x[i] += xOff, y[i] += yOff;\r
-}\r
-\r
-//\r
-// Offset only a specific polygon in the glyph\r
-//\r
-void GlyphPoints::OffsetPoly(uint16 poly, int32 xOff, int32 yOff)\r
-{\r
- if (poly >= numPolys)\r
-#ifdef DEBUG\r
-{\r
-WriteLogMsg("Exception: GetPolyEnd(uint16). poly=%u, numPolys=%u\xD\xA", poly, numPolys);\r
-#endif\r
- throw GP_OUT_OF_RANGE;\r
-#ifdef DEBUG\r
-}\r
-#endif\r
-\r
- uint16 polyStart = (poly == 0 ? 0 : polyEnd[poly - 1] + 1);\r
-\r
- for(int i=0; i<GetNumPoints(poly); i++)\r
- x[polyStart + i] += xOff, y[polyStart + i] += yOff;\r
-}\r
-\r
-void GlyphPoints::ScalePoints(float sc)\r
-{\r
- for(int i=0; i<numPoints; i++)\r
- x[i] = (int)(((float)x[i] * sc) + 0.5f),\r
- y[i] = (int)(((float)y[i] * sc) + 0.5f);\r
-}\r
-\r
-void GlyphPoints::SetXY(uint16 pt, int xx, int yy)\r
-{\r
- if (pt >= numPoints)\r
-#ifdef DEBUG\r
-{\r
-WriteLogMsg("Exception: SetXY(uint16, int, int). pt=%u, numPoints=%u\xD\xA", pt, numPoints);\r
-#endif\r
- throw GP_OUT_OF_RANGE;\r
-#ifdef DEBUG\r
-}\r
-#endif\r
-\r
- x[pt] = xx, y[pt] = yy;\r
-}\r
-\r
-void GlyphPoints::SetOnCurve(uint16 pt, bool oc)\r
-{\r
- if (pt >= numPoints)\r
-#ifdef DEBUG\r
-{\r
-WriteLogMsg("Exception: SetOnCurve(uint16, bool). pt=%u, numPoints=%u\xD\xA", pt, numPoints);\r
-#endif\r
- throw GP_OUT_OF_RANGE;\r
-#ifdef DEBUG\r
-}\r
-#endif\r
-\r
- onCurve[pt] = oc;\r
-}\r
-\r
-uint16 GlyphPoints::GetPrev(uint16 pt)\r
-{\r
-// pt = 7, polyEnd = 4, 9, 15\r
- uint16 min = 0, max = numPoints - 1;\r
-\r
- for(int i=0; i<numPolys; i++)\r
- {\r
- if (pt <= polyEnd[i])\r
- {\r
- if (i > 0)\r
- min = polyEnd[i - 1] + 1;\r
-\r
- max = polyEnd[i];\r
- break;\r
- }\r
- }\r
-\r
- uint16 retVal = pt - 1;\r
-\r
- if (pt == min)\r
- retVal = max;\r
-\r
- return retVal;\r
-}\r
-\r
-uint16 GlyphPoints::GetNext(uint16 pt)\r
-{\r
- uint16 min = 0, max = numPoints - 1;\r
-\r
- for(int i=0; i<numPolys; i++)\r
- {\r
- if (pt <= polyEnd[i])\r
- {\r
- if (i > 0)\r
- min = polyEnd[i - 1] + 1;\r
-\r
- max = polyEnd[i];\r
- break;\r
- }\r
- }\r
-\r
- uint16 retVal = pt + 1;\r
-\r
- if (pt == max)\r
- retVal = min;\r
-\r
- return retVal;\r
-}\r
-\r
-//\r
-// Get previous point for this polygon using wraparound.\r
-// Note that pt is a zero-based index!\r
-//\r
-uint16 GlyphPoints::GetPrev(uint16 poly, uint16 pt)\r
-{\r
- return (pt == 0 ? GetNumPoints(poly) - 1 : pt - 1);\r
-}\r
-\r
-//\r
-// Get next point for this polygon using wraparound.\r
-// Note that pt is a zero-based index!\r
-//\r
-uint16 GlyphPoints::GetNext(uint16 poly, uint16 pt)\r
-{\r
- return (pt == GetNumPoints(poly) - 1 ? 0 : pt + 1);\r
-}\r
-\r
-uint16 GlyphPoints::GetPoly(uint16 pt)\r
-{\r
- if (pt >= numPoints)\r
-#ifdef DEBUG\r
-{\r
-WriteLogMsg("Exception: GetPoly(uint16). pt=%u, numPoints=%u\xD\xA", pt, numPoints);\r
-#endif\r
- throw GP_OUT_OF_RANGE;\r
-#ifdef DEBUG\r
-}\r
-#endif\r
-\r
- for(int i=0; i<numPolys; i++)\r
- if (pt <= polyEnd[i])\r
- return i;\r
-\r
- return (uint16)-1;\r
-}\r
-\r
-void GlyphPoints::AddNewPolyAtEnd(void)\r
-{\r
- if (numPoints == 0) // By default, we already *have* a poly\r
- return;\r
-\r
- uint16 * newPolyEnd = new uint16[numPolys + 1];\r
-\r
- for(uint16 i=0; i<numPolys; i++)\r
- newPolyEnd[i] = polyEnd[i];\r
-\r
- newPolyEnd[numPolys] = newPolyEnd[numPolys - 1];\r
- numPolys++;\r
- delete[] polyEnd;\r
- polyEnd = newPolyEnd;\r
-}\r
-\r
+//
+// GLYPHPOINTS.CPP
+//
+// Class implementation. Nothing too inexplicable going on here. Fairly
+// straightforward stuff.
+//
+// by James L. Hammons
+// (C) 2004 Underground Software
+//
+// 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
+//
+
+// Uncomment this for debugging...
+#define DEBUG
+
+#include "glyphpoints.h"
+#ifdef DEBUG
+#include "debug.h"
+#endif
+#include <math.h>
+
+
+/*GlyphPoints::GlyphPoints(void)
+{
+ GlyphPoints(0, 0, NULL, NULL, NULL, NULL);
+}*/
+
+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)
+//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)
+{
+ AllocateAndCopy(nPts, nPlys, xa, ya, oca, pa);
+
+ if (nPlys == 0)
+ {
+ numPolys = 1;
+ polyEnd = new uint16[numPolys];
+ polyEnd[0] = numPoints - 1;
+ }
+#ifdef DEBUG
+WriteLogMsg("GlyphPoints: Default constructor. %u points, %u polys.\n", numPoints, numPolys);
+#endif
+}
+
+
+GlyphPoints::GlyphPoints(int xx, int yy, bool oc)
+{
+//Hmm. What to do with this...?
+ AllocateAndCopy(1, 0, &xx, &yy, &oc, NULL);
+#ifdef DEBUG
+WriteLogMsg("GlyphPoints: Single point constructor. %u points, %u polys.\n", numPoints, numPolys);
+#endif
+}
+
+
+// Copy constructor (needed for deep copying)
+
+//GlyphPoints::GlyphPoints(GlyphPoints &c): x(NULL), y(NULL), onCurve(NULL), polyEnd(NULL)
+GlyphPoints::GlyphPoints(const GlyphPoints &c): x(NULL), y(NULL), onCurve(NULL), polyEnd(NULL)
+{
+ *this = c; // Use overloaded operator=
+#ifdef DEBUG
+WriteLogMsg("GlyphPoints: Copy constructor. %u points, %u polys.\n", numPoints, numPolys);
+#endif
+}
+
+
+GlyphPoints::~GlyphPoints()
+{
+ FreeAllocatedMemory();
+#if 0
+ if (x)
+ delete[] x;
+
+ if (y)
+ delete[] y;
+
+ if (onCurve)
+ delete[] onCurve;
+
+ if (polyEnd)
+ delete[] polyEnd;
+#endif
+}
+
+
+void GlyphPoints::AllocateAndCopy(int nPts, int nPlys, int * xa, int * ya, bool * oca, uint16 * pa)
+{
+ numPoints = nPts, numPolys = nPlys;
+
+ if (nPts)
+ {
+ x = new int[numPoints];
+ y = new int[numPoints];
+ onCurve = new bool[numPoints];
+
+ if (xa) // Copy points in if they're passed in...
+ for(int i=0; i<nPts; i++)
+ x[i] = xa[i];
+
+ if (ya)
+ for(int i=0; i<nPts; i++)
+ y[i] = ya[i];
+
+ if (oca)
+ for(int i=0; i<nPts; i++)
+ onCurve[i] = oca[i];
+ }
+
+ if (numPolys)
+ {
+ polyEnd = new uint16[numPolys];
+
+ if (pa) // Copy poly ends in if they're passed in...
+ for(int i=0; i<nPlys; i++)
+ polyEnd[i] = pa[i];
+ }
+}
+
+
+void GlyphPoints::FreeAllocatedMemory(void)
+{
+ if (x)
+ delete[] x;
+
+ if (y)
+ delete[] y;
+
+ if (onCurve)
+ delete[] onCurve;
+
+ 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)
+{
+ int totPoints = numPoints + c.numPoints, totPolys = numPolys + c.numPolys;
+
+ int * totX = new int[totPoints];
+ int * totY = new int[totPoints];
+ bool * totOnCurve = new bool[totPoints];
+ uint16 * totPolyEnd = new uint16[totPolys];
+
+ for(int i=0; i<numPoints; i++)
+ {
+ totX[i] = x[i];
+ totY[i] = y[i];
+ totOnCurve[i] = onCurve[i];
+ }
+
+ for(int i=0; i<numPolys; i++)
+ totPolyEnd[i] = polyEnd[i];
+
+ for(int i=0; i<c.numPoints; i++)
+ {
+ totX[numPoints+i] = c.x[i];
+ totY[numPoints+i] = c.y[i];
+ totOnCurve[numPoints+i] = c.onCurve[i];
+ }
+
+ for(int i=0; i<c.numPolys; i++)
+ totPolyEnd[numPolys+i] = numPoints + c.polyEnd[i]; // Need to adjust the "added in"
+ // poly's end points...
+
+ GlyphPoints retVal(totPoints, totPolys, totX, totY, totOnCurve, totPolyEnd);
+ delete[] totX;
+ delete[] totY;
+ delete[] totOnCurve;
+ delete[] totPolyEnd;
+
+ return retVal;
+}
+
+
+// Add a point to this GlyphPoints...
+
+GlyphPoints GlyphPoints::operator+(const IPoint &c)
+{
+//This is kinda silly. We can do better than this! !!! FIX !!!
+ int * totX = new int[numPoints + 1];
+ int * totY = new int[numPoints + 1];
+ bool * totOnCurve = new bool[numPoints + 1];
+ uint16 * totPolyEnd = new uint16[numPolys];
+
+ for(int i=0; i<numPoints; i++)
+ totX[i] = x[i], totY[i] = y[i], totOnCurve[i] = onCurve[i];
+
+ totX[numPoints] = c.x, totY[numPoints] = c.y, totOnCurve[numPoints] = c.onCurve;
+
+ for(int i=0; i<numPolys; i++)
+ totPolyEnd[i] = polyEnd[i];
+
+ totPolyEnd[numPolys - 1]++; // Bump polygon's end point
+ GlyphPoints retVal(numPoints + 1, numPolys, totX, totY, totOnCurve, totPolyEnd);
+
+ delete[] totX;
+ delete[] totY;
+ delete[] totOnCurve;
+
+ return retVal;
+}
+
+
+GlyphPoints& GlyphPoints::operator+=(const IPoint &p)
+{
+ InsertPoint(numPoints, p.x, p.y, p.onCurve);
+
+ return *this;
+}
+
+
+void GlyphPoints::Clear(void)
+{
+ FreeAllocatedMemory();
+ x = y = NULL;
+ onCurve = NULL;
+ polyEnd = NULL;
+ numPoints = numPolys = pointsAllocated = polysAllocated = 0;
+}
+
+
+void GlyphPoints::InsertPoint(uint16 pt, int xx, int yy, bool oc)
+{
+ if (pt > numPoints) // > because we can insert at end...!
+ throw GP_OUT_OF_RANGE;
+
+//This is kinda silly. We can do better than this! !!! FIX !!!
+ int * totX = new int[numPoints + 1];
+ int * totY = new int[numPoints + 1];
+ bool * totOnCurve = new bool[numPoints + 1];
+
+ for(int i=0; i<pt; i++)
+ totX[i] = x[i], totY[i] = y[i], totOnCurve[i] = onCurve[i];
+
+ for(int i=pt; i<numPoints; i++)
+ totX[i + 1] = x[i], totY[i + 1] = y[i], totOnCurve[i + 1] = onCurve[i];
+
+ 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
+//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++;
+
+ delete[] x;
+ delete[] y;
+ delete[] onCurve;
+
+ x = totX, y = totY, onCurve = totOnCurve;
+}
+
+
+void GlyphPoints::InsertPoint(uint16 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)
+{
+ // Adjust polygon ends appropriately
+ uint16 poly = GetPoly(pt);
+
+ for(int i=poly; i<numPolys; i++)
+ polyEnd[i]--;
+
+//Need to check here if we're deleting the last point in the glyph or not.
+//!!! FIX !!! [DONE]
+ if (GetNumPoints(poly) == 0 && numPoints > 0)
+ {
+ numPolys--;
+
+ for(int i=poly; i<numPolys; i++)
+ polyEnd[i] = polyEnd[i + 1];
+ }
+
+//This causes a crash becuz GetPoly() uses numPoints... !!! FIX !!! [DONE by switching poly delete & point delete]
+ // Close up the gap left by the current point
+ numPoints--;
+
+ for(int i=pt; i<numPoints; i++)
+ x[i] = x[i + 1], y[i] = y[i + 1], onCurve[i] = onCurve[i + 1];
+}
+
+
+uint16 GlyphPoints::GetNumPoints(void)
+{
+ return numPoints;
+}
+
+
+uint16 GlyphPoints::GetNumPoints(uint16 poly)
+{
+ if (poly >= numPolys)
+#ifdef DEBUG
+{
+WriteLogMsg("Exception: GetNumPoints(uint16). poly=%u, numPolys=%u\xD\xA", poly, numPolys);
+#endif
+ throw GP_OUT_OF_RANGE;
+#ifdef DEBUG
+}
+#endif
+
+ return polyEnd[poly] - (poly == 0 ? -1 : polyEnd[poly - 1]);
+}
+
+
+uint16 GlyphPoints::GetNumPolys(void)
+{
+ return numPolys;
+}
+
+
+int GlyphPoints::GetX(uint16 pt)
+{
+ if (pt >= numPoints)
+#ifdef DEBUG
+{
+WriteLogMsg("Exception: GetX(uint16). pt=%u, numPoints=%u\xD\xA", pt, numPoints);
+#endif
+ throw GP_OUT_OF_RANGE;
+#ifdef DEBUG
+}
+#endif
+
+ return x[pt];
+}
+
+
+int GlyphPoints::GetY(uint16 pt)
+{
+ if (pt >= numPoints)
+#ifdef DEBUG
+{
+WriteLogMsg("Exception: GetY(uint16). pt=%u, numPoints=%u\xD\xA", pt, numPoints);
+#endif
+ throw GP_OUT_OF_RANGE;
+#ifdef DEBUG
+}
+#endif
+
+ return y[pt];
+}
+
+
+bool GlyphPoints::GetOnCurve(uint16 pt)
+{
+ if (pt >= numPoints)
+#ifdef DEBUG
+{
+WriteLogMsg("Exception: GetOnCurve(uint16). pt=%u, numPoints=%u\xD\xA", pt, numPoints);
+#endif
+ throw GP_OUT_OF_RANGE;
+#ifdef DEBUG
+}
+#endif
+
+ return onCurve[pt];
+}
+
+
+int GlyphPoints::GetX(uint16 poly, uint16 pt)
+{
+ if (pt >= GetNumPoints(poly))
+#ifdef DEBUG
+{
+WriteLogMsg("Exception: GetX(uint16, uint16). poly= %u, pt=%u, numPoints=%u\xD\xA", poly, pt, numPoints);
+#endif
+ throw GP_OUT_OF_RANGE;
+#ifdef DEBUG
+}
+#endif
+
+ return x[pt + (poly == 0 ? 0 : polyEnd[poly - 1] + 1)];
+}
+
+
+int GlyphPoints::GetNextX(uint16 poly, uint16 pt)
+{
+ return GetX(poly, GetNext(poly, pt));
+}
+
+
+int GlyphPoints::GetY(uint16 poly, uint16 pt)
+{
+ if (pt >= GetNumPoints(poly))
+#ifdef DEBUG
+{
+WriteLogMsg("Exception: GetY(uint16, uint16). poly= %u, pt=%u, numPoints=%u\xD\xA", poly, pt, numPoints);
+#endif
+ throw GP_OUT_OF_RANGE;
+#ifdef DEBUG
+}
+#endif
+
+ return y[pt + (poly == 0 ? 0 : polyEnd[poly - 1] + 1)];
+}
+
+
+int GlyphPoints::GetNextY(uint16 poly, uint16 pt)
+{
+ return GetY(poly, GetNext(poly, pt));
+}
+
+
+IPoint GlyphPoints::GetPoint(uint16 poly, uint16 pt)
+{
+ return IPoint(GetX(poly, pt), GetY(poly, pt));
+}
+
+
+IPoint GlyphPoints::GetPoint(uint16 pointNumber)
+{
+ if (pointNumber > numPoints)
+ throw GP_OUT_OF_RANGE;
+
+ return IPoint(x[pointNumber], y[pointNumber]);
+}
+
+
+bool GlyphPoints::GetOnCurve(uint16 poly, uint16 pt)
+{
+ if (pt >= GetNumPoints(poly))
+#ifdef DEBUG
+{
+WriteLogMsg("Exception: GetOnCurve(uint16, uint16). poly= %u, pt=%u, numPoints=%u\xD\xA", poly, pt, numPoints);
+#endif
+ throw GP_OUT_OF_RANGE;
+#ifdef DEBUG
+}
+#endif
+
+ return onCurve[pt + (poly == 0 ? 0 : polyEnd[poly - 1] + 1)];
+}
+
+
+bool GlyphPoints::GetPrevOnCurve(uint16 poly, uint16 pt)
+{
+ return GetOnCurve(poly, GetPrev(poly, pt));
+}
+
+
+bool GlyphPoints::GetNextOnCurve(uint16 poly, uint16 pt)
+{
+ return GetOnCurve(poly, GetNext(poly, pt));
+}
+
+
+uint16 GlyphPoints::GetPolyStart(uint16 poly)
+{
+ if (poly >= numPolys)
+#ifdef DEBUG
+{
+WriteLogMsg("Exception: GetPolyEnd(uint16). 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 GlyphPoints::GetPolyEnd(uint16 poly)
+{
+ if (poly >= numPolys)
+#ifdef DEBUG
+{
+WriteLogMsg("Exception: GetPolyEnd(uint16). poly=%u, numPolys=%u\xD\xA", poly, numPolys);
+#endif
+ throw GP_OUT_OF_RANGE;
+#ifdef DEBUG
+}
+#endif
+
+ 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)
+{
+ if (poly >= numPolys)
+#ifdef DEBUG
+{
+WriteLogMsg("Exception: GetPolyEnd(uint16). 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);
+
+ 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++)
+ x[i] = (int)(((float)x[i] * sc) + 0.5f),
+ y[i] = (int)(((float)y[i] * sc) + 0.5f);
+}
+
+
+void GlyphPoints::SetXY(uint16 pt, int xx, int yy)
+{
+ if (pt >= numPoints)
+#ifdef DEBUG
+{
+WriteLogMsg("Exception: SetXY(uint16, int, int). pt=%u, numPoints=%u\xD\xA", pt, numPoints);
+#endif
+ throw GP_OUT_OF_RANGE;
+#ifdef DEBUG
+}
+#endif
+
+ x[pt] = xx, y[pt] = yy;
+}
+
+
+void GlyphPoints::SetOnCurve(uint16 pt, bool oc)
+{
+ if (pt >= numPoints)
+#ifdef DEBUG
+{
+WriteLogMsg("Exception: SetOnCurve(uint16, bool). pt=%u, numPoints=%u\xD\xA", pt, numPoints);
+#endif
+ throw GP_OUT_OF_RANGE;
+#ifdef DEBUG
+}
+#endif
+
+ onCurve[pt] = oc;
+}
+
+
+uint16 GlyphPoints::GetPrev(uint16 pt)
+{
+// pt = 7, polyEnd = 4, 9, 15
+ uint16 min = 0, max = numPoints - 1;
+
+ for(int i=0; i<numPolys; i++)
+ {
+ if (pt <= polyEnd[i])
+ {
+ if (i > 0)
+ min = polyEnd[i - 1] + 1;
+
+ max = polyEnd[i];
+ break;
+ }
+ }
+
+ uint16 retVal = pt - 1;
+
+ if (pt == min)
+ retVal = max;
+
+ return retVal;
+}
+
+
+uint16 GlyphPoints::GetNext(uint16 pt)
+{
+ uint16 min = 0, max = numPoints - 1;
+
+ for(int i=0; i<numPolys; i++)
+ {
+ if (pt <= polyEnd[i])
+ {
+ if (i > 0)
+ min = polyEnd[i - 1] + 1;
+
+ max = polyEnd[i];
+ break;
+ }
+ }
+
+ uint16 retVal = pt + 1;
+
+ if (pt == max)
+ retVal = min;
+
+ 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)
+{
+ 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)
+{
+ return (pt == GetNumPoints(poly) - 1 ? 0 : pt + 1);
+}
+
+
+#warning "!!! This function returns incorrect results !!!"
+uint16 GlyphPoints::GetPoly(uint16 pt)
+{
+ if (pt >= numPoints)
+#ifdef DEBUG
+{
+WriteLogMsg("Exception: GetPoly(uint16). pt=%u, numPoints=%u\xD\xA", pt, numPoints);
+#endif
+ throw GP_OUT_OF_RANGE;
+#ifdef DEBUG
+}
+#endif
+
+ for(int i=0; i<numPolys; i++)
+ if (pt <= polyEnd[i])
+ return i;
+
+ return (uint16)-1;
+}
+
+
+void GlyphPoints::AddNewPolyAtEnd(void)
+{
+ if (numPoints == 0) // By default, we already *have* a poly
+ return;
+
+ uint16 * newPolyEnd = new uint16[numPolys + 1];
+
+ for(uint16 i=0; i<numPolys; i++)
+ newPolyEnd[i] = polyEnd[i];
+
+ newPolyEnd[numPolys] = newPolyEnd[numPolys - 1];
+ numPolys++;
+ delete[] polyEnd;
+ polyEnd = newPolyEnd;
+}
+
+
+IPoint GlyphPoints::GetMidpointToPrev(uint16 poly, uint16 pt)
+{
+ uint16 prev = GetPrev(poly, pt);
+
+ int32 x1 = GetX(poly, pt), y1 = GetY(poly, pt);
+ int32 x2 = GetX(poly, prev), y2 = GetY(poly, prev);
+
+ return IPoint((x1 + x2) / 2.0f, (y1 + y2) / 2.0f);
+}
+
+
+IPoint GlyphPoints::GetMidpointToNext(uint16 poly, uint16 pt)
+{
+ uint16 next = GetNext(poly, pt);
+
+ int32 x1 = GetX(poly, pt), y1 = GetY(poly, pt);
+ int32 x2 = GetX(poly, next), y2 = GetY(poly, next);
+
+ return IPoint((x1 + x2) / 2.0f, (y1 + y2) / 2.0f);
+}
+
+
+IPoint GlyphPoints::GetPrevPoint(uint16 poly, uint16 pt)
+{
+ uint16 prevPt = GetPrev(poly, pt);
+
+ return IPoint(GetX(poly, prevPt), GetY(poly, prevPt));
+}
+
+
+IPoint GlyphPoints::GetNextPoint(uint16 poly, uint16 pt)
+{
+ uint16 nextPt = GetNext(poly, pt);
+
+ return IPoint(GetX(poly, nextPt), GetY(poly, nextPt));
+}
+
+
+uint16 GlyphPoints::GetPolyForPoint(IPoint point)
+{
+ uint16 poly = 0;
+
+ for(uint16 i=0; i<numPoints; i++)
+ {
+ if (i > polyEnd[poly])
+ poly++;
+
+ if (IPoint(x[i], y[i]) == point)
+ return poly;
+ }
+
+ return 0xFFFF;
+}
+
+
+uint16 GlyphPoints::GetPolyForPointNumber(uint16 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 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 poly)
+{
+ // We should throw an exception here, but meh
+ // (this actually short circuits the exception handling in all the GetPolyXXX() functions)
+ if (poly >= numPolys)
+ return IPoint(0, 0);
+
+// if (poly >= numPolys)
+//#ifdef DEBUG
+//{
+//WriteLogMsg("Exception: GetPolyEnd(uint16). poly=%u, numPolys=%u\xD\xA", poly, numPolys);
+//#endif
+// throw GP_OUT_OF_RANGE;
+//#ifdef DEBUG
+//}
+//#endif
+
+ IPoint centroid; // Initializes to (0, 0)
+ uint16 numPointsInPoly = GetNumPoints(poly);
+
+ for(uint16 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 poly, const double angle)
+{
+ if (poly >= numPolys)
+ return;
+
+ IPoint centroid = GetPolyCentroid(poly);
+
+ for(uint16 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;
+ }
+}
+
+
+// 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], &line);
+ onCurve[i] = (line[0] == 'T' ? true : false);
+ }
+
+ fscanf(file, "%s %u", line, &numPolys);
+ polyEnd = new uint16[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;
+}
+