diff --git a/src/servers/app/server/BitmapDriver.cpp b/src/servers/app/server/BitmapDriver.cpp index 65074d1465..f82953c007 100644 --- a/src/servers/app/server/BitmapDriver.cpp +++ b/src/servers/app/server/BitmapDriver.cpp @@ -758,7 +758,7 @@ void BitmapDriver::FillPatternRect(const BRect &rect, const DrawData *d) { } -void BitmapDriver::StrokeSolidLine(const BPoint &start, const BPoint &end, const RGBColor &color) +void BitmapDriver::StrokeSolidLine(int32 x1, int32 y1, int32 x2, int32 y2, const RGBColor &color) { } diff --git a/src/servers/app/server/BitmapDriver.h b/src/servers/app/server/BitmapDriver.h index e67d259e65..71f41acdc6 100644 --- a/src/servers/app/server/BitmapDriver.h +++ b/src/servers/app/server/BitmapDriver.h @@ -83,7 +83,7 @@ protected: virtual void Blit(const BRect &src, const BRect &dest, const DrawData *d); virtual void FillSolidRect(const BRect &rect, const RGBColor &color); virtual void FillPatternRect(const BRect &rect, const DrawData *d); - virtual void StrokeSolidLine(const BPoint &start, const BPoint &end, const RGBColor &color); + virtual void StrokeSolidLine(int32 x1, int32 y1, int32 x2, int32 y2, const RGBColor &color); virtual void StrokePatternLine(int32 x1, int32 y1, int32 x2, int32 y2, const DrawData *d); virtual void StrokeSolidRect(const BRect &rect, const RGBColor &color); virtual void CopyBitmap(ServerBitmap *bitmap, const BRect &source, const BRect &dest, const DrawData *d); diff --git a/src/servers/app/server/DirectDriver.cpp b/src/servers/app/server/DirectDriver.cpp index a8530253e6..e666669659 100644 --- a/src/servers/app/server/DirectDriver.cpp +++ b/src/servers/app/server/DirectDriver.cpp @@ -475,14 +475,14 @@ void DirectDriver::StrokeSolidRect(const BRect &rect, const RGBColor &color) Unlock(); } -void DirectDriver::StrokeSolidLine(const BPoint &start, const BPoint &end,const RGBColor &color) +void DirectDriver::StrokeSolidLine(int32 x1, int32 y1, int32 x2, int32 y2, const RGBColor &color) { Lock(); framebuffer->Lock(); drawview->SetHighColor(color.GetColor32()); - drawview->StrokeLine(start,end); + drawview->StrokeLine(BPoint(x1,y1),BPoint(x2,y2)); drawview->Sync(); - screenwin->rectpipe.PutRect(BRect(start,end)); + screenwin->rectpipe.PutRect(BRect(x1,y1,x2,y2)); framebuffer->Unlock(); Unlock(); } diff --git a/src/servers/app/server/DirectDriver.h b/src/servers/app/server/DirectDriver.h index 0137ee822b..3e02f97ab6 100644 --- a/src/servers/app/server/DirectDriver.h +++ b/src/servers/app/server/DirectDriver.h @@ -148,7 +148,7 @@ protected: virtual void FillSolidRect(const BRect &rect, const RGBColor &color); virtual void FillPatternRect(const BRect &rect, const DrawData *d); virtual void StrokeSolidRect(const BRect &rect, const RGBColor &color); - virtual void StrokeSolidLine(const BPoint &start, const BPoint &end,const RGBColor &color); + virtual void StrokeSolidLine(int32 x1, int32 y1, int32 x2, int32 y2, const RGBColor &color); virtual void StrokePatternLine(int32 x1, int32 y1, int32 x2, int32 y2, const DrawData *d); virtual void CopyBitmap(ServerBitmap *bitmap, const BRect &source, const BRect &dest, const DrawData *d); diff --git a/src/servers/app/server/DisplayDriver.cpp b/src/servers/app/server/DisplayDriver.cpp index 9bfe58d071..d94f5f984a 100644 --- a/src/servers/app/server/DisplayDriver.cpp +++ b/src/servers/app/server/DisplayDriver.cpp @@ -38,6 +38,108 @@ // handled by the public drawing functions. // Add clipping and make sure public functions have Lock & Unlock. +class BezierCurve +{ +public: + BezierCurve(BPoint* pts); + ~BezierCurve(); + BPoint* GetPointArray(); + BList points; +private: + int GeneratePoints(int startPos); + BPoint* pointArray; +}; + +BezierCurve::BezierCurve(BPoint* pts) +{ + int i; + + pointArray = NULL; + for (i=0; i<4; i++) + points.AddItem(new BPoint(pts[i])); + GeneratePoints(0); +} + +BezierCurve::~BezierCurve() +{ + int i, numPoints; + + numPoints = points.CountItems(); + for (i=0; ix-pointList[startPos+3]->x) <= 1) && + (fabs(pointList[startPos]->y-pointList[startPos+3]->y) <= 1) ) + return 0; + + if ( (pointList[startPos]->x == pointList[startPos+1]->x) && + (pointList[startPos+1]->x == pointList[startPos+2]->x) && + (pointList[startPos+2]->x == pointList[startPos+3]->x) ) + return 0; + + slopeAB = (pointList[startPos]->y-pointList[startPos+1]->y)/(pointList[startPos]->x-pointList[startPos+1]->x); + slopeBC = (pointList[startPos+1]->y-pointList[startPos+2]->y)/(pointList[startPos+1]->x-pointList[startPos+2]->x); + slopeCD = (pointList[startPos+2]->y-pointList[startPos+3]->y)/(pointList[startPos+2]->x-pointList[startPos+3]->x); + + if ( (slopeAB == slopeBC) && (slopeBC == slopeCD) ) + return 0; + + BPoint *pointAB = new BPoint(); + BPoint pointBC; + BPoint *pointCD = new BPoint(); + BPoint *pointABC = new BPoint(); + BPoint *pointBCD = new BPoint(); + BPoint *curvePoint = new BPoint(); + int lengthIncrement = 3; + + pointAB->x = (pointList[startPos]->x + pointList[startPos+1]->x)/2; + pointAB->y = (pointList[startPos]->y + pointList[startPos+1]->y)/2; + pointBC.x = (pointList[startPos+1]->x + pointList[startPos+2]->x)/2; + pointBC.y = (pointList[startPos+1]->y + pointList[startPos+2]->y)/2; + pointCD->x = (pointList[startPos+2]->x + pointList[startPos+3]->x)/2; + pointCD->y = (pointList[startPos+2]->y + pointList[startPos+3]->y)/2; + pointABC->x = (pointAB->x + pointBC.x)/2; + pointABC->y = (pointAB->y + pointBC.y)/2; + pointBCD->x = (pointCD->x + pointBC.x)/2; + pointBCD->y = (pointCD->y + pointBC.y)/2; + curvePoint->x = (pointABC->x + pointBCD->x)/2; + curvePoint->y = (pointABC->y + pointBCD->y)/2; + delete pointList[startPos+1]; + delete pointList[startPos+2]; + pointList[startPos+1] = pointAB; + pointList[startPos+2] = pointCD; + points.AddItem(pointABC,startPos+2); + points.AddItem(curvePoint,startPos+3); + points.AddItem(pointBCD,startPos+4); + lengthIncrement += GeneratePoints(startPos); + lengthIncrement += GeneratePoints(startPos + lengthIncrement); + return lengthIncrement; +} + struct integer_rect { int32 x; @@ -659,7 +761,7 @@ void DisplayDriver::DrawBitmap(ServerBitmap *bmp, const BRect &src, const BRect /* Lock(); FBBitmap frameBuffer; - FBBitmap *fbmp = &frameBuffer; + //FBBitmap *fbmp = &frameBuffer; if(!AcquireBuffer(&frameBuffer)) { @@ -1203,19 +1305,14 @@ void DisplayDriver::Invalidate(const BRect &r) { } -void DisplayDriver::FillArc(const BRect &r, const float &angle, const float &span, const RGBColor &color) -{ -} - /*! \brief Called for all BView::FillArc calls \param r Rectangle enclosing the entire arc \param angle Starting angle for the arc in degrees \param span Span of the arc in degrees. Ending angle = angle+span. - \param d Object holding the bazillion other options + \param color The color of the arc */ - -void DisplayDriver::FillArc(const BRect &r, const float &angle, const float &span, const DrawData *d) +void DisplayDriver::FillArc(const BRect &r, const float &angle, const float &span, const RGBColor &color) { float xc = (r.left+r.right)/2; float yc = (r.top+r.bottom)/2; @@ -1240,7 +1337,7 @@ void DisplayDriver::FillArc(const BRect &r, const float &angle, const float &spa // Watch out for bozos giving us whacko spans if ( (span >= 360) || (span <= -360) ) { - FillEllipse(r,d); + FillEllipse(r,color); return; } @@ -1291,13 +1388,13 @@ void DisplayDriver::FillArc(const BRect &r, const float &angle, const float &spa } if ( useQuad1 ) - StrokePatternLine(ROUND(xc),ROUND(yc-y),ROUND(xc+x),ROUND(yc-y),d); + StrokeSolidLine(ROUND(xc),ROUND(yc-y),ROUND(xc+x),ROUND(yc-y),color); if ( useQuad2 ) - StrokePatternLine(ROUND(xc),ROUND(yc-y),ROUND(xc-x),ROUND(yc-y),d); + StrokeSolidLine(ROUND(xc),ROUND(yc-y),ROUND(xc-x),ROUND(yc-y),color); if ( useQuad3 ) - StrokePatternLine(ROUND(xc),ROUND(yc+y),ROUND(xc-x),ROUND(yc+y),d); + StrokeSolidLine(ROUND(xc),ROUND(yc+y),ROUND(xc-x),ROUND(yc+y),color); if ( useQuad4 ) - StrokePatternLine(ROUND(xc),ROUND(yc+y),ROUND(xc+x),ROUND(yc+y),d); + StrokeSolidLine(ROUND(xc),ROUND(yc+y),ROUND(xc+x),ROUND(yc+y),color); p = ROUND (Ry2 - (Rx2 * ry) + (.25 * Rx2)); while (px < py) @@ -1314,23 +1411,23 @@ void DisplayDriver::FillArc(const BRect &r, const float &angle, const float &spa } if ( useQuad1 ) - StrokePatternLine(ROUND(xc),ROUND(yc-y),ROUND(xc+x),ROUND(yc-y),d); + StrokeSolidLine(ROUND(xc),ROUND(yc-y),ROUND(xc+x),ROUND(yc-y),color); if ( useQuad2 ) - StrokePatternLine(ROUND(xc),ROUND(yc-y),ROUND(xc-x),ROUND(yc-y),d); + StrokeSolidLine(ROUND(xc),ROUND(yc-y),ROUND(xc-x),ROUND(yc-y),color); if ( useQuad3 ) - StrokePatternLine(ROUND(xc),ROUND(yc+y),ROUND(xc-x),ROUND(yc+y),d); + StrokeSolidLine(ROUND(xc),ROUND(yc+y),ROUND(xc-x),ROUND(yc+y),color); if ( useQuad4 ) - StrokePatternLine(ROUND(xc),ROUND(yc+y),ROUND(xc+x),ROUND(yc+y),d); + StrokeSolidLine(ROUND(xc),ROUND(yc+y),ROUND(xc+x),ROUND(yc+y),color); if ( !shortspan ) { if ( startQuad == 1 ) { if ( x <= startx ) - StrokePatternLine(ROUND(xc),ROUND(yc-y),ROUND(xc+x),ROUND(yc-y),d); + StrokeSolidLine(ROUND(xc),ROUND(yc-y),ROUND(xc+x),ROUND(yc-y),color); else { xclip = ROUND(y*startx/(double)starty); - StrokePatternLine(ROUND(xc),ROUND(yc-y),ROUND(xc+xclip),ROUND(yc-y),d); + StrokeSolidLine(ROUND(xc),ROUND(yc-y),ROUND(xc+xclip),ROUND(yc-y),color); } } else if ( startQuad == 2 ) @@ -1338,17 +1435,17 @@ void DisplayDriver::FillArc(const BRect &r, const float &angle, const float &spa if ( x >= startx ) { xclip = ROUND(y*startx/(double)starty); - StrokePatternLine(ROUND(xc-x),ROUND(yc-y),ROUND(xc-xclip),ROUND(yc-y),d); + StrokeSolidLine(ROUND(xc-x),ROUND(yc-y),ROUND(xc-xclip),ROUND(yc-y),color); } } else if ( startQuad == 3 ) { if ( x <= startx ) - StrokePatternLine(ROUND(xc-x),ROUND(yc+y),ROUND(xc),ROUND(yc+y),d); + StrokeSolidLine(ROUND(xc-x),ROUND(yc+y),ROUND(xc),ROUND(yc+y),color); else { xclip = ROUND(y*startx/(double)starty); - StrokePatternLine(ROUND(xc-xclip),ROUND(yc+y),ROUND(xc),ROUND(yc+y),d); + StrokeSolidLine(ROUND(xc-xclip),ROUND(yc+y),ROUND(xc),ROUND(yc+y),color); } } else if ( startQuad == 4 ) @@ -1356,7 +1453,7 @@ void DisplayDriver::FillArc(const BRect &r, const float &angle, const float &spa if ( x >= startx ) { xclip = ROUND(y*startx/(double)starty); - StrokePatternLine(ROUND(xc+xclip),ROUND(yc+y),ROUND(xc+x),ROUND(yc+y),d); + StrokeSolidLine(ROUND(xc+xclip),ROUND(yc+y),ROUND(xc+x),ROUND(yc+y),color); } } @@ -1365,17 +1462,17 @@ void DisplayDriver::FillArc(const BRect &r, const float &angle, const float &spa if ( x >= endx ) { xclip = ROUND(y*endx/(double)endy); - StrokePatternLine(ROUND(xc+xclip),ROUND(yc-y),ROUND(xc+x),ROUND(yc-y),d); + StrokeSolidLine(ROUND(xc+xclip),ROUND(yc-y),ROUND(xc+x),ROUND(yc-y),color); } } else if ( endQuad == 2 ) { if ( x <= endx ) - StrokePatternLine(ROUND(xc-x),ROUND(yc-y),ROUND(xc),ROUND(yc-y),d); + StrokeSolidLine(ROUND(xc-x),ROUND(yc-y),ROUND(xc),ROUND(yc-y),color); else { xclip = ROUND(y*endx/(double)endy); - StrokePatternLine(ROUND(xc-xclip),ROUND(yc-y),ROUND(xc),ROUND(yc-y),d); + StrokeSolidLine(ROUND(xc-xclip),ROUND(yc-y),ROUND(xc),ROUND(yc-y),color); } } else if ( endQuad == 3 ) @@ -1383,17 +1480,17 @@ void DisplayDriver::FillArc(const BRect &r, const float &angle, const float &spa if ( x >= endx ) { xclip = ROUND(y*endx/(double)endy); - StrokePatternLine(ROUND(xc-x),ROUND(yc+y),ROUND(xc-xclip),ROUND(yc+y),d); + StrokeSolidLine(ROUND(xc-x),ROUND(yc+y),ROUND(xc-xclip),ROUND(yc+y),color); } } else if ( endQuad == 4 ) { if ( x <= endx ) - StrokePatternLine(ROUND(xc),ROUND(yc+y),ROUND(xc+x),ROUND(yc+y),d); + StrokeSolidLine(ROUND(xc),ROUND(yc+y),ROUND(xc+x),ROUND(yc+y),color); else { xclip = ROUND(y*endx/(double)endy); - StrokePatternLine(ROUND(xc),ROUND(yc+y),ROUND(xc+xclip),ROUND(yc+y),d); + StrokeSolidLine(ROUND(xc),ROUND(yc+y),ROUND(xc+xclip),ROUND(yc+y),color); } } } @@ -1404,30 +1501,30 @@ void DisplayDriver::FillArc(const BRect &r, const float &angle, const float &spa if ( startQuad == 1 ) { if ( (x <= startx) && (x >= endx) ) - StrokePatternLine(ROUND(xc+endclip),ROUND(yc-y),ROUND(xc+x),ROUND(yc-y),d); + StrokeSolidLine(ROUND(xc+endclip),ROUND(yc-y),ROUND(xc+x),ROUND(yc-y),color); else - StrokePatternLine(ROUND(xc+endclip),ROUND(yc-y),ROUND(xc+startclip),ROUND(yc-y),d); + StrokeSolidLine(ROUND(xc+endclip),ROUND(yc-y),ROUND(xc+startclip),ROUND(yc-y),color); } else if ( startQuad == 2 ) { if ( (x <= startx) && (x >= endx) ) - StrokePatternLine(ROUND(xc-x),ROUND(yc-y),ROUND(xc-startclip),ROUND(yc-y),d); + StrokeSolidLine(ROUND(xc-x),ROUND(yc-y),ROUND(xc-startclip),ROUND(yc-y),color); else - StrokePatternLine(ROUND(xc-endclip),ROUND(yc-y),ROUND(xc-startclip),ROUND(yc-y),d); + StrokeSolidLine(ROUND(xc-endclip),ROUND(yc-y),ROUND(xc-startclip),ROUND(yc-y),color); } else if ( startQuad == 3 ) { if ( (x <= startx) && (x >= endx) ) - StrokePatternLine(ROUND(xc-x),ROUND(yc+y),ROUND(xc-endclip),ROUND(yc+y),d); + StrokeSolidLine(ROUND(xc-x),ROUND(yc+y),ROUND(xc-endclip),ROUND(yc+y),color); else - StrokePatternLine(ROUND(xc-startclip),ROUND(yc+y),ROUND(xc-endclip),ROUND(yc+y),d); + StrokeSolidLine(ROUND(xc-startclip),ROUND(yc+y),ROUND(xc-endclip),ROUND(yc+y),color); } else if ( startQuad == 4 ) { if ( (x <= startx) && (x >= endx) ) - StrokePatternLine(ROUND(xc+startclip),ROUND(yc+y),ROUND(xc+x),ROUND(yc+y),d); + StrokeSolidLine(ROUND(xc+startclip),ROUND(yc+y),ROUND(xc+x),ROUND(yc+y),color); else - StrokePatternLine(ROUND(xc+startclip),ROUND(yc+y),ROUND(xc+endclip),ROUND(yc+y),d); + StrokeSolidLine(ROUND(xc+startclip),ROUND(yc+y),ROUND(xc+endclip),ROUND(yc+y),color); } } } @@ -1447,23 +1544,23 @@ void DisplayDriver::FillArc(const BRect &r, const float &angle, const float &spa } if ( useQuad1 ) - StrokePatternLine(ROUND(xc),ROUND(yc-y),ROUND(xc+x),ROUND(yc-y),d); + StrokeSolidLine(ROUND(xc),ROUND(yc-y),ROUND(xc+x),ROUND(yc-y),color); if ( useQuad2 ) - StrokePatternLine(ROUND(xc),ROUND(yc-y),ROUND(xc-x),ROUND(yc-y),d); + StrokeSolidLine(ROUND(xc),ROUND(yc-y),ROUND(xc-x),ROUND(yc-y),color); if ( useQuad3 ) - StrokePatternLine(ROUND(xc),ROUND(yc+y),ROUND(xc-x),ROUND(yc+y),d); + StrokeSolidLine(ROUND(xc),ROUND(yc+y),ROUND(xc-x),ROUND(yc+y),color); if ( useQuad4 ) - StrokePatternLine(ROUND(xc),ROUND(yc+y),ROUND(xc+x),ROUND(yc+y),d); + StrokeSolidLine(ROUND(xc),ROUND(yc+y),ROUND(xc+x),ROUND(yc+y),color); if ( !shortspan ) { if ( startQuad == 1 ) { if ( x <= startx ) - StrokePatternLine(ROUND(xc),ROUND(yc-y),ROUND(xc+x),ROUND(yc-y),d); + StrokeSolidLine(ROUND(xc),ROUND(yc-y),ROUND(xc+x),ROUND(yc-y),color); else { xclip = ROUND(y*startx/(double)starty); - StrokePatternLine(ROUND(xc),ROUND(yc-y),ROUND(xc+xclip),ROUND(yc-y),d); + StrokeSolidLine(ROUND(xc),ROUND(yc-y),ROUND(xc+xclip),ROUND(yc-y),color); } } else if ( startQuad == 2 ) @@ -1471,17 +1568,17 @@ void DisplayDriver::FillArc(const BRect &r, const float &angle, const float &spa if ( x >= startx ) { xclip = ROUND(y*startx/(double)starty); - StrokePatternLine(ROUND(xc-x),ROUND(yc-y),ROUND(xc-xclip),ROUND(yc-y),d); + StrokeSolidLine(ROUND(xc-x),ROUND(yc-y),ROUND(xc-xclip),ROUND(yc-y),color); } } else if ( startQuad == 3 ) { if ( x <= startx ) - StrokePatternLine(ROUND(xc-x),ROUND(yc+y),ROUND(xc),ROUND(yc+y),d); + StrokeSolidLine(ROUND(xc-x),ROUND(yc+y),ROUND(xc),ROUND(yc+y),color); else { xclip = ROUND(y*startx/(double)starty); - StrokePatternLine(ROUND(xc-xclip),ROUND(yc+y),ROUND(xc),ROUND(yc+y),d); + StrokeSolidLine(ROUND(xc-xclip),ROUND(yc+y),ROUND(xc),ROUND(yc+y),color); } } else if ( startQuad == 4 ) @@ -1489,7 +1586,7 @@ void DisplayDriver::FillArc(const BRect &r, const float &angle, const float &spa if ( x >= startx ) { xclip = ROUND(y*startx/(double)starty); - StrokePatternLine(ROUND(xc+xclip),ROUND(yc+y),ROUND(xc+x),ROUND(yc+y),d); + StrokeSolidLine(ROUND(xc+xclip),ROUND(yc+y),ROUND(xc+x),ROUND(yc+y),color); } } @@ -1498,17 +1595,17 @@ void DisplayDriver::FillArc(const BRect &r, const float &angle, const float &spa if ( x >= endx ) { xclip = ROUND(y*endx/(double)endy); - StrokePatternLine(ROUND(xc+xclip),ROUND(yc-y),ROUND(xc+x),ROUND(yc-y),d); + StrokeSolidLine(ROUND(xc+xclip),ROUND(yc-y),ROUND(xc+x),ROUND(yc-y),color); } } else if ( endQuad == 2 ) { if ( x <= endx ) - StrokePatternLine(ROUND(xc-x),ROUND(yc-y),ROUND(xc),ROUND(yc-y),d); + StrokeSolidLine(ROUND(xc-x),ROUND(yc-y),ROUND(xc),ROUND(yc-y),color); else { xclip = ROUND(y*endx/(double)endy); - StrokePatternLine(ROUND(xc-xclip),ROUND(yc-y),ROUND(xc),ROUND(yc-y),d); + StrokeSolidLine(ROUND(xc-xclip),ROUND(yc-y),ROUND(xc),ROUND(yc-y),color); } } else if ( endQuad == 3 ) @@ -1516,17 +1613,17 @@ void DisplayDriver::FillArc(const BRect &r, const float &angle, const float &spa if ( x >= endx ) { xclip = ROUND(y*endx/(double)endy); - StrokePatternLine(ROUND(xc-x),ROUND(yc+y),ROUND(xc-xclip),ROUND(yc+y),d); + StrokeSolidLine(ROUND(xc-x),ROUND(yc+y),ROUND(xc-xclip),ROUND(yc+y),color); } } else if ( endQuad == 4 ) { if ( x <= endx ) - StrokePatternLine(ROUND(xc),ROUND(yc+y),ROUND(xc+x),ROUND(yc+y),d); + StrokeSolidLine(ROUND(xc),ROUND(yc+y),ROUND(xc+x),ROUND(yc+y),color); else { xclip = ROUND(y*endx/(double)endy); - StrokePatternLine(ROUND(xc),ROUND(yc+y),ROUND(xc+xclip),ROUND(yc+y),d); + StrokeSolidLine(ROUND(xc),ROUND(yc+y),ROUND(xc+xclip),ROUND(yc+y),color); } } } @@ -1537,136 +1634,431 @@ void DisplayDriver::FillArc(const BRect &r, const float &angle, const float &spa if ( startQuad == 1 ) { if ( (x <= startx) && (x >= endx) ) - StrokePatternLine(ROUND(xc+endclip),ROUND(yc-y),ROUND(xc+x),ROUND(yc-y),d); + StrokeSolidLine(ROUND(xc+endclip),ROUND(yc-y),ROUND(xc+x),ROUND(yc-y),color); else - StrokePatternLine(ROUND(xc+endclip),ROUND(yc-y),ROUND(xc+startclip),ROUND(yc-y),d); + StrokeSolidLine(ROUND(xc+endclip),ROUND(yc-y),ROUND(xc+startclip),ROUND(yc-y),color); } else if ( startQuad == 2 ) { if ( (x <= startx) && (x >= endx) ) - StrokePatternLine(ROUND(xc-x),ROUND(yc-y),ROUND(xc-startclip),ROUND(yc-y),d); + StrokeSolidLine(ROUND(xc-x),ROUND(yc-y),ROUND(xc-startclip),ROUND(yc-y),color); else - StrokePatternLine(ROUND(xc-endclip),ROUND(yc-y),ROUND(xc-startclip),ROUND(yc-y),d); + StrokeSolidLine(ROUND(xc-endclip),ROUND(yc-y),ROUND(xc-startclip),ROUND(yc-y),color); } else if ( startQuad == 3 ) { if ( (x <= startx) && (x >= endx) ) - StrokePatternLine(ROUND(xc-x),ROUND(yc+y),ROUND(xc-endclip),ROUND(yc+y),d); + StrokeSolidLine(ROUND(xc-x),ROUND(yc+y),ROUND(xc-endclip),ROUND(yc+y),color); else - StrokePatternLine(ROUND(xc-startclip),ROUND(yc+y),ROUND(xc-endclip),ROUND(yc+y),d); + StrokeSolidLine(ROUND(xc-startclip),ROUND(yc+y),ROUND(xc-endclip),ROUND(yc+y),color); } else if ( startQuad == 4 ) { if ( (x <= startx) && (x >= endx) ) - StrokePatternLine(ROUND(xc+startclip),ROUND(yc+y),ROUND(xc+x),ROUND(yc+y),d); + StrokeSolidLine(ROUND(xc+startclip),ROUND(yc+y),ROUND(xc+x),ROUND(yc+y),color); else - StrokePatternLine(ROUND(xc+startclip),ROUND(yc+y),ROUND(xc+endclip),ROUND(yc+y),d); + StrokeSolidLine(ROUND(xc+startclip),ROUND(yc+y),ROUND(xc+endclip),ROUND(yc+y),color); } } } Unlock(); +} +/*! + \brief Called for all BView::FillArc calls + \param r Rectangle enclosing the entire arc + \param angle Starting angle for the arc in degrees + \param span Span of the arc in degrees. Ending angle = angle+span. + \param d Object holding the bazillion other options +*/ +void DisplayDriver::FillArc(const BRect &r, const float &angle, const float &span, const DrawData *d) +{ + float xc = (r.left+r.right)/2; + float yc = (r.top+r.bottom)/2; + float rx = r.Width()/2; + float ry = r.Height()/2; + int Rx2 = ROUND(rx*rx); + int Ry2 = ROUND(ry*ry); + int twoRx2 = 2*Rx2; + int twoRy2 = 2*Ry2; + int p; + int x=0; + int y = (int)ry; + int px = 0; + int py = twoRx2 * y; + int startx, endx; + int starty, endy; + int xclip, startclip, endclip; + int startQuad, endQuad; + bool useQuad1, useQuad2, useQuad3, useQuad4; + bool shortspan = false; + DrawData data; + + // Watch out for bozos giving us whacko spans + if ( (span >= 360) || (span <= -360) ) + { + FillEllipse(r,d); + return; + } + + Lock(); + + data = *d; + data.pensize = 1; + + if ( span > 0 ) + { + startQuad = (int)(angle/90)%4+1; + endQuad = (int)((angle+span)/90)%4+1; + startx = ROUND(.5*r.Width()*fabs(cos(angle*M_PI/180))); + endx = ROUND(.5*r.Width()*fabs(cos((angle+span)*M_PI/180))); + } + else + { + endQuad = (int)(angle/90)%4+1; + startQuad = (int)((angle+span)/90)%4+1; + endx = ROUND(.5*r.Width()*fabs(cos(angle*M_PI/180))); + startx = ROUND(.5*r.Width()*fabs(cos((angle+span)*M_PI/180))); + } + + starty = ROUND(ry*sqrt(1-(double)startx*startx/(rx*rx))); + endy = ROUND(ry*sqrt(1-(double)endx*endx/(rx*rx))); + + if ( startQuad != endQuad ) + { + useQuad1 = (endQuad > 1) && (startQuad > endQuad); + useQuad2 = ((startQuad == 1) && (endQuad > 2)) || ((startQuad > endQuad) && (endQuad > 2)); + useQuad3 = ((startQuad < 3) && (endQuad == 4)) || ((startQuad < 3) && (endQuad < startQuad)); + useQuad4 = (startQuad < 4) && (startQuad > endQuad); + } + else + { + if ( (span < 90) && (span > -90) ) + { + useQuad1 = false; + useQuad2 = false; + useQuad3 = false; + useQuad4 = false; + shortspan = true; + } + else + { + useQuad1 = (startQuad != 1); + useQuad2 = (startQuad != 2); + useQuad3 = (startQuad != 3); + useQuad4 = (startQuad != 4); + } + } + + if ( useQuad1 ) + StrokeLine(BPoint(xc,yc-y),BPoint(xc+x,yc-y),&data); + if ( useQuad2 ) + StrokeLine(BPoint(xc,yc-y),BPoint(xc-x,yc-y),&data); + if ( useQuad3 ) + StrokeLine(BPoint(xc,yc+y),BPoint(xc-x,yc+y),&data); + if ( useQuad4 ) + StrokeLine(BPoint(xc,yc+y),BPoint(xc+x,yc+y),&data); + + p = ROUND (Ry2 - (Rx2 * ry) + (.25 * Rx2)); + while (px < py) + { + x++; + px += twoRy2; + if ( p < 0 ) + p += Ry2 + px; + else + { + y--; + py -= twoRx2; + p += Ry2 + px - py; + } + + if ( useQuad1 ) + StrokeLine(BPoint(xc,yc-y),BPoint(xc+x,yc-y),&data); + if ( useQuad2 ) + StrokeLine(BPoint(xc,yc-y),BPoint(xc-x,yc-y),&data); + if ( useQuad3 ) + StrokeLine(BPoint(xc,yc+y),BPoint(xc-x,yc+y),&data); + if ( useQuad4 ) + StrokeLine(BPoint(xc,yc+y),BPoint(xc+x,yc+y),&data); + if ( !shortspan ) + { + if ( startQuad == 1 ) + { + if ( x <= startx ) + StrokeLine(BPoint(xc,yc-y),BPoint(xc+x,yc-y),&data); + else + { + xclip = ROUND(y*startx/(double)starty); + StrokeLine(BPoint(xc,yc-y),BPoint(xc+xclip,yc-y),&data); + } + } + else if ( startQuad == 2 ) + { + if ( x >= startx ) + { + xclip = ROUND(y*startx/(double)starty); + StrokeLine(BPoint(xc-x,yc-y),BPoint(xc-xclip,yc-y),&data); + } + } + else if ( startQuad == 3 ) + { + if ( x <= startx ) + StrokeLine(BPoint(xc-x,yc+y),BPoint(xc,yc+y),&data); + else + { + xclip = ROUND(y*startx/(double)starty); + StrokeLine(BPoint(xc-xclip,yc+y),BPoint(xc,yc+y),&data); + } + } + else if ( startQuad == 4 ) + { + if ( x >= startx ) + { + xclip = ROUND(y*startx/(double)starty); + StrokeLine(BPoint(xc+xclip,yc+y),BPoint(xc+x,yc+y),&data); + } + } + + if ( endQuad == 1 ) + { + if ( x >= endx ) + { + xclip = ROUND(y*endx/(double)endy); + StrokeLine(BPoint(xc+xclip,yc-y),BPoint(xc+x,yc-y),&data); + } + } + else if ( endQuad == 2 ) + { + if ( x <= endx ) + StrokeLine(BPoint(xc-x,yc-y),BPoint(xc,yc-y),&data); + else + { + xclip = ROUND(y*endx/(double)endy); + StrokeLine(BPoint(xc-xclip,yc-y),BPoint(xc,yc-y),&data); + } + } + else if ( endQuad == 3 ) + { + if ( x >= endx ) + { + xclip = ROUND(y*endx/(double)endy); + StrokeLine(BPoint(xc-x,yc+y),BPoint(xc-xclip,yc+y),&data); + } + } + else if ( endQuad == 4 ) + { + if ( x <= endx ) + StrokeLine(BPoint(xc,yc+y),BPoint(xc+x,yc+y),&data); + else + { + xclip = ROUND(y*endx/(double)endy); + StrokeLine(BPoint(xc,yc+y),BPoint(xc+xclip,yc+y),&data); + } + } + } + else + { + startclip = ROUND(y*startx/(double)starty); + endclip = ROUND(y*endx/(double)endy); + if ( startQuad == 1 ) + { + if ( (x <= startx) && (x >= endx) ) + StrokeLine(BPoint(xc+endclip,yc-y),BPoint(xc+x,yc-y),&data); + else + StrokeLine(BPoint(xc+endclip,yc-y),BPoint(xc+startclip,yc-y),&data); + } + else if ( startQuad == 2 ) + { + if ( (x <= startx) && (x >= endx) ) + StrokeLine(BPoint(xc-x,yc-y),BPoint(xc-startclip,yc-y),&data); + else + StrokeLine(BPoint(xc-endclip,yc-y),BPoint(xc-startclip,yc-y),&data); + } + else if ( startQuad == 3 ) + { + if ( (x <= startx) && (x >= endx) ) + StrokeLine(BPoint(xc-x,yc+y),BPoint(xc-endclip,yc+y),&data); + else + StrokeLine(BPoint(xc-startclip,yc+y),BPoint(xc-endclip,yc+y),&data); + } + else if ( startQuad == 4 ) + { + if ( (x <= startx) && (x >= endx) ) + StrokeLine(BPoint(xc+startclip,yc+y),BPoint(xc+x,yc+y),&data); + else + StrokeLine(BPoint(xc+startclip,yc+y),BPoint(xc+endclip,yc+y),&data); + } + } + } + + p = ROUND(Ry2*(x+.5)*(x+.5) + Rx2*(y-1)*(y-1) - Rx2*Ry2); + while (y>0) + { + y--; + py -= twoRx2; + if (p>0) + p += Rx2 - py; + else + { + x++; + px += twoRy2; + p += Rx2 - py +px; + } + + if ( useQuad1 ) + StrokeLine(BPoint(xc,yc-y),BPoint(xc+x,yc-y),&data); + if ( useQuad2 ) + StrokeLine(BPoint(xc,yc-y),BPoint(xc-x,yc-y),&data); + if ( useQuad3 ) + StrokeLine(BPoint(xc,yc+y),BPoint(xc-x,yc+y),&data); + if ( useQuad4 ) + StrokeLine(BPoint(xc,yc+y),BPoint(xc+x,yc+y),&data); + if ( !shortspan ) + { + if ( startQuad == 1 ) + { + if ( x <= startx ) + StrokeLine(BPoint(xc,yc-y),BPoint(xc+x,yc-y),&data); + else + { + xclip = ROUND(y*startx/(double)starty); + StrokeLine(BPoint(xc,yc-y),BPoint(xc+xclip,yc-y),&data); + } + } + else if ( startQuad == 2 ) + { + if ( x >= startx ) + { + xclip = ROUND(y*startx/(double)starty); + StrokeLine(BPoint(xc-x,yc-y),BPoint(xc-xclip,yc-y),&data); + } + } + else if ( startQuad == 3 ) + { + if ( x <= startx ) + StrokeLine(BPoint(xc-x,yc+y),BPoint(xc,yc+y),&data); + else + { + xclip = ROUND(y*startx/(double)starty); + StrokeLine(BPoint(xc-xclip,yc+y),BPoint(xc,yc+y),&data); + } + } + else if ( startQuad == 4 ) + { + if ( x >= startx ) + { + xclip = ROUND(y*startx/(double)starty); + StrokeLine(BPoint(xc+xclip,yc+y),BPoint(xc+x,yc+y),&data); + } + } + + if ( endQuad == 1 ) + { + if ( x >= endx ) + { + xclip = ROUND(y*endx/(double)endy); + StrokeLine(BPoint(xc+xclip,yc-y),BPoint(xc+x,yc-y),&data); + } + } + else if ( endQuad == 2 ) + { + if ( x <= endx ) + StrokeLine(BPoint(xc-x,yc-y),BPoint(xc,yc-y),&data); + else + { + xclip = ROUND(y*endx/(double)endy); + StrokeLine(BPoint(xc-xclip,yc-y),BPoint(xc,yc-y),&data); + } + } + else if ( endQuad == 3 ) + { + if ( x >= endx ) + { + xclip = ROUND(y*endx/(double)endy); + StrokeLine(BPoint(xc-x,yc+y),BPoint(xc-xclip,yc+y),&data); + } + } + else if ( endQuad == 4 ) + { + if ( x <= endx ) + StrokeLine(BPoint(xc,yc+y),BPoint(xc+x,yc+y),&data); + else + { + xclip = ROUND(y*endx/(double)endy); + StrokeLine(BPoint(xc,yc+y),BPoint(xc+xclip,yc+y),&data); + } + } + } + else + { + startclip = ROUND(y*startx/(double)starty); + endclip = ROUND(y*endx/(double)endy); + if ( startQuad == 1 ) + { + if ( (x <= startx) && (x >= endx) ) + StrokeLine(BPoint(xc+endclip,yc-y),BPoint(xc+x,yc-y),&data); + else + StrokeLine(BPoint(xc+endclip,yc-y),BPoint(xc+startclip,yc-y),&data); + } + else if ( startQuad == 2 ) + { + if ( (x <= startx) && (x >= endx) ) + StrokeLine(BPoint(xc-x,yc-y),BPoint(xc-startclip,yc-y),&data); + else + StrokeLine(BPoint(xc-endclip,yc-y),BPoint(xc-startclip,yc-y),&data); + } + else if ( startQuad == 3 ) + { + if ( (x <= startx) && (x >= endx) ) + StrokeLine(BPoint(xc-x,yc+y),BPoint(xc-endclip,yc+y),&data); + else + StrokeLine(BPoint(xc-startclip,yc+y),BPoint(xc-endclip,yc+y),&data); + } + else if ( startQuad == 4 ) + { + if ( (x <= startx) && (x >= endx) ) + StrokeLine(BPoint(xc+startclip,yc+y),BPoint(xc+x,yc+y),&data); + else + StrokeLine(BPoint(xc+startclip,yc+y),BPoint(xc+endclip,yc+y),&data); + } + } + } + Unlock(); } void DisplayDriver::FillBezier(BPoint *pts, const RGBColor &color) { -} + Lock(); -void DisplayDriver::FillBezier(BPoint *pts, const DrawData *d) -{ + BezierCurve curve(pts); + FillPolygon(curve.GetPointArray(), curve.points.CountItems(), color); + + Unlock(); } /*! \brief Called for all BView::FillBezier calls. \param pts 4-element array of BPoints in the order of start, end, and then the two control points. - \param setLine Horizontal ine drawing routine which handles things like color and pattern. - - Does not work quite right, need to redo this. + \param d draw data */ -void DisplayDriver::FillBezier(BPoint *pts, DisplayDriver* driver, SetHorizontalLineFuncType setLine) +void DisplayDriver::FillBezier(BPoint *pts, const DrawData *d) { - /* - double Ax, Bx, Cx, Dx; - double Ay, By, Cy, Dy; - int x, y; - int lastx=-1, lasty=-1; - double t; - double dt = .0002; - double dt2, dt3; - double X, Y, dx, ddx, dddx, dy, ddy, dddy; - float oldpensize; - bool steep = false; - Lock(); - if ( fabs(pts[3].y-pts[0].y) > fabs(pts[3].x-pts[0].x) ) - steep = true; - - LineCalc line(pts[0], pts[3]); - oldpensize = d->pensize; - d->pensize = 1; - Ax = -pts[0].x + 3*pts[1].x - 3*pts[2].x + pts[3].x; - Bx = 3*pts[0].x - 6*pts[1].x + 3*pts[2].x; - Cx = -3*pts[0].x + 3*pts[1].x; - Dx = pts[0].x; + BezierCurve curve(pts); + FillPolygon(curve.GetPointArray(), curve.points.CountItems(), d); - Ay = -pts[0].y + 3*pts[1].y - 3*pts[2].y + pts[3].y; - By = 3*pts[0].y - 6*pts[1].y + 3*pts[2].y; - Cy = -3*pts[0].y + 3*pts[1].y; - Dy = pts[0].y; - - dt2 = dt * dt; - dt3 = dt2 * dt; - X = Dx; - dx = Ax*dt3 + Bx*dt2 + Cx*dt; - ddx = 6*Ax*dt3 + 2*Bx*dt2; - dddx = 6*Ax*dt3; - Y = Dy; - dy = Ay*dt3 + By*dt2 + Cy*dt; - ddy = 6*Ay*dt3 + 2*By*dt2; - dddy = 6*Ay*dt3; - - lastx = -1; - lasty = -1; - - for (t=0; t<=1; t+=dt) - { - x = ROUND(X); - y = ROUND(Y); - if ( (x!=lastx) || (y!=lasty) ) - { - if ( steep ) - StrokeLine(BPoint(x,y),BPoint(line.GetX(y),y),d,pat); - else - StrokeLine(BPoint(x,y),BPoint(x,line.GetY(x)),d,pat); - } - lastx = x; - lasty = y; - - X += dx; - dx += ddx; - ddx += dddx; - Y += dy; - dy += ddy; - ddy += dddy; - } - d->pensize = oldpensize; Unlock(); - */ -} - -void DisplayDriver::FillEllipse(const BRect &r, const RGBColor &color) -{ } /*! \brief Called for all BView::FillEllipse calls \param r BRect enclosing the ellipse to be drawn. - \param d DrawData containing the endless options + \param color The color of the ellipse */ - -void DisplayDriver::FillEllipse(const BRect &r, const DrawData *d) +void DisplayDriver::FillEllipse(const BRect &r, const RGBColor &color) { float xc = (r.left+r.right)/2; float yc = (r.top+r.bottom)/2; @@ -1684,8 +2076,8 @@ void DisplayDriver::FillEllipse(const BRect &r, const DrawData *d) Lock(); - StrokePatternLine(ROUND(xc),ROUND(yc-y),ROUND(xc),ROUND(yc-y),d); - StrokePatternLine(ROUND(xc),ROUND(yc+y),ROUND(xc),ROUND(yc+y),d); + StrokeSolidLine(ROUND(xc),ROUND(yc-y),ROUND(xc),ROUND(yc-y),color); + StrokeSolidLine(ROUND(xc),ROUND(yc+y),ROUND(xc),ROUND(yc+y),color); p = ROUND (Ry2 - (Rx2 * ry) + (.25 * Rx2)); while (px < py) @@ -1701,8 +2093,8 @@ void DisplayDriver::FillEllipse(const BRect &r, const DrawData *d) p += Ry2 + px - py; } - StrokePatternLine(ROUND(xc-x),ROUND(yc-y),ROUND(xc+x),ROUND(yc-y),d); - StrokePatternLine(ROUND(xc-x),ROUND(yc+y),ROUND(xc+x),ROUND(yc+y),d); + StrokeSolidLine(ROUND(xc-x),ROUND(yc-y),ROUND(xc+x),ROUND(yc-y),color); + StrokeSolidLine(ROUND(xc-x),ROUND(yc+y),ROUND(xc+x),ROUND(yc+y),color); } p = ROUND(Ry2*(x+.5)*(x+.5) + Rx2*(y-1)*(y-1) - Rx2*Ry2); @@ -1719,23 +2111,87 @@ void DisplayDriver::FillEllipse(const BRect &r, const DrawData *d) p += Rx2 - py +px; } - StrokePatternLine(ROUND(xc-x),ROUND(yc-y),ROUND(xc+x),ROUND(yc-y),d); - StrokePatternLine(ROUND(xc-x),ROUND(yc+y),ROUND(xc+x),ROUND(yc+y),d); + StrokeSolidLine(ROUND(xc-x),ROUND(yc-y),ROUND(xc+x),ROUND(yc-y),color); + StrokeSolidLine(ROUND(xc-x),ROUND(yc+y),ROUND(xc+x),ROUND(yc+y),color); } Unlock(); } -void DisplayDriver::FillPolygon(BPoint *ptlist, int32 numpts, const RGBColor &color) +/*! + \brief Called for all BView::FillEllipse calls + \param r BRect enclosing the ellipse to be drawn. + \param d DrawData containing the endless options +*/ +void DisplayDriver::FillEllipse(const BRect &r, const DrawData *d) { + float xc = (r.left+r.right)/2; + float yc = (r.top+r.bottom)/2; + float rx = r.Width()/2; + float ry = r.Height()/2; + int Rx2 = ROUND(rx*rx); + int Ry2 = ROUND(ry*ry); + int twoRx2 = 2*Rx2; + int twoRy2 = 2*Ry2; + int p; + int x=0; + int y = (int)ry; + int px = 0; + int py = twoRx2 * y; + DrawData data; + + Lock(); + + data = *d; + data.pensize = 1; + + StrokeLine(BPoint(xc,yc-y),BPoint(xc,yc-y),&data); + StrokeLine(BPoint(xc,yc+y),BPoint(xc,yc+y),&data); + + p = ROUND (Ry2 - (Rx2 * ry) + (.25 * Rx2)); + while (px < py) + { + x++; + px += twoRy2; + if ( p < 0 ) + p += Ry2 + px; + else + { + y--; + py -= twoRx2; + p += Ry2 + px - py; + } + + StrokeLine(BPoint(xc-x,yc-y),BPoint(xc+x,yc-y),&data); + StrokeLine(BPoint(xc-x,yc+y),BPoint(xc+x,yc+y),&data); + } + + p = ROUND(Ry2*(x+.5)*(x+.5) + Rx2*(y-1)*(y-1) - Rx2*Ry2); + while (y>0) + { + y--; + py -= twoRx2; + if (p>0) + p += Rx2 - py; + else + { + x++; + px += twoRy2; + p += Rx2 - py +px; + } + + StrokeLine(BPoint(xc-x,yc-y),BPoint(xc+x,yc-y),&data); + StrokeLine(BPoint(xc-x,yc+y),BPoint(xc+x,yc+y),&data); + } + Unlock(); } /*! \brief Called for all BView::FillPolygon calls \param ptlist Array of BPoints defining the polygon. \param numpts Number of points in the BPoint array. - \param d The 50 bazillion drawing options (inluding clip region) + \param color The color of the polygon */ -void DisplayDriver::FillPolygon(BPoint *ptlist, int32 numpts, const DrawData *d) +void DisplayDriver::FillPolygon(BPoint *ptlist, int32 numpts, const RGBColor &color) { /* Here's the plan. Record all line segments in polygon. If a line segments crosses the y-value of a point not in the segment, split the segment into 2 segments. @@ -1756,7 +2212,12 @@ void DisplayDriver::FillPolygon(BPoint *ptlist, int32 numpts, const DrawData *d) int currentIndex, bestIndex, i, j, y; LineCalc *segmentArray = new LineCalc[2*numpts]; int numSegments = 0; + int minX, minY, maxX, maxY; + minX = ROUND(ptlist[0].x); + maxX = ROUND(ptlist[0].x); + minY = ROUND(ptlist[0].y); + maxY = ROUND(ptlist[0].y); /* Generate the segment list */ currentPoint = ptlist; currentIndex = 0; @@ -1771,6 +2232,15 @@ void DisplayDriver::FillPolygon(BPoint *ptlist, int32 numpts, const DrawData *d) return; } + if ( ROUND(currentPoint->x) < minX ) + minX = ROUND(currentPoint->x); + if ( ROUND(currentPoint->x) > maxX ) + maxX = ROUND(currentPoint->x); + if ( ROUND(currentPoint->y) < minY ) + minY = ROUND(currentPoint->y); + if ( ROUND(currentPoint->y) > maxY ) + maxY = ROUND(currentPoint->y); + for (i=0; i currentPoint->y) && (ptlist[i].y < nextPoint->y)) || @@ -1819,7 +2289,7 @@ void DisplayDriver::FillPolygon(BPoint *ptlist, int32 numpts, const DrawData *d) } /* Draw the lines */ - for (y=(int)segmentArray[0].MinY(); y<=segmentArray[numSegments-1].MaxY(); y++) + for (y=minY; y<=maxY; y++) { i = 0; while (i= 0) ) - StrokePatternLine(ROUND(segmentArray[i].MinX()), y, - ROUND(segmentArray[i].MaxX()), y, d); + StrokeSolidLine(ROUND(segmentArray[i].MinX()), y, + ROUND(segmentArray[i].MaxX()), y, color); i++; } else { - if ( (segmentArray[i].GetX(y) < _displaymode.virtual_width) && - (segmentArray[i+1].GetX(y) >= 0) ) - StrokePatternLine(ROUND(segmentArray[i].GetX(y)), y, - ROUND(segmentArray[i+1].GetX(y)), y, d); + if ( (segmentArray[i+1].GetX(y) < _displaymode.virtual_width) && + (segmentArray[i].GetX(y) >= 0) ) + StrokeSolidLine(ROUND(segmentArray[i].GetX(y)), y, + ROUND(segmentArray[i+1].GetX(y)), y, color); i+=2; } } } + + delete[] segmentArray; + Unlock(); + +} + +/*! + \brief Called for all BView::FillPolygon calls + \param ptlist Array of BPoints defining the polygon. + \param numpts Number of points in the BPoint array. + \param d The 50 bazillion drawing options (inluding clip region) +*/ +void DisplayDriver::FillPolygon(BPoint *ptlist, int32 numpts, const DrawData *d) +{ + /* Here's the plan. Record all line segments in polygon. If a line segments crosses + the y-value of a point not in the segment, split the segment into 2 segments. + Once we have gone through all of the segments, sort them primarily on y-value + and secondarily on x-value. Step through each y-value in the bounding rectangle + and look for intersections with line segments. First intersection is start of + horizontal line, second intersection is end of horizontal line. Continue for + all pairs of intersections. Watch out for horizontal line segments. + */ + if ( !ptlist || (numpts < 3) ) + return; + + Lock(); + + BPoint *currentPoint, *nextPoint; + BPoint tempNextPoint; + BPoint tempCurrentPoint; + int currentIndex, bestIndex, i, j, y; + LineCalc *segmentArray = new LineCalc[2*numpts]; + int numSegments = 0; + int minX, minY, maxX, maxY; + + minX = ROUND(ptlist[0].x); + maxX = ROUND(ptlist[0].x); + minY = ROUND(ptlist[0].y); + maxY = ROUND(ptlist[0].y); + /* Generate the segment list */ + currentPoint = ptlist; + currentIndex = 0; + nextPoint = &ptlist[1]; + while (currentPoint) + { + if ( numSegments >= 2*numpts ) + { + printf("ERROR: Insufficient memory allocated to segment array\n"); + delete[] segmentArray; + Unlock(); + return; + } + + if ( ROUND(currentPoint->x) < minX ) + minX = ROUND(currentPoint->x); + if ( ROUND(currentPoint->x) > maxX ) + maxX = ROUND(currentPoint->x); + if ( ROUND(currentPoint->y) < minY ) + minY = ROUND(currentPoint->y); + if ( ROUND(currentPoint->y) > maxY ) + maxY = ROUND(currentPoint->y); + + for (i=0; i currentPoint->y) && (ptlist[i].y < nextPoint->y)) || + ((ptlist[i].y < currentPoint->y) && (ptlist[i].y > nextPoint->y)) ) + { + segmentArray[numSegments].SetPoints(*currentPoint,*nextPoint); + tempNextPoint.x = segmentArray[numSegments].GetX(ptlist[i].y); + tempNextPoint.y = ptlist[i].y; + nextPoint = &tempNextPoint; + } + } + + segmentArray[numSegments].SetPoints(*currentPoint,*nextPoint); + numSegments++; + if ( nextPoint == &tempNextPoint ) + { + tempCurrentPoint = tempNextPoint; + currentPoint = &tempCurrentPoint; + nextPoint = &ptlist[(currentIndex+1)%numpts]; + } + else if ( nextPoint == ptlist ) + { + currentPoint = NULL; + } + else + { + currentPoint = nextPoint; + currentIndex++; + nextPoint = &ptlist[(currentIndex+1)%numpts]; + } + } + + /* Selection sort the segments. Probably should replace this later. */ + for (i=0; iclipReg ) + { + /* Draw the lines */ + for (y=minY; y<=maxY; y++) + { + i = 0; + while (i y) + break; + if (segmentArray[i].MaxY() < y) + { + i++; + continue; + } + if (segmentArray[i].MinY() == segmentArray[i].MaxY()) + { + if ( (segmentArray[i].MinX() < _displaymode.virtual_width) && + (segmentArray[i].MaxX() >= 0) ) + StrokePatternLine(ROUND(segmentArray[i].MinX()), y, + ROUND(segmentArray[i].MaxX()), y, d); + i++; + } + else + { + if ( (segmentArray[i+1].GetX(y) < _displaymode.virtual_width) && + (segmentArray[i].GetX(y) >= 0) ) + StrokePatternLine(ROUND(segmentArray[i].GetX(y)), y, + ROUND(segmentArray[i+1].GetX(y)), y, d); + i+=2; + } + } + } + } + else + { + int numRects, rectIndex; + int yStart, yEnd; + BRect clipRect; + numRects = d->clipReg->CountRects(); + for (rectIndex = 0; rectIndex < numRects; rectIndex++) + { + clipRect = d->clipReg->RectAt(rectIndex); + if ( clipRect.bottom < minY ) + continue; + if ( clipRect.top > maxY ) + continue; + if ( clipRect.left < minX ) + continue; + if ( clipRect.right > maxX ) + continue; + yStart = MAX(minY,ROUND(clipRect.top)); + yEnd = MIN(maxY,ROUND(clipRect.bottom)); + + /* Draw the lines */ + for (y=yStart; y<=yEnd; y++) + { + i = 0; + while (i y) + break; + if (segmentArray[i].MaxY() < y) + { + i++; + continue; + } + if (segmentArray[i].MinY() == segmentArray[i].MaxY()) + { + if (segmentArray[i].MinX() > clipRect.right) + { + i++; + continue; + } + if (segmentArray[i].MaxX() < clipRect.left) + { + i++; + continue; + } + StrokePatternLine(ROUND(MAX(segmentArray[i].MinX(),clipRect.left)), y, + ROUND(MIN(segmentArray[i].MaxX(),clipRect.right)), y, d); + i++; + } + else + { + if (segmentArray[i].GetX(y) > clipRect.right) + { + i+=2; + continue; + } + if (segmentArray[i+1].GetX(y) < clipRect.left) + { + i+=2; + continue; + } + StrokePatternLine(ROUND(MAX(segmentArray[i].GetX(y),clipRect.left)), y, + ROUND(MIN(segmentArray[i+1].GetX(y),clipRect.right)), y, d); + i+=2; + } + } + } + } + } delete[] segmentArray; Unlock(); } @@ -1874,8 +2556,24 @@ void DisplayDriver::FillRect(const BRect &r, const RGBColor &color) */ void DisplayDriver::FillRect(const BRect &r, const DrawData *d) { + if(!d) + return; + Lock(); - FillPatternRect(r,d); + if ( d->clipReg ) + { + if ( d->clipReg->Intersects(r) ) + { + BRegion reg(r); + reg.IntersectWith(d->clipReg); + int numRects = reg.CountRects(); + + for(int32 i=0; iclipReg ) + { + BRegion drawReg = r; + + drawReg.IntersectWith(d->clipReg); + numRects = drawReg.CountRects(); + + for(int32 i=0; iclipReg ) { - arc_x = xrad*sqrt(1-i*i/yrad2); - StrokePatternLine(ROUND(r.left+xrad-arc_x), ROUND(r.top+yrad-i), - ROUND(r.right-xrad+arc_x), ROUND(r.top+yrad-i),d); - StrokePatternLine(ROUND(r.left+xrad-arc_x), ROUND(r.bottom-yrad+i), - ROUND(r.right-xrad+arc_x), ROUND(r.bottom-yrad+i),d); + int numRects, rectIndex; + BRect clipRect; + int left, right, y1, y2; + int rectTop, rectBottom, rectLeft, rectRight; + + numRects = d->clipReg->CountRects(); + for (rectIndex=0; rectIndexclipReg->RectAt(rectIndex); + rectTop = ROUND(clipRect.top); + rectBottom = ROUND(clipRect.bottom); + rectLeft = ROUND(clipRect.left); + rectRight = ROUND(clipRect.right); + for (i=0; i<=(int)yrad; i++) + { + arc_x = xrad*sqrt(1-i*i/yrad2); + left = ROUND(r.left + xrad - arc_x); + right = ROUND(r.right - xrad + arc_x); + if ( (left > rectRight) || (right < rectLeft) ) + continue; + y1 = ROUND(r.top + yrad - i); + y2 = ROUND(r.bottom - yrad + i); + if ( (y1 >= rectTop) && (y1 <= rectBottom) ) + StrokePatternLine(MAX(left,rectLeft), y1, MIN(right,rectRight), y1,d); + if ( (y2 >= rectTop) && (y2 <= rectBottom) ) + StrokePatternLine(MAX(left,rectLeft), y2, MIN(right,rectRight), y2,d); + } + } + } + else + { + for (i=0; i<=(int)yrad; i++) + { + arc_x = xrad*sqrt(1-i*i/yrad2); + StrokePatternLine(ROUND(r.left+xrad-arc_x), ROUND(r.top+yrad-i), ROUND(r.right-xrad+arc_x), ROUND(r.top+yrad-i),d); + StrokePatternLine(ROUND(r.left+xrad-arc_x), ROUND(r.bottom-yrad+i), ROUND(r.right-xrad+arc_x), ROUND(r.bottom-yrad+i),d); + } } FillPatternRect(BRect(r.left,r.top+yrad,r.right,r.bottom-yrad),d); - + Unlock(); } //void DisplayDriver::FillShape(SShape *sh, const DrawData *d, const Pattern &pat) @@ -1962,19 +2714,11 @@ void DisplayDriver::FillRoundRect(const BRect &r, const float &xrad, const float //} void DisplayDriver::FillTriangle(BPoint *pts, const RGBColor &color) -{ -} - -/*! - \brief Called for all BView::FillTriangle calls - \param pts Array of 3 BPoints. Always non-NULL. - \param setLine Horizontal line drawing routine which handles things like color and pattern. -*/ -void DisplayDriver::FillTriangle(BPoint *pts, const DrawData *d) { if ( !pts ) return; + Lock(); BPoint first, second, third; // Sort points according to their y values and x values (y is primary) @@ -2019,7 +2763,7 @@ void DisplayDriver::FillTriangle(BPoint *pts, const DrawData *d) end.y=first.y; start.x=MIN(first.x,MIN(second.x,third.x)); end.x=MAX(first.x,MAX(second.x,third.x)); - StrokePatternLine(ROUND(start.x), ROUND(start.y), ROUND(end.x), ROUND(start.y), d); + StrokeSolidLine(ROUND(start.x), ROUND(start.y), ROUND(end.x), ROUND(start.y), color); return; } @@ -2031,9 +2775,9 @@ void DisplayDriver::FillTriangle(BPoint *pts, const DrawData *d) LineCalc lineA(first, third); LineCalc lineB(second, third); - StrokePatternLine(ROUND(first.x), ROUND(first.y), ROUND(second.x), ROUND(first.y), d); + StrokeSolidLine(ROUND(first.x), ROUND(first.y), ROUND(second.x), ROUND(first.y), color); for(i=(int32)first.y+1; i<=third.y; i++) - StrokePatternLine(ROUND(lineA.GetX(i)), i, ROUND(lineB.GetX(i)), i, d); + StrokeSolidLine(ROUND(lineA.GetX(i)), i, ROUND(lineB.GetX(i)), i, color); return; } @@ -2043,9 +2787,9 @@ void DisplayDriver::FillTriangle(BPoint *pts, const DrawData *d) LineCalc lineA(first, second); LineCalc lineB(first, third); - StrokePatternLine(ROUND(second.x), ROUND(second.y), ROUND(third.x), ROUND(second.y), d); + StrokeSolidLine(ROUND(second.x), ROUND(second.y), ROUND(third.x), ROUND(second.y), color); for(i=(int32)first.y; iclipReg ) + { + // For now, cop out and use FillPolygon + // Need to investigate if Triangle specific code would save processing time + FillPolygon(pts,3,d); + } + else + { + BPoint first, second, third; + + // Sort points according to their y values and x values (y is primary) + if ( (pts[0].y < pts[1].y) || + ((pts[0].y == pts[1].y) && (pts[0].x <= pts[1].x)) ) + { + first=pts[0]; + second=pts[1]; + } + else + { + first=pts[1]; + second=pts[0]; + } + + if ( (second.y= 360) || (span <= -360) ) { - StrokeEllipse(r,driver,setPixel); + StrokeEllipse(r,color); return; } @@ -2345,19 +3195,19 @@ void DisplayDriver::StrokeArc(const BRect &r, const float &angle, const float &s if ( useQuad1 || (!shortspan && (((startQuad == 1) && (x <= startx)) || ((endQuad == 1) && (x >= endx)))) || (shortspan && (startQuad == 1) && (x <= startx) && (x >= endx)) ) - (driver->*setPixel)(ROUND(xc+x),ROUND(yc-y)); + StrokePoint(BPoint(xc+x,yc-y),color); if ( useQuad2 || (!shortspan && (((startQuad == 2) && (x >= startx)) || ((endQuad == 2) && (x <= endx)))) || (shortspan && (startQuad == 2) && (x >= startx) && (x <= endx)) ) - (driver->*setPixel)(ROUND(xc-x),ROUND(yc-y)); + StrokePoint(BPoint(xc-x,yc-y),color); if ( useQuad3 || (!shortspan && (((startQuad == 3) && (x <= startx)) || ((endQuad == 3) && (x >= endx)))) || (shortspan && (startQuad == 3) && (x <= startx) && (x >= endx)) ) - (driver->*setPixel)(ROUND(xc-x),ROUND(yc+y)); + StrokePoint(BPoint(xc-x,yc+y),color); if ( useQuad4 || (!shortspan && (((startQuad == 4) && (x >= startx)) || ((endQuad == 4) && (x <= endx)))) || (shortspan && (startQuad == 4) && (x >= startx) && (x <= endx)) ) - (driver->*setPixel)(ROUND(xc+x),ROUND(yc+y)); + StrokePoint(BPoint(xc+x,yc+y),color); p = ROUND (Ry2 - (Rx2 * ry) + (.25 * Rx2)); while (px < py) @@ -2376,19 +3226,19 @@ void DisplayDriver::StrokeArc(const BRect &r, const float &angle, const float &s if ( useQuad1 || (!shortspan && (((startQuad == 1) && (x <= startx)) || ((endQuad == 1) && (x >= endx)))) || (shortspan && (startQuad == 1) && (x <= startx) && (x >= endx)) ) - (driver->*setPixel)(ROUND(xc+x),ROUND(yc-y)); + StrokePoint(BPoint(xc+x,yc-y),color); if ( useQuad2 || (!shortspan && (((startQuad == 2) && (x >= startx)) || ((endQuad == 2) && (x <= endx)))) || (shortspan && (startQuad == 2) && (x >= startx) && (x <= endx)) ) - (driver->*setPixel)(ROUND(xc-x),ROUND(yc-y)); + StrokePoint(BPoint(xc-x,yc-y),color); if ( useQuad3 || (!shortspan && (((startQuad == 3) && (x <= startx)) || ((endQuad == 3) && (x >= endx)))) || (shortspan && (startQuad == 3) && (x <= startx) && (x >= endx)) ) - (driver->*setPixel)(ROUND(xc-x),ROUND(yc+y)); + StrokePoint(BPoint(xc-x,yc+y),color); if ( useQuad4 || (!shortspan && (((startQuad == 4) && (x >= startx)) || ((endQuad == 4) && (x <= endx)))) || (shortspan && (startQuad == 4) && (x >= startx) && (x <= endx)) ) - (driver->*setPixel)(ROUND(xc+x),ROUND(yc+y)); + StrokePoint(BPoint(xc+x,yc+y),color); } p = ROUND(Ry2*(x+.5)*(x+.5) + Rx2*(y-1)*(y-1) - Rx2*Ry2); @@ -2408,104 +3258,34 @@ void DisplayDriver::StrokeArc(const BRect &r, const float &angle, const float &s if ( useQuad1 || (!shortspan && (((startQuad == 1) && (x <= startx)) || ((endQuad == 1) && (x >= endx)))) || (shortspan && (startQuad == 1) && (x <= startx) && (x >= endx)) ) - (driver->*setPixel)(ROUND(xc+x),ROUND(yc-y)); + StrokePoint(BPoint(xc+x,yc-y),color); if ( useQuad2 || (!shortspan && (((startQuad == 2) && (x >= startx)) || ((endQuad == 2) && (x <= endx)))) || (shortspan && (startQuad == 2) && (x >= startx) && (x <= endx)) ) - (driver->*setPixel)(ROUND(xc-x),ROUND(yc-y)); + StrokePoint(BPoint(xc-x,yc-y),color); if ( useQuad3 || (!shortspan && (((startQuad == 3) && (x <= startx)) || ((endQuad == 3) && (x >= endx)))) || (shortspan && (startQuad == 3) && (x <= startx) && (x >= endx)) ) - (driver->*setPixel)(ROUND(xc-x),ROUND(yc+y)); + StrokePoint(BPoint(xc-x,yc+y),color); if ( useQuad4 || (!shortspan && (((startQuad == 4) && (x >= startx)) || ((endQuad == 4) && (x <= endx)))) || (shortspan && (startQuad == 4) && (x >= startx) && (x <= endx)) ) - (driver->*setPixel)(ROUND(xc+x),ROUND(yc+y)); + StrokePoint(BPoint(xc+x,yc+y),color); } -} - -void DisplayDriver::StrokeBezier(BPoint *pts, const RGBColor &color) -{ -} - -void DisplayDriver::StrokeBezier(BPoint *pts, const DrawData *d) -{ + Unlock(); } /*! - \brief Called for all BView::StrokeBezier calls. - \param pts 4-element array of BPoints in the order of start, end, and then the two control - points. - \param setPixel Pixel drawing function which handles things like size and pattern. + \brief Called for all BView::StrokeArc calls + \param r Rectangle enclosing the entire arc + \param angle Starting angle for the arc in degrees + \param span Span of the arc in degrees. Ending angle = angle+span. + \param d The drawing data for the arc + + This is inefficient and should probably be reworked */ -void DisplayDriver::StrokeBezier(BPoint *pts, DisplayDriver* driver, SetPixelFuncType setPixel) -{ - double Ax, Bx, Cx, Dx; - double Ay, By, Cy, Dy; - int x, y; - int lastx=-1, lasty=-1; - double t; - double dt = .0005; - double dt2, dt3; - double X, Y, dx, ddx, dddx, dy, ddy, dddy; - - Ax = -pts[0].x + 3*pts[1].x - 3*pts[2].x + pts[3].x; - Bx = 3*pts[0].x - 6*pts[1].x + 3*pts[2].x; - Cx = -3*pts[0].x + 3*pts[1].x; - Dx = pts[0].x; - - Ay = -pts[0].y + 3*pts[1].y - 3*pts[2].y + pts[3].y; - By = 3*pts[0].y - 6*pts[1].y + 3*pts[2].y; - Cy = -3*pts[0].y + 3*pts[1].y; - Dy = pts[0].y; - - dt2 = dt * dt; - dt3 = dt2 * dt; - X = Dx; - dx = Ax*dt3 + Bx*dt2 + Cx*dt; - ddx = 6*Ax*dt3 + 2*Bx*dt2; - dddx = 6*Ax*dt3; - Y = Dy; - dy = Ay*dt3 + By*dt2 + Cy*dt; - ddy = 6*Ay*dt3 + 2*By*dt2; - dddy = 6*Ay*dt3; - - lastx = -1; - lasty = -1; - - for (t=0; t<=1; t+=dt) - { - x = ROUND(X); - y = ROUND(Y); - if ( (x!=lastx) || (y!=lasty) ) - (driver->*setPixel)(x,y); - lastx = x; - lasty = y; - - X += dx; - dx += ddx; - ddx += dddx; - Y += dy; - dy += ddy; - ddy += dddy; - } -} - -void DisplayDriver::StrokeEllipse(const BRect &r, const RGBColor &color) -{ -} - -void DisplayDriver::StrokeEllipse(const BRect &r, const DrawData *d) -{ -} - -/*! - \brief Called for all BView::StrokeEllipse calls - \param r BRect enclosing the ellipse to be drawn. - \param setPixel Pixel drawing function which handles things like size and pattern. -*/ -void DisplayDriver::StrokeEllipse(const BRect &r, DisplayDriver* driver, SetPixelFuncType setPixel) +void DisplayDriver::StrokeArc(const BRect &r, const float &angle, const float &span, const DrawData *d) { float xc = (r.left+r.right)/2; float yc = (r.top+r.bottom)/2; @@ -2520,11 +3300,77 @@ void DisplayDriver::StrokeEllipse(const BRect &r, DisplayDriver* driver, SetPixe int y = (int)ry; int px = 0; int py = twoRx2 * y; + int startx, endx; + int startQuad, endQuad; + bool useQuad1, useQuad2, useQuad3, useQuad4; + bool shortspan = false; - (driver->*setPixel)(ROUND(xc+x),ROUND(yc-y)); - (driver->*setPixel)(ROUND(xc-x),ROUND(yc-y)); - (driver->*setPixel)(ROUND(xc-x),ROUND(yc+y)); - (driver->*setPixel)(ROUND(xc+x),ROUND(yc+y)); + Lock(); + + // Watch out for bozos giving us whacko spans + if ( (span >= 360) || (span <= -360) ) + { + StrokeEllipse(r,d); + return; + } + + if ( span > 0 ) + { + startQuad = (int)(angle/90)%4+1; + endQuad = (int)((angle+span)/90)%4+1; + startx = ROUND(.5*r.Width()*fabs(cos(angle*M_PI/180))); + endx = ROUND(.5*r.Width()*fabs(cos((angle+span)*M_PI/180))); + } + else + { + endQuad = (int)(angle/90)%4+1; + startQuad = (int)((angle+span)/90)%4+1; + endx = ROUND(.5*r.Width()*fabs(cos(angle*M_PI/180))); + startx = ROUND(.5*r.Width()*fabs(cos((angle+span)*M_PI/180))); + } + + if ( startQuad != endQuad ) + { + useQuad1 = (endQuad > 1) && (startQuad > endQuad); + useQuad2 = ((startQuad == 1) && (endQuad > 2)) || ((startQuad > endQuad) && (endQuad > 2)); + useQuad3 = ((startQuad < 3) && (endQuad == 4)) || ((startQuad < 3) && (endQuad < startQuad)); + useQuad4 = (startQuad < 4) && (startQuad > endQuad); + } + else + { + if ( (span < 90) && (span > -90) ) + { + useQuad1 = false; + useQuad2 = false; + useQuad3 = false; + useQuad4 = false; + shortspan = true; + } + else + { + useQuad1 = (startQuad != 1); + useQuad2 = (startQuad != 2); + useQuad3 = (startQuad != 3); + useQuad4 = (startQuad != 4); + } + } + + if ( useQuad1 || + (!shortspan && (((startQuad == 1) && (x <= startx)) || ((endQuad == 1) && (x >= endx)))) || + (shortspan && (startQuad == 1) && (x <= startx) && (x >= endx)) ) + StrokePoint(BPoint(xc+x,yc-y),d); + if ( useQuad2 || + (!shortspan && (((startQuad == 2) && (x >= startx)) || ((endQuad == 2) && (x <= endx)))) || + (shortspan && (startQuad == 2) && (x >= startx) && (x <= endx)) ) + StrokePoint(BPoint(xc-x,yc-y),d); + if ( useQuad3 || + (!shortspan && (((startQuad == 3) && (x <= startx)) || ((endQuad == 3) && (x >= endx)))) || + (shortspan && (startQuad == 3) && (x <= startx) && (x >= endx)) ) + StrokePoint(BPoint(xc-x,yc+y),d); + if ( useQuad4 || + (!shortspan && (((startQuad == 4) && (x >= startx)) || ((endQuad == 4) && (x <= endx)))) || + (shortspan && (startQuad == 4) && (x >= startx) && (x <= endx)) ) + StrokePoint(BPoint(xc+x,yc+y),d); p = ROUND (Ry2 - (Rx2 * ry) + (.25 * Rx2)); while (px < py) @@ -2540,10 +3386,22 @@ void DisplayDriver::StrokeEllipse(const BRect &r, DisplayDriver* driver, SetPixe p += Ry2 + px - py; } - (driver->*setPixel)(ROUND(xc+x),ROUND(yc-y)); - (driver->*setPixel)(ROUND(xc-x),ROUND(yc-y)); - (driver->*setPixel)(ROUND(xc-x),ROUND(yc+y)); - (driver->*setPixel)(ROUND(xc+x),ROUND(yc+y)); + if ( useQuad1 || + (!shortspan && (((startQuad == 1) && (x <= startx)) || ((endQuad == 1) && (x >= endx)))) || + (shortspan && (startQuad == 1) && (x <= startx) && (x >= endx)) ) + StrokePoint(BPoint(xc+x,yc-y),d); + if ( useQuad2 || + (!shortspan && (((startQuad == 2) && (x >= startx)) || ((endQuad == 2) && (x <= endx)))) || + (shortspan && (startQuad == 2) && (x >= startx) && (x <= endx)) ) + StrokePoint(BPoint(xc-x,yc-y),d); + if ( useQuad3 || + (!shortspan && (((startQuad == 3) && (x <= startx)) || ((endQuad == 3) && (x >= endx)))) || + (shortspan && (startQuad == 3) && (x <= startx) && (x >= endx)) ) + StrokePoint(BPoint(xc-x,yc+y),d); + if ( useQuad4 || + (!shortspan && (((startQuad == 4) && (x >= startx)) || ((endQuad == 4) && (x <= endx)))) || + (shortspan && (startQuad == 4) && (x >= startx) && (x <= endx)) ) + StrokePoint(BPoint(xc+x,yc+y),d); } p = ROUND(Ry2*(x+.5)*(x+.5) + Rx2*(y-1)*(y-1) - Rx2*Ry2); @@ -2560,28 +3418,322 @@ void DisplayDriver::StrokeEllipse(const BRect &r, DisplayDriver* driver, SetPixe p += Rx2 - py +px; } - (driver->*setPixel)(ROUND(xc+x),ROUND(yc-y)); - (driver->*setPixel)(ROUND(xc-x),ROUND(yc-y)); - (driver->*setPixel)(ROUND(xc-x),ROUND(yc+y)); - (driver->*setPixel)(ROUND(xc+x),ROUND(yc+y)); + if ( useQuad1 || + (!shortspan && (((startQuad == 1) && (x <= startx)) || ((endQuad == 1) && (x >= endx)))) || + (shortspan && (startQuad == 1) && (x <= startx) && (x >= endx)) ) + StrokePoint(BPoint(xc+x,yc-y),d); + if ( useQuad2 || + (!shortspan && (((startQuad == 2) && (x >= startx)) || ((endQuad == 2) && (x <= endx)))) || + (shortspan && (startQuad == 2) && (x >= startx) && (x <= endx)) ) + StrokePoint(BPoint(xc-x,yc-y),d); + if ( useQuad3 || + (!shortspan && (((startQuad == 3) && (x <= startx)) || ((endQuad == 3) && (x >= endx)))) || + (shortspan && (startQuad == 3) && (x <= startx) && (x >= endx)) ) + StrokePoint(BPoint(xc-x,yc+y),d); + if ( useQuad4 || + (!shortspan && (((startQuad == 4) && (x >= startx)) || ((endQuad == 4) && (x <= endx)))) || + (shortspan && (startQuad == 4) && (x >= startx) && (x <= endx)) ) + StrokePoint(BPoint(xc+x,yc+y),d); } -} -void DisplayDriver::StrokeLine(const BPoint &start, const BPoint &end, const RGBColor &color) -{ - Lock(); - //Not quite that simple bub - REDO!!! - StrokeSolidLine(start,end,color); Unlock(); } +/*! + \brief Called for all BView::StrokeBezier calls. + \param pts 4-element array of BPoints in the order of start, end, and then the two control points. + \param color draw color +*/ +void DisplayDriver::StrokeBezier(BPoint *pts, const RGBColor &color) +{ + int i, numLines; + + Lock(); + BezierCurve curve(pts); + + numLines = curve.points.CountItems()-1; + for (i=0; i0) + { + lastx = x; + lasty = y; + y--; + py -= twoRx2; + if (p>0) + p += Rx2 - py; + else + { + x++; + px += twoRy2; + p += Rx2 - py +px; + } + + StrokeLine(BPoint(xc+lastx,yc-lasty),BPoint(xc+x,yc-y),color); + StrokeLine(BPoint(xc-lastx,yc-lasty),BPoint(xc-x,yc-y),color); + StrokeLine(BPoint(xc-lastx,yc+lasty),BPoint(xc-x,yc+y),color); + StrokeLine(BPoint(xc+lastx,yc+lasty),BPoint(xc+x,yc+y),color); + } + + Unlock(); +} + +/*! + \brief Called for all BView::StrokeEllipse calls + \param r BRect enclosing the ellipse to be drawn. + \param d Drawing data for the ellipse +*/ +void DisplayDriver::StrokeEllipse(const BRect &r, const DrawData *d) +{ + float xc = (r.left+r.right)/2; + float yc = (r.top+r.bottom)/2; + float rx = r.Width()/2; + float ry = r.Height()/2; + int Rx2 = ROUND(rx*rx); + int Ry2 = ROUND(ry*ry); + int twoRx2 = 2*Rx2; + int twoRy2 = 2*Ry2; + int p; + int x=0; + int y = (int)ry; + int px = 0; + int py = twoRx2 * y; + int lastx, lasty; + + Lock(); + + p = ROUND (Ry2 - (Rx2 * ry) + (.25 * Rx2)); + while (px < py) + { + lastx = x; + lasty = y; + x++; + px += twoRy2; + if ( p < 0 ) + p += Ry2 + px; + else + { + y--; + py -= twoRx2; + p += Ry2 + px - py; + } + + StrokeLine(BPoint(xc+lastx,yc-lasty),BPoint(xc+x,yc-y),d); + StrokeLine(BPoint(xc-lastx,yc-lasty),BPoint(xc-x,yc-y),d); + StrokeLine(BPoint(xc-lastx,yc+lasty),BPoint(xc-x,yc+y),d); + StrokeLine(BPoint(xc+lastx,yc+lasty),BPoint(xc+x,yc+y),d); + } + + p = ROUND(Ry2*(x+.5)*(x+.5) + Rx2*(y-1)*(y-1) - Rx2*Ry2); + while (y>0) + { + lastx = x; + lasty = y; + y--; + py -= twoRx2; + if (p>0) + p += Rx2 - py; + else + { + x++; + px += twoRy2; + p += Rx2 - py +px; + } + + StrokeLine(BPoint(xc+lastx,yc-lasty),BPoint(xc+x,yc-y),d); + StrokeLine(BPoint(xc-lastx,yc-lasty),BPoint(xc-x,yc-y),d); + StrokeLine(BPoint(xc-lastx,yc+lasty),BPoint(xc-x,yc+y),d); + StrokeLine(BPoint(xc+lastx,yc+lasty),BPoint(xc+x,yc+y),d); + } + + Unlock(); +} + +/*! + \brief Draws a line. Really. + \param start Starting point + \param end Ending point + \param c The color of the line +*/ +void DisplayDriver::StrokeLine(const BPoint &start, const BPoint &end, const RGBColor &color) +{ + Lock(); + StrokeSolidLine(ROUND(start.x),ROUND(start.y),ROUND(end.x),ROUND(end.y),color); + Unlock(); +} + +/*! + \brief Draws a line. Really. + \param start Starting point + \param end Ending point + \param d The relevant drawing data for this line +*/ void DisplayDriver::StrokeLine(const BPoint &start, const BPoint &end, const DrawData *d) { -// TODO: IMPLEMENT!!! This is TEMPORARY!!! Lock(); - //Not quite that simple bub - REDO!!! - RGBColor c = d->highcolor; - StrokeSolidLine(start,end,c); + if ( d->pensize == 1 ) + { + if ( d->clipReg ) + { + int i, numRects; + double left, right, y1, y2; + BRect clipRect; + LineCalc line(start,end); + numRects = d->clipReg->CountRects(); + for (i=0; iclipReg->RectAt(i); + left = MAX(line.MinX(), clipRect.left); + right = MIN(line.MaxX(), clipRect.right); + if ( right < left ) + continue; + y1 = line.GetY(left); + y2 = line.GetY(right); + if ( MAX(y1,y2) < clipRect.top ) + continue; + if ( MIN(y1,y2) > clipRect.bottom ) + continue; + if ( y1 < clipRect.top ) + { + y1 = clipRect.top; + left = line.GetX(y1); + } + if ( y1 > clipRect.bottom ) + { + y1 = clipRect.bottom; + left = line.GetX(y1); + } + if ( y2 < clipRect.top ) + { + y2 = clipRect.top; + right = line.GetX(y2); + } + if ( y2 > clipRect.bottom ) + { + y2 = clipRect.bottom; + right = line.GetX(y2); + } + StrokePatternLine(ROUND(left),ROUND(y1),ROUND(right),ROUND(y2),d); + } + } + else + StrokePatternLine(ROUND(start.x),ROUND(start.y),ROUND(end.x),ROUND(end.y),d); + } + else + { + BPoint corners[4]; + double halfWidth = .5*d->pensize; + corners[0] = start; + corners[1] = start; + corners[2] = end; + corners[3] = end; + if ( (start.x == end.x) && (start.y == end.y) ) + { + FillRect(BRect(start.x-halfWidth,start.y-halfWidth,start.x+halfWidth,start.y+halfWidth),d); + } + else + { + if ( start.x == end.x ) + { + corners[0].x += halfWidth; + corners[1].x -= halfWidth; + corners[2].x -= halfWidth; + corners[3].x += halfWidth; + } + else if ( start.y == end.y ) + { + corners[0].y -= halfWidth; + corners[1].y += halfWidth; + corners[2].y += halfWidth; + corners[3].y -= halfWidth; + } + else + { + double angle, xoffset, yoffset; + // TODO try to find a way to avoid atan2, sin, and cos + angle = atan2(end.y-start.y, end.x-start.x) + M_PI/4; + xoffset = halfWidth*cos(angle); + yoffset = halfWidth*sin(angle); + corners[0].x += xoffset; + corners[0].y += yoffset; + corners[1].x -= xoffset; + corners[1].y -= yoffset; + corners[2].x -= xoffset; + corners[2].y -= yoffset; + corners[3].x += xoffset; + corners[3].y += yoffset; + } + FillPolygon(corners,4,d); + } + } Unlock(); } @@ -2620,23 +3772,26 @@ void DisplayDriver::StrokeLine(const BPoint &start, const BPoint &end, DisplayDr } } -void DisplayDriver::StrokePoint(BPoint& pt, const RGBColor &color) +void DisplayDriver::StrokePoint(const BPoint& pt, const RGBColor &color) { StrokeLine(pt, pt, color); } +void DisplayDriver::StrokePoint(const BPoint& pt, const DrawData *d) +{ + StrokeLine(pt, pt, d); +} + void DisplayDriver::StrokePolygon(BPoint *ptlist, int32 numpts, const RGBColor &color, bool is_closed) { if(!ptlist) return; Lock(); - /* for(int32 i=0; i<(numpts-1); i++) - StrokeSolidLine(ptlist[i],ptlist[i+1],color); + StrokeLine(ptlist[i],ptlist[i+1],color); if(is_closed) - StrokeSolidLine(ptlist[numpts-1],ptlist[0],color); - */ + StrokeLine(ptlist[numpts-1],ptlist[0],color); Unlock(); } @@ -2668,7 +3823,10 @@ void DisplayDriver::StrokePolygon(BPoint *ptlist, int32 numpts, const DrawData * void DisplayDriver::StrokeRect(const BRect &r, const RGBColor &color) { Lock(); - StrokeSolidRect(r,color); + StrokeLine(r.LeftTop(),r.RightTop(),color); + StrokeLine(r.LeftTop(),r.LeftBottom(),color); + StrokeLine(r.RightTop(),r.RightBottom(),color); + StrokeLine(r.LeftBottom(),r.RightBottom(),color); Unlock(); } @@ -2711,6 +3869,32 @@ void DisplayDriver::StrokeRegion(BRegion& r, const DrawData *d) void DisplayDriver::StrokeRoundRect(const BRect &r, const float &xrad, const float &yrad, const RGBColor &color) { + int hLeft, hRight; + int vTop, vBottom; + float bLeft, bRight, bTop, bBottom; + + hLeft = (int)ROUND(r.left + xrad); + hRight = (int)ROUND(r.right - xrad); + vTop = (int)ROUND(r.top + yrad); + vBottom = (int)ROUND(r.bottom - yrad); + bLeft = hLeft + xrad; + bRight = hRight -xrad; + bTop = vTop + yrad; + bBottom = vBottom - yrad; + + Lock(); + StrokeArc(BRect(bRight, r.top, r.right, bTop), 0, 90, color); + StrokeLine(BPoint(hRight, r.top), BPoint(hLeft, r.top), color); + + StrokeArc(BRect(r.left,r.top,bLeft,bTop), 90, 90, color); + StrokeLine(BPoint(r.left, vTop), BPoint(r.left, vBottom), color); + + StrokeArc(BRect(r.left,bBottom,bLeft,r.bottom), 180, 90, color); + StrokeLine(BPoint(hLeft, r.bottom), BPoint(hRight, r.bottom), color); + + StrokeArc(BRect(bRight,bBottom,r.right,r.bottom), 270, 90, color); + StrokeLine(BPoint(r.right, vBottom), BPoint(r.right, vTop), color); + Unlock(); } /*! @@ -2787,6 +3971,19 @@ void DisplayDriver::StrokeTriangle(BPoint *pts, const DrawData *d) */ void DisplayDriver::StrokeLineArray(BPoint *pts, const int32 &numlines, const DrawData *d, RGBColor *colors) { + int i; + DrawData data; + + Lock(); + + data = *d; + for (i=0; iclippReg) - _full.IntersectWith( ld->clippReg ); + if(ld->clipReg) + _full.IntersectWith( ld->clipReg ); } while( (ld = ld->prevState) ); // clip to user picture region diff --git a/src/servers/app/server/LayerData.cpp b/src/servers/app/server/LayerData.cpp index f647090062..452a5be8fd 100644 --- a/src/servers/app/server/LayerData.cpp +++ b/src/servers/app/server/LayerData.cpp @@ -52,7 +52,7 @@ DrawData::DrawData(void) if(fontserver) font=*(fontserver->GetSystemPlain()); - clippReg=NULL; + clipReg=NULL; edelta.space=0; edelta.nonspace=0; @@ -60,8 +60,8 @@ DrawData::DrawData(void) DrawData::~DrawData(void) { - if (clippReg) - delete clippReg; + if (clipReg) + delete clipReg; } DrawData::DrawData(const DrawData &data) @@ -90,12 +90,12 @@ DrawData &DrawData::operator=(const DrawData &from) fontAliasing=from.fontAliasing; font=from.font; - if(from.clippReg) + if(from.clipReg) { - if(clippReg) - *clippReg=*(from.clippReg); + if(clipReg) + *clipReg=*(from.clipReg); else - clippReg=new BRegion(*(from.clippReg)); + clipReg=new BRegion(*(from.clipReg)); } edelta=from.edelta; @@ -150,12 +150,12 @@ LayerData &LayerData::operator=(const LayerData &from) fontAliasing=from.fontAliasing; font=from.font; - if(from.clippReg) + if(from.clipReg) { - if(clippReg) - *clippReg=*(from.clippReg); + if(clipReg) + *clipReg=*(from.clipReg); else - clippReg=new BRegion(*(from.clippReg)); + clipReg=new BRegion(*(from.clipReg)); } edelta=from.edelta; @@ -182,8 +182,8 @@ void LayerData::PrintToStream() const{ printf("\t LineCap: %d\t LineJoin: %d\t MiterLimit: %f\n", (int16)lineCap, (int16)lineJoin, miterLimit); printf("\t AlphaSrcMode: %ld\t AlphaFncMode: %ld\n", (int32)alphaSrcMode, (int32)alphaFncMode); printf("\t Scale: %f\n", scale); - if (clippReg) - clippReg->PrintToStream(); + if (clipReg) + clipReg->PrintToStream(); printf("\t ===== Font Data =====\n"); printf("\t FontStyle: CURRENTLY NOT SET\n"); diff --git a/src/servers/app/server/ServerWindow.cpp b/src/servers/app/server/ServerWindow.cpp index 0495395f7a..4ebe43132a 100644 --- a/src/servers/app/server/ServerWindow.cpp +++ b/src/servers/app/server/ServerWindow.cpp @@ -595,7 +595,7 @@ void ServerWindow::SetLayerState(Layer *layer){ lowColor, viewColor; pattern patt; - int32 clippRegRects; + int32 clipRegRects; fSession->ReadPoint( &(layer->_layerdata->penlocation)); fSession->ReadFloat( &(layer->_layerdata->pensize)); @@ -612,30 +612,30 @@ void ServerWindow::SetLayerState(Layer *layer){ fSession->ReadInt8((int8*) &(layer->_layerdata->alphaFncMode)); fSession->ReadFloat( &(layer->_layerdata->scale)); fSession->ReadBool( &(layer->_layerdata->fontAliasing)); - fSession->ReadInt32( &clippRegRects); + fSession->ReadInt32( &clipRegRects); layer->_layerdata->patt.Set(*((uint64*)&patt)); layer->_layerdata->highcolor.SetColor(highColor); layer->_layerdata->lowcolor.SetColor(lowColor); layer->_layerdata->viewcolor.SetColor(viewColor); - if(clippRegRects != 0){ - if(layer->_layerdata->clippReg == NULL) - layer->_layerdata->clippReg = new BRegion(); + if(clipRegRects != 0){ + if(layer->_layerdata->clipReg == NULL) + layer->_layerdata->clipReg = new BRegion(); else - layer->_layerdata->clippReg->MakeEmpty(); + layer->_layerdata->clipReg->MakeEmpty(); BRect rect; - for(int32 i = 0; i < clippRegRects; i++){ + for(int32 i = 0; i < clipRegRects; i++){ fSession->ReadRect(&rect); - layer->_layerdata->clippReg->Include(rect); + layer->_layerdata->clipReg->Include(rect); } } else{ - if (layer->_layerdata->clippReg){ - delete layer->_layerdata->clippReg; - layer->_layerdata->clippReg = NULL; + if (layer->_layerdata->clipReg){ + delete layer->_layerdata->clipReg; + layer->_layerdata->clipReg = NULL; } } STRACE(("DONE: ServerWindow %s: Message AS_LAYER_SET_STATE: Layer: %s\n",fTitle.String(), layer->_name->String())); @@ -890,13 +890,13 @@ void ServerWindow::DispatchMessage(int32 code) fSession->WriteFloat(ld->fontAliasing); int32 noOfRects = 0; - if (ld->clippReg) - noOfRects = ld->clippReg->CountRects(); + if (ld->clipReg) + noOfRects = ld->clipReg->CountRects(); fSession->WriteInt32(noOfRects); for(int i = 0; i < noOfRects; i++){ - fSession->WriteRect(ld->clippReg->RectAt(i)); + fSession->WriteRect(ld->clipReg->RectAt(i)); } fSession->WriteFloat(cl->_frame.left); @@ -1331,12 +1331,12 @@ void ServerWindow::DispatchMessage(int32 code) ld = cl->_layerdata; reg = cl->ConvertFromParent(&(cl->_visible)); - if(ld->clippReg) - reg.IntersectWith(ld->clippReg); + if(ld->clipReg) + reg.IntersectWith(ld->clipReg); while((ld = ld->prevState)) - if(ld->clippReg) - reg.IntersectWith(ld->clippReg); + if(ld->clipReg) + reg.IntersectWith(ld->clipReg); noOfRects = reg.CountRects(); fSession->WriteInt32(noOfRects); @@ -1356,16 +1356,16 @@ void ServerWindow::DispatchMessage(int32 code) int32 noOfRects; BRect r; - if(cl->_layerdata->clippReg) - cl->_layerdata->clippReg->MakeEmpty(); + if(cl->_layerdata->clipReg) + cl->_layerdata->clipReg->MakeEmpty(); else - cl->_layerdata->clippReg = new BRegion(); + cl->_layerdata->clipReg = new BRegion(); fSession->ReadInt32(&noOfRects); for(int i = 0; i < noOfRects; i++){ fSession->ReadRect(&r); - cl->_layerdata->clippReg->Include(r); + cl->_layerdata->clipReg->Include(r); } cl->RebuildFullRegion(); diff --git a/src/servers/app/server/ViewDriver.cpp b/src/servers/app/server/ViewDriver.cpp index 9534e36ba0..7e15818dbf 100644 --- a/src/servers/app/server/ViewDriver.cpp +++ b/src/servers/app/server/ViewDriver.cpp @@ -706,7 +706,7 @@ void ViewDriver::StrokePatternLine(int32 x1, int32 y1, int32 x2, int32 y2, const screenwin->Unlock(); } -void ViewDriver::StrokeSolidLine(const BPoint &start, const BPoint &end, const RGBColor &color) +void ViewDriver::StrokeSolidLine(int32 x1, int32 y1, int32 x2, int32 y2, const RGBColor &color) { if(!is_initialized) return; @@ -714,9 +714,9 @@ void ViewDriver::StrokeSolidLine(const BPoint &start, const BPoint &end, const R screenwin->Lock(); framebuffer->Lock(); drawview->SetHighColor(color.GetColor32()); - drawview->StrokeLine(start,end); + drawview->StrokeLine(BPoint(x1,y1),BPoint(x2,y2)); drawview->Sync(); - screenwin->view->Invalidate(BRect(start,end)); + screenwin->view->Invalidate(BRect(x1,y1,x2,y2)); framebuffer->Unlock(); screenwin->Unlock(); } diff --git a/src/servers/app/server/ViewDriver.h b/src/servers/app/server/ViewDriver.h index db652ede3d..2ef02aabd7 100644 --- a/src/servers/app/server/ViewDriver.h +++ b/src/servers/app/server/ViewDriver.h @@ -133,7 +133,7 @@ protected: virtual void FillSolidRect(const BRect &rect, const RGBColor &color); virtual void FillPatternRect(const BRect &rect, const DrawData *d); virtual void StrokeSolidRect(const BRect &rect, const RGBColor &color); - virtual void StrokeSolidLine(const BPoint &start, const BPoint &end, + virtual void StrokeSolidLine(int32 x1, int32 y1, int32 x2, int32 y2, const RGBColor &color); virtual void SetDrawData(const DrawData *d, bool set_font_data=false); virtual void StrokePatternLine(int32 x1, int32 y1, int32 x2, int32 y2, diff --git a/src/servers/app/server/WinBorder.cpp b/src/servers/app/server/WinBorder.cpp index cc01161f93..ad64ac9bc3 100644 --- a/src/servers/app/server/WinBorder.cpp +++ b/src/servers/app/server/WinBorder.cpp @@ -140,8 +140,8 @@ void WinBorder::RebuildFullRegion(void){ ld = topLayer->_layerdata; do{ // clip to user region - if(ld->clippReg) - topLayerFull.IntersectWith( ld->clippReg ); + if(ld->clipReg) + topLayerFull.IntersectWith( ld->clipReg ); } while( (ld = ld->prevState) ); // clip to user picture region