123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458 |
- #include <precomp.h>
- #include "drawpoly.h"
- #include <bfc/parse/pathparse.h>
- #define MAXPOINTS 32
- static ARGB32 *bits, color;
- static int w, h, across;
- struct Point2d {
- int X, Y;
- };
- typedef struct Point2d Point2d;
- static Point2d points[MAXPOINTS];
- static int npoints;
- void Draw::beginPolygon(ARGB32 *bits, int w, int h, ARGB32 color) {
- ::bits = bits;
- ::w = w;
- ::h = h;
- ::color = color;
- ::across = w;
- npoints = 0;
- }
- void Draw::addPoint(int x, int y) {
- if (npoints >= MAXPOINTS) return;
- points[npoints].X = x;
- points[npoints].Y = y;
- npoints++;
- }
- static void premultiply(ARGB32 *m_pBits, int nwords) {
- for (; nwords > 0; nwords--, m_pBits++) {
- unsigned __int8 *pixel = (unsigned __int8 *)m_pBits;
- unsigned int alpha = pixel[3];
- if (alpha == 255) continue;
- pixel[0] = (pixel[0] * alpha) >> 8;
- pixel[1] = (pixel[1] * alpha) >> 8;
- pixel[2] = (pixel[2] * alpha) >> 8;
- }
- }
- void Draw::drawPointList(ARGB32 *bits, int w, int h, const wchar_t *pointlist) {
- if (pointlist == NULL || *pointlist == '\0') return;
- PathParserW outer(pointlist, L"|");
- const wchar_t *pl;
- for (int i = 0; (pl = outer.enumString(i)) != NULL; i++)
- {
- PathParserW inner(pl, L"=");
- ARGB32 color = WASABI_API_SKIN->parse(inner.enumStringSafe(1, L"255,255,255,255"), L"coloralpha");
- int a = color & 0xff000000;
- color = _byteswap_ulong(color<<8) | a;
- premultiply(&color, 1);
- beginPolygon(bits, w, h, color);
- PathParserW eener(inner.enumStringSafe(0, L"0,0"), L";");
- const wchar_t *cc;
- for (int j = 0; (cc = eener.enumString(j)) != NULL; j++) {
- PathParserW com(cc, L",");
- const wchar_t *xs = com.enumStringSafe(0, L"0");
- int x = wcschr(xs, '.') ? (int)floor(WTOF(xs) * w + .5f) : WTOI(xs);
- const wchar_t *ys = com.enumStringSafe(1, L"0");
- int y = wcschr(ys, '.') ? (int)floor(WTOF(ys) * h + .5f) : WTOI(ys);
- addPoint(x, y);
- }
- endPolygon();
- }
- }
- #define PIXEL ARGB32
- typedef struct {
- int X, Y;
- } Point2dC;
- struct Point2dListHeader {
- int Length;
- struct Point2d *Point2dPtr;
- };
- typedef struct Point2dListHeader Point2dListHeader;
- struct HLine {
- int XStart;
- int XEnd;
- };
- typedef struct {
- int XStart, XEnd;
- } HLineColor;
- struct HLineList {
- int Length;
- int YStart;
- struct HLine * HLinePtr;
- };
- static void DrawHorizontalLineList(struct HLineList * HLineListPtr, PIXEL *dest,
- PIXEL Color) {
- struct HLine *HLinePtr, *ptr;
- int Length, Width, c;
- PIXEL *ScreenPtr;
-
- ScreenPtr = dest + HLineListPtr->YStart * across;
- Length = HLineListPtr->Length;
-
- HLinePtr = HLineListPtr->HLinePtr;
-
- for (ptr = HLinePtr, c = Length; c; c--) {
- if (ptr->XStart < 0) ptr->XStart = 0;
- if (ptr->XEnd >= w) ptr->XEnd = w - 1;
- ptr++;
- }
-
- if (HLineListPtr->YStart < 0) {
- int skip = -HLineListPtr->YStart;
- HLineListPtr->YStart = 0;
- ScreenPtr += across * skip;
- Length -= skip;
- HLinePtr += skip;
- }
-
- if (HLineListPtr->YStart + Length > h) {
- Length -= (HLineListPtr->YStart + Length) - h;
- }
-
- while (Length-- > 0) {
-
- if ((Width = HLinePtr->XEnd - HLinePtr->XStart + 1) > 0)
- MEMFILL<PIXEL>(ScreenPtr+HLinePtr->XStart, Color, Width);
- HLinePtr++;
- ScreenPtr += across;
- }
- }
- static void ScanEdge(int X1, int Y1, int X2, int Y2, int SetXStart,
- int SkipFirst, struct HLine **EdgePoint2dPtr) {
- int DeltaX, Height, Width, AdvanceAmt, ErrorTerm, i;
- int ErrorTermAdvance, XMajorAdvanceAmt;
- struct HLine *WorkingEdgePoint2dPtr;
- WorkingEdgePoint2dPtr = *EdgePoint2dPtr;
- AdvanceAmt = ((DeltaX = X2 - X1) > 0) ? 1 : -1;
-
- if ((Height = Y2 - Y1) <= 0)
- return;
-
- if ((Width = abs(DeltaX)) == 0) {
-
-
- for (i = Height - SkipFirst; i-- > 0; WorkingEdgePoint2dPtr++) {
-
- if (SetXStart == 1)
- WorkingEdgePoint2dPtr->XStart = X1;
- else
- WorkingEdgePoint2dPtr->XEnd = X1;
- }
- } else if (Width == Height) {
-
- if (SkipFirst)
- X1 += AdvanceAmt;
-
- for (i = Height - SkipFirst; i-- > 0; WorkingEdgePoint2dPtr++) {
-
- if (SetXStart == 1)
- WorkingEdgePoint2dPtr->XStart = X1;
- else
- WorkingEdgePoint2dPtr->XEnd = X1;
- X1 += AdvanceAmt;
- }
- } else if (Height > Width) {
-
- if (DeltaX >= 0)
- ErrorTerm = 0;
- else
- ErrorTerm = -Height + 1;
- if (SkipFirst) {
-
- if ((ErrorTerm += Width) > 0) {
- X1 += AdvanceAmt;
- ErrorTerm -= Height;
- }
- }
-
- for (i = Height - SkipFirst; i-- > 0; WorkingEdgePoint2dPtr++) {
-
- if (SetXStart == 1)
- WorkingEdgePoint2dPtr->XStart = X1;
- else
- WorkingEdgePoint2dPtr->XEnd = X1;
-
- if ((ErrorTerm += Width) > 0) {
- X1 += AdvanceAmt;
- ErrorTerm -= Height;
- }
- }
- } else {
-
-
- XMajorAdvanceAmt = (Width / Height) * AdvanceAmt;
-
- ErrorTermAdvance = Width % Height;
- if (DeltaX >= 0)
- ErrorTerm = 0;
- else
- ErrorTerm = -Height + 1;
- if (SkipFirst) {
- X1 += XMajorAdvanceAmt;
-
- if ((ErrorTerm += ErrorTermAdvance) > 0) {
- X1 += AdvanceAmt;
- ErrorTerm -= Height;
- }
- }
-
- for (i = Height - SkipFirst; i-- > 0; WorkingEdgePoint2dPtr++) {
-
- if (SetXStart == 1)
- WorkingEdgePoint2dPtr->XStart = X1;
- else
- WorkingEdgePoint2dPtr->XEnd = X1;
- X1 += XMajorAdvanceAmt;
-
- if ((ErrorTerm += ErrorTermAdvance) > 0) {
- X1 += AdvanceAmt;
- ErrorTerm -= Height;
- }
- }
- }
- *EdgePoint2dPtr = WorkingEdgePoint2dPtr;
- }
- #define INDEX_FORWARD(Index) \
- Index = (Index + 1) % VertexList->Length;
- #define INDEX_BACKWARD(Index) \
- Index = (Index - 1 + VertexList->Length) % VertexList->Length;
- #define INDEX_MOVE(Index,Direction) \
- if (Direction > 0) \
- Index = (Index + 1) % VertexList->Length; \
- else \
- Index = (Index - 1 + VertexList->Length) % VertexList->Length;
- int FillConvexPolygon(struct Point2dListHeader *VertexList, PIXEL *dest,
- PIXEL Color) {
- int i, MinIndexL, MaxIndex, MinIndexR, SkipFirst, Temp;
- int MinPoint2d_Y, MaxPoint2d_Y, TopIsFlat, LeftEdgeDir;
- int NextIndex, CurrentIndex, PreviousIndex;
- int DeltaXN, DeltaYN, DeltaXP, DeltaYP;
- struct HLineList WorkingHLineList;
- struct HLine *EdgePoint2dPtr;
- struct Point2d *VertexPtr;
-
- VertexPtr = VertexList->Point2dPtr;
-
- if (VertexList->Length == 0)
- return(1);
- MaxPoint2d_Y = MinPoint2d_Y = VertexPtr[MinIndexL = MaxIndex = 0].Y;
- for (i = 1; i < VertexList->Length; i++) {
- if (VertexPtr[i].Y < MinPoint2d_Y)
- MinPoint2d_Y = VertexPtr[MinIndexL = i].Y;
- else if (VertexPtr[i].Y > MaxPoint2d_Y)
- MaxPoint2d_Y = VertexPtr[MaxIndex = i].Y;
- }
- if (MinPoint2d_Y == MaxPoint2d_Y)
- return(1);
-
- MinIndexR = MinIndexL;
- while (VertexPtr[MinIndexR].Y == MinPoint2d_Y)
- INDEX_FORWARD(MinIndexR);
- INDEX_BACKWARD(MinIndexR);
-
- while (VertexPtr[MinIndexL].Y == MinPoint2d_Y)
- INDEX_BACKWARD(MinIndexL);
- INDEX_FORWARD(MinIndexL);
-
- LeftEdgeDir = -1;
- if ((TopIsFlat = (VertexPtr[MinIndexL].X !=
- VertexPtr[MinIndexR].X) ? 1 : 0) == 1) {
-
- if (VertexPtr[MinIndexL].X > VertexPtr[MinIndexR].X) {
- LeftEdgeDir = 1;
- Temp = MinIndexL;
- MinIndexL = MinIndexR;
- MinIndexR = Temp;
- }
- } else {
-
- NextIndex = MinIndexR;
- INDEX_FORWARD(NextIndex);
- PreviousIndex = MinIndexL;
- INDEX_BACKWARD(PreviousIndex);
-
- DeltaXN = VertexPtr[NextIndex].X - VertexPtr[MinIndexL].X;
- DeltaYN = VertexPtr[NextIndex].Y - VertexPtr[MinIndexL].Y;
- DeltaXP = VertexPtr[PreviousIndex].X - VertexPtr[MinIndexL].X;
- DeltaYP = VertexPtr[PreviousIndex].Y - VertexPtr[MinIndexL].Y;
- if (((long)DeltaXN * DeltaYP - (long)DeltaYN * DeltaXP) < 0L) {
- LeftEdgeDir = 1;
- Temp = MinIndexL;
- MinIndexL = MinIndexR;
- MinIndexR = Temp;
- }
- }
-
- if ((WorkingHLineList.Length =
- MaxPoint2d_Y - MinPoint2d_Y - 1 + TopIsFlat) <= 0)
- return(1);
-
- WorkingHLineList.YStart = MinPoint2d_Y + 1 - TopIsFlat;
-
- if ((WorkingHLineList.HLinePtr =
- (struct HLine *) (malloc(sizeof(struct HLine) *
- WorkingHLineList.Length))) == NULL)
- return(0);
-
-
- EdgePoint2dPtr = WorkingHLineList.HLinePtr;
-
- PreviousIndex = CurrentIndex = MinIndexL;
-
- SkipFirst = TopIsFlat ? 0 : 1;
-
- do {
- INDEX_MOVE(CurrentIndex,LeftEdgeDir);
- ScanEdge(VertexPtr[PreviousIndex].X,
- VertexPtr[PreviousIndex].Y,
- VertexPtr[CurrentIndex].X,
- VertexPtr[CurrentIndex].Y, 1, SkipFirst, &EdgePoint2dPtr);
- PreviousIndex = CurrentIndex;
- SkipFirst = 0;
- } while (CurrentIndex != MaxIndex);
-
- EdgePoint2dPtr = WorkingHLineList.HLinePtr;
- PreviousIndex = CurrentIndex = MinIndexR;
- SkipFirst = TopIsFlat ? 0 : 1;
-
- do {
- INDEX_MOVE(CurrentIndex,-LeftEdgeDir);
-
- ScanEdge(VertexPtr[PreviousIndex].X - 1,
- VertexPtr[PreviousIndex].Y,
-
- VertexPtr[CurrentIndex].X - 1,
- VertexPtr[CurrentIndex].Y, 0, SkipFirst, &EdgePoint2dPtr);
- PreviousIndex = CurrentIndex;
- SkipFirst = 0;
- } while (CurrentIndex != MaxIndex);
-
-
- DrawHorizontalLineList(&WorkingHLineList, dest, Color);
-
- free(WorkingHLineList.HLinePtr);
- return(1);
- }
- void Draw::endPolygon() {
- if (npoints == 0) return;
- struct Point2dListHeader head;
- head.Length = npoints;
- head.Point2dPtr = &points[0];
- FillConvexPolygon(&head, bits, color);
- }
|