#ifdef DEBUG
#include "debug.h"
#endif
+#include <math.h>
+
/*GlyphPoints::GlyphPoints(void)
{
#endif
}
+
GlyphPoints::GlyphPoints(int xx, int yy, bool oc)
{
//Hmm. What to do with this...?
#endif
}
+
// Copy constructor (needed for deep copying)
//GlyphPoints::GlyphPoints(GlyphPoints &c): x(NULL), y(NULL), onCurve(NULL), polyEnd(NULL)
#endif
}
+
GlyphPoints::~GlyphPoints()
{
+ FreeAllocatedMemory();
+#if 0
if (x)
delete[] x;
if (polyEnd)
delete[] polyEnd;
+#endif
}
+
void GlyphPoints::AllocateAndCopy(int nPts, int nPlys, int * xa, int * ya, bool * oca, uint16 * pa)
{
numPoints = nPts, numPolys = nPlys;
}
}
+
+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
+#if 0
if (x)
delete[] x;
if (polyEnd)
delete[] polyEnd;
-
+#endif
+ 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)
return retVal;
}
+
// Add a point to this GlyphPoints...
GlyphPoints GlyphPoints::operator+(const IPoint &c)
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...!
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
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)
return polyEnd[poly] - (poly == 0 ? -1 : polyEnd[poly - 1]);
}
+
uint16 GlyphPoints::GetNumPolys(void)
{
return numPolys;
}
+
int GlyphPoints::GetX(uint16 pt)
{
if (pt >= numPoints)
return x[pt];
}
+
int GlyphPoints::GetY(uint16 pt)
{
if (pt >= numPoints)
return y[pt];
}
+
bool GlyphPoints::GetOnCurve(uint16 pt)
{
if (pt >= numPoints)
return onCurve[pt];
}
+
int GlyphPoints::GetX(uint16 poly, uint16 pt)
{
if (pt >= GetNumPoints(poly))
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))
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));
}
+
bool GlyphPoints::GetOnCurve(uint16 poly, uint16 pt)
{
if (pt >= GetNumPoints(poly))
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)
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
//
x[polyStart + i] += xOff, y[polyStart + i] += yOff;
}
+
void GlyphPoints::ScalePoints(float sc)
{
for(int i=0; i<numPoints; i++)
y[i] = (int)(((float)y[i] * sc) + 0.5f);
}
+
void GlyphPoints::SetXY(uint16 pt, int xx, int yy)
{
if (pt >= numPoints)
x[pt] = xx, y[pt] = yy;
}
+
void GlyphPoints::SetOnCurve(uint16 pt, bool oc)
{
if (pt >= numPoints)
onCurve[pt] = oc;
}
+
uint16 GlyphPoints::GetPrev(uint16 pt)
{
// pt = 7, polyEnd = 4, 9, 15
return retVal;
}
+
uint16 GlyphPoints::GetNext(uint16 pt)
{
uint16 min = 0, max = numPoints - 1;
return retVal;
}
+
//
// Get previous point for this polygon using wraparound.
// Note that pt is a zero-based index!
return (pt == 0 ? GetNumPoints(poly) - 1 : pt - 1);
}
+
//
// Get next point for this polygon using wraparound.
// Note that pt is a zero-based index!
return (pt == GetNumPoints(poly) - 1 ? 0 : pt + 1);
}
+
uint16 GlyphPoints::GetPoly(uint16 pt)
{
if (pt >= numPoints)
return (uint16)-1;
}
+
void GlyphPoints::AddNewPolyAtEnd(void)
{
if (numPoints == 0) // By default, we already *have* a poly
polyEnd = newPolyEnd;
}
+
IPoint GlyphPoints::GetMidpointToPrev(uint16 poly, uint16 pt)
{
uint16 prev = GetPrev(poly, pt);
return IPoint((x1 + x2) / 2.0f, (y1 + y2) / 2.0f);
}
+
IPoint GlyphPoints::GetMidpointToNext(uint16 poly, uint16 pt)
{
uint16 next = GetNext(poly, pt);
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));
}
+
+
+//
+// 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;
+}
+