4 // Class implementation. Nothing too inexplicable going on here. Fairly
\r
5 // straightforward stuff.
\r
7 // by James L. Hammons
\r
8 // (C) 2004 Underground Software
\r
10 // JLH = James L. Hammons <jlhamm@acm.org>
\r
13 // --- ---------- ------------------------------------------------------------
\r
14 // JLH ??/??/200? Created this file
\r
15 // JLH 05/18/2004 Added pure point adding, inserting, better polygon handling
\r
18 // Uncomment this for debugging...
\r
21 #include "glyphpoints.h"
\r
26 /*GlyphPoints::GlyphPoints(void)
\r
28 GlyphPoints(0, 0, NULL, NULL, NULL, NULL);
\r
31 GlyphPoints::GlyphPoints(int nPts/*=0*/, int nPlys/*=0*/, int * xa/*=null*/, int * ya/*=null*/,
\r
32 bool * oca/*=null*/, uint16 * pa/*=null*/): x(NULL), y(NULL), onCurve(NULL), polyEnd(NULL)
\r
33 //GlyphPoints::GlyphPoints(int nPts, int nPlys/*=0*/, int * xa/*=null*/, int * ya/*=null*/,
\r
34 // bool * oca/*=null*/, uint16 * pa/*=null*/): x(NULL), y(NULL), onCurve(NULL), polyEnd(NULL)
\r
36 AllocateAndCopy(nPts, nPlys, xa, ya, oca, pa);
\r
41 polyEnd = new uint16[numPolys];
\r
42 polyEnd[0] = numPoints - 1;
\r
45 WriteLogMsg("GlyphPoints: Default constructor. %u points, %u polys.\n", numPoints, numPolys);
\r
49 GlyphPoints::GlyphPoints(int xx, int yy, bool oc)
\r
51 //Hmm. What to do with this...?
\r
52 AllocateAndCopy(1, 0, &xx, &yy, &oc, NULL);
\r
54 WriteLogMsg("GlyphPoints: Single point constructor. %u points, %u polys.\n", numPoints, numPolys);
\r
58 // Copy constructor (needed for deep copying)
\r
60 //GlyphPoints::GlyphPoints(GlyphPoints &c): x(NULL), y(NULL), onCurve(NULL), polyEnd(NULL)
\r
61 GlyphPoints::GlyphPoints(const GlyphPoints &c): x(NULL), y(NULL), onCurve(NULL), polyEnd(NULL)
\r
63 *this = c; // Use overloaded operator=
\r
65 WriteLogMsg("GlyphPoints: Copy constructor. %u points, %u polys.\n", numPoints, numPolys);
\r
69 GlyphPoints::~GlyphPoints()
\r
84 void GlyphPoints::AllocateAndCopy(int nPts, int nPlys, int * xa, int * ya, bool * oca, uint16 * pa)
\r
86 numPoints = nPts, numPolys = nPlys;
\r
90 x = new int[numPoints];
\r
91 y = new int[numPoints];
\r
92 onCurve = new bool[numPoints];
\r
94 if (xa) // Copy points in if they're passed in...
\r
95 for(int i=0; i<nPts; i++)
\r
99 for(int i=0; i<nPts; i++)
\r
103 for(int i=0; i<nPts; i++)
\r
104 onCurve[i] = oca[i];
\r
109 polyEnd = new uint16[numPolys];
\r
111 if (pa) // Copy poly ends in if they're passed in...
\r
112 for(int i=0; i<nPlys; i++)
\r
113 polyEnd[i] = pa[i];
\r
117 GlyphPoints& GlyphPoints::operator=(const GlyphPoints &c)
\r
120 return *this; // Take care of self-assignment
\r
134 AllocateAndCopy(c.numPoints, c.numPolys, c.x, c.y, c.onCurve, c.polyEnd);
\r
139 // Add another GlyphPoints' points to this one...
\r
141 GlyphPoints GlyphPoints::operator+(const GlyphPoints &c)
\r
143 int totPoints = numPoints + c.numPoints, totPolys = numPolys + c.numPolys;
\r
145 int * totX = new int[totPoints];
\r
146 int * totY = new int[totPoints];
\r
147 bool * totOnCurve = new bool[totPoints];
\r
148 uint16 * totPolyEnd = new uint16[totPolys];
\r
150 for(int i=0; i<numPoints; i++)
\r
154 totOnCurve[i] = onCurve[i];
\r
157 for(int i=0; i<numPolys; i++)
\r
158 totPolyEnd[i] = polyEnd[i];
\r
160 for(int i=0; i<c.numPoints; i++)
\r
162 totX[numPoints+i] = c.x[i];
\r
163 totY[numPoints+i] = c.y[i];
\r
164 totOnCurve[numPoints+i] = c.onCurve[i];
\r
167 for(int i=0; i<c.numPolys; i++)
\r
168 totPolyEnd[numPolys+i] = numPoints + c.polyEnd[i]; // Need to adjust the "added in"
\r
169 // poly's end points...
\r
171 GlyphPoints retVal(totPoints, totPolys, totX, totY, totOnCurve, totPolyEnd);
\r
174 delete[] totOnCurve;
\r
175 delete[] totPolyEnd;
\r
180 // Add a point to this GlyphPoints...
\r
182 GlyphPoints GlyphPoints::operator+(const IPoint &c)
\r
184 //This is kinda silly. We can do better than this! !!! FIX !!!
\r
185 int * totX = new int[numPoints + 1];
\r
186 int * totY = new int[numPoints + 1];
\r
187 bool * totOnCurve = new bool[numPoints + 1];
\r
188 uint16 * totPolyEnd = new uint16[numPolys];
\r
190 for(int i=0; i<numPoints; i++)
\r
191 totX[i] = x[i], totY[i] = y[i], totOnCurve[i] = onCurve[i];
\r
193 totX[numPoints] = c.x, totY[numPoints] = c.y, totOnCurve[numPoints] = c.onCurve;
\r
195 for(int i=0; i<numPolys; i++)
\r
196 totPolyEnd[i] = polyEnd[i];
\r
198 totPolyEnd[numPolys - 1]++; // Bump polygon's end point
\r
199 GlyphPoints retVal(numPoints + 1, numPolys, totX, totY, totOnCurve, totPolyEnd);
\r
203 delete[] totOnCurve;
\r
208 GlyphPoints& GlyphPoints::operator+=(const IPoint &p)
\r
210 InsertPoint(numPoints, p.x, p.y, p.onCurve);
\r
215 void GlyphPoints::InsertPoint(uint16 pt, int xx, int yy, bool oc)
\r
217 if (pt > numPoints) // > because we can insert at end...!
\r
218 throw GP_OUT_OF_RANGE;
\r
220 //This is kinda silly. We can do better than this! !!! FIX !!!
\r
221 int * totX = new int[numPoints + 1];
\r
222 int * totY = new int[numPoints + 1];
\r
223 bool * totOnCurve = new bool[numPoints + 1];
\r
225 for(int i=0; i<pt; i++)
\r
226 totX[i] = x[i], totY[i] = y[i], totOnCurve[i] = onCurve[i];
\r
228 for(int i=pt; i<numPoints; i++)
\r
229 totX[i + 1] = x[i], totY[i + 1] = y[i], totOnCurve[i + 1] = onCurve[i];
\r
231 totX[pt] = xx, totY[pt] = yy, totOnCurve[pt] = oc;
\r
233 //A way to fix the kludge in GetPoly() would be to put a check here to see if
\r
234 //we're adding to the end of the structure: [DONE, below]
\r
235 int polyInsert = (pt == numPoints ? numPolys - 1 : GetPoly(pt));
\r
236 for(int i=polyInsert; i<numPolys; i++)
\r
237 // for(int i=GetPoly(pt); i<numPolys; i++)
\r
238 polyEnd[i]++; // Bump polygons' end point
\r
246 x = totX, y = totY, onCurve = totOnCurve;
\r
249 void GlyphPoints::InsertPoint(uint16 pt, const IPoint &p)
\r
251 InsertPoint(pt, p.x, p.y, p.onCurve);
\r
255 // Delete a point from the glyph
\r
256 // Note that we don't bother to reallocate anything here, just bump the
\r
257 // size counters down as needed. In the future, we'll keep track so we
\r
258 // don't have to reallocate *every* damn time a point is added...
\r
260 void GlyphPoints::DeletePoint(uint16 pt)
\r
262 // Adjust polygon ends appropriately
\r
263 uint16 poly = GetPoly(pt);
\r
265 for(int i=poly; i<numPolys; i++)
\r
268 //Need to check here if we're deleting the last point in the glyph or not.
\r
269 //!!! FIX !!! [DONE]
\r
270 if (GetNumPoints(poly) == 0 && numPoints > 0)
\r
274 for(int i=poly; i<numPolys; i++)
\r
275 polyEnd[i] = polyEnd[i + 1];
\r
278 //This causes a crash becuz GetPoly() uses numPoints... !!! FIX !!! [DONE by switching poly delete & point delete]
\r
279 // Close up the gap left by the current point
\r
282 for(int i=pt; i<numPoints; i++)
\r
283 x[i] = x[i + 1], y[i] = y[i + 1], onCurve[i] = onCurve[i + 1];
\r
286 uint16 GlyphPoints::GetNumPoints(void)
\r
291 uint16 GlyphPoints::GetNumPoints(uint16 poly)
\r
293 if (poly >= numPolys)
\r
296 WriteLogMsg("Exception: GetNumPoints(uint16). poly=%u, numPolys=%u\xD\xA", poly, numPolys);
\r
298 throw GP_OUT_OF_RANGE;
\r
303 return polyEnd[poly] - (poly == 0 ? -1 : polyEnd[poly - 1]);
\r
306 uint16 GlyphPoints::GetNumPolys(void)
\r
311 int GlyphPoints::GetX(uint16 pt)
\r
313 if (pt >= numPoints)
\r
316 WriteLogMsg("Exception: GetX(uint16). pt=%u, numPoints=%u\xD\xA", pt, numPoints);
\r
318 throw GP_OUT_OF_RANGE;
\r
326 int GlyphPoints::GetY(uint16 pt)
\r
328 if (pt >= numPoints)
\r
331 WriteLogMsg("Exception: GetY(uint16). pt=%u, numPoints=%u\xD\xA", pt, numPoints);
\r
333 throw GP_OUT_OF_RANGE;
\r
341 bool GlyphPoints::GetOnCurve(uint16 pt)
\r
343 if (pt >= numPoints)
\r
346 WriteLogMsg("Exception: GetOnCurve(uint16). pt=%u, numPoints=%u\xD\xA", pt, numPoints);
\r
348 throw GP_OUT_OF_RANGE;
\r
353 return onCurve[pt];
\r
356 int GlyphPoints::GetX(uint16 poly, uint16 pt)
\r
358 if (pt >= GetNumPoints(poly))
\r
361 WriteLogMsg("Exception: GetX(uint16, uint16). poly= %u, pt=%u, numPoints=%u\xD\xA", poly, pt, numPoints);
\r
363 throw GP_OUT_OF_RANGE;
\r
368 return x[pt + (poly == 0 ? 0 : polyEnd[poly - 1] + 1)];
\r
371 int GlyphPoints::GetY(uint16 poly, uint16 pt)
\r
373 if (pt >= GetNumPoints(poly))
\r
376 WriteLogMsg("Exception: GetY(uint16, uint16). poly= %u, pt=%u, numPoints=%u\xD\xA", poly, pt, numPoints);
\r
378 throw GP_OUT_OF_RANGE;
\r
383 return y[pt + (poly == 0 ? 0 : polyEnd[poly - 1] + 1)];
\r
386 bool GlyphPoints::GetOnCurve(uint16 poly, uint16 pt)
\r
388 if (pt >= GetNumPoints(poly))
\r
391 WriteLogMsg("Exception: GetOnCurve(uint16, uint16). poly= %u, pt=%u, numPoints=%u\xD\xA", poly, pt, numPoints);
\r
393 throw GP_OUT_OF_RANGE;
\r
398 return onCurve[pt + (poly == 0 ? 0 : polyEnd[poly - 1] + 1)];
\r
401 uint16 GlyphPoints::GetPolyEnd(uint16 poly)
\r
403 if (poly >= numPolys)
\r
406 WriteLogMsg("Exception: GetPolyEnd(uint16). poly=%u, numPolys=%u\xD\xA", poly, numPolys);
\r
408 throw GP_OUT_OF_RANGE;
\r
413 return polyEnd[poly];
\r
416 void GlyphPoints::OffsetPoints(int xOff, int yOff)
\r
418 for(int i=0; i<numPoints; i++)
\r
419 x[i] += xOff, y[i] += yOff;
\r
423 // Offset only a specific polygon in the glyph
\r
425 void GlyphPoints::OffsetPoly(uint16 poly, int32 xOff, int32 yOff)
\r
427 if (poly >= numPolys)
\r
430 WriteLogMsg("Exception: GetPolyEnd(uint16). poly=%u, numPolys=%u\xD\xA", poly, numPolys);
\r
432 throw GP_OUT_OF_RANGE;
\r
437 uint16 polyStart = (poly == 0 ? 0 : polyEnd[poly - 1] + 1);
\r
439 for(int i=0; i<GetNumPoints(poly); i++)
\r
440 x[polyStart + i] += xOff, y[polyStart + i] += yOff;
\r
443 void GlyphPoints::ScalePoints(float sc)
\r
445 for(int i=0; i<numPoints; i++)
\r
446 x[i] = (int)(((float)x[i] * sc) + 0.5f),
\r
447 y[i] = (int)(((float)y[i] * sc) + 0.5f);
\r
450 void GlyphPoints::SetXY(uint16 pt, int xx, int yy)
\r
452 if (pt >= numPoints)
\r
455 WriteLogMsg("Exception: SetXY(uint16, int, int). pt=%u, numPoints=%u\xD\xA", pt, numPoints);
\r
457 throw GP_OUT_OF_RANGE;
\r
462 x[pt] = xx, y[pt] = yy;
\r
465 void GlyphPoints::SetOnCurve(uint16 pt, bool oc)
\r
467 if (pt >= numPoints)
\r
470 WriteLogMsg("Exception: SetOnCurve(uint16, bool). pt=%u, numPoints=%u\xD\xA", pt, numPoints);
\r
472 throw GP_OUT_OF_RANGE;
\r
480 uint16 GlyphPoints::GetPrev(uint16 pt)
\r
482 // pt = 7, polyEnd = 4, 9, 15
\r
483 uint16 min = 0, max = numPoints - 1;
\r
485 for(int i=0; i<numPolys; i++)
\r
487 if (pt <= polyEnd[i])
\r
490 min = polyEnd[i - 1] + 1;
\r
497 uint16 retVal = pt - 1;
\r
505 uint16 GlyphPoints::GetNext(uint16 pt)
\r
507 uint16 min = 0, max = numPoints - 1;
\r
509 for(int i=0; i<numPolys; i++)
\r
511 if (pt <= polyEnd[i])
\r
514 min = polyEnd[i - 1] + 1;
\r
521 uint16 retVal = pt + 1;
\r
530 // Get previous point for this polygon using wraparound.
\r
531 // Note that pt is a zero-based index!
\r
533 uint16 GlyphPoints::GetPrev(uint16 poly, uint16 pt)
\r
535 return (pt == 0 ? GetNumPoints(poly) - 1 : pt - 1);
\r
539 // Get next point for this polygon using wraparound.
\r
540 // Note that pt is a zero-based index!
\r
542 uint16 GlyphPoints::GetNext(uint16 poly, uint16 pt)
\r
544 return (pt == GetNumPoints(poly) - 1 ? 0 : pt + 1);
\r
547 uint16 GlyphPoints::GetPoly(uint16 pt)
\r
549 if (pt >= numPoints)
\r
552 WriteLogMsg("Exception: GetPoly(uint16). pt=%u, numPoints=%u\xD\xA", pt, numPoints);
\r
554 throw GP_OUT_OF_RANGE;
\r
559 for(int i=0; i<numPolys; i++)
\r
560 if (pt <= polyEnd[i])
\r
566 void GlyphPoints::AddNewPolyAtEnd(void)
\r
568 if (numPoints == 0) // By default, we already *have* a poly
\r
571 uint16 * newPolyEnd = new uint16[numPolys + 1];
\r
573 for(uint16 i=0; i<numPolys; i++)
\r
574 newPolyEnd[i] = polyEnd[i];
\r
576 newPolyEnd[numPolys] = newPolyEnd[numPolys - 1];
\r
579 polyEnd = newPolyEnd;
\r