From a8cb43fea1b9901d9a1ff09e4e3395ce9e08c457 Mon Sep 17 00:00:00 2001 From: shadow303 Date: Mon, 3 Nov 2003 01:51:50 +0000 Subject: [PATCH] Reduce redundant code in drivers (we can unvirtualize stuff as speed requires after implementation is complete) Fix some color handling for 15/16 bit. Implement HLine functions for BitmapDriver. I forget what I did to Clipper. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5243 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/servers/app/server/AccelerantDriver.cpp | 1565 +------------------ src/servers/app/server/AccelerantDriver.h | 55 - src/servers/app/server/BitmapDriver.cpp | 1495 ++---------------- src/servers/app/server/BitmapDriver.h | 14 - src/servers/app/server/Clipper.cpp | 50 +- src/servers/app/server/Clipper.h | 42 +- src/servers/app/server/DisplayDriver.cpp | 1400 +++++++++++++++++ src/servers/app/server/RGBColor.cpp | 17 +- 8 files changed, 1573 insertions(+), 3065 deletions(-) diff --git a/src/servers/app/server/AccelerantDriver.cpp b/src/servers/app/server/AccelerantDriver.cpp index 7b952268f8..6229acc489 100644 --- a/src/servers/app/server/AccelerantDriver.cpp +++ b/src/servers/app/server/AccelerantDriver.cpp @@ -38,7 +38,6 @@ #include #include - #define RUN_UNDER_R5 #define CLIP_X(a) ( (a < 0) ? 0 : ((a > mDisplayMode.virtual_width-1) ? \ @@ -50,77 +49,6 @@ /* TODO: Add handling of draw modes */ -AccLineCalc::AccLineCalc() -{ -} - -AccLineCalc::AccLineCalc(const BPoint &pta, const BPoint &ptb) -{ - start=pta; - end=ptb; - slope=(start.y-end.y)/(start.x-end.x); - offset=start.y-(slope * start.x); - minx = MIN(start.x,end.x); - maxx = MAX(start.x,end.x); - miny = MIN(start.y,end.y); - maxy = MAX(start.y,end.y); -} - -void AccLineCalc::SetPoints(const BPoint &pta, const BPoint &ptb) -{ - start=pta; - end=ptb; - slope=(start.y-end.y)/(start.x-end.x); - offset=start.y-(slope * start.x); - minx = MIN(start.x,end.x); - maxx = MAX(start.x,end.x); - miny = MIN(start.y,end.y); - maxy = MAX(start.y,end.y); -} - -void AccLineCalc::Swap(AccLineCalc &from) -{ - BPoint pta, ptb; - pta = start; - ptb = end; - SetPoints(from.start,from.end); - from.SetPoints(pta,ptb); -} - -float AccLineCalc::GetX(float y) -{ - if (start.x == end.x) - return start.x; - return ( (y-offset)/slope ); -} - -float AccLineCalc::MinX() -{ - return minx; -} - -float AccLineCalc::MaxX() -{ - return maxx; -} - -float AccLineCalc::GetY(float x) -{ - if ( start.x == end.x ) - return start.y; - return ( (slope * x) + offset ); -} - -float AccLineCalc::MinY() -{ - return miny; -} - -float AccLineCalc::MaxY() -{ - return maxy; -} - /*! \brief Sets up internal variables needed by AccelerantDriver @@ -471,852 +399,6 @@ void AccelerantDriver::DrawString(const char *string, int32 length, BPoint pt, L 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 Data structure containing any other data necessary for the call. Always non-NULL. - \param pat 8-byte array containing the pattern to use. Always non-NULL. - - Bounds checking must be done in this call because only part of the arc may end up - being clipped. -*/ -void AccelerantDriver::FillArc(BRect r, float angle, float span, LayerData *d, const Pattern &pat) -{ - 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; - float oldpensize; - BPoint center(xc,yc); - - // Watch out for bozos giving us whacko spans - if ( (span >= 360) || (span <= -360) ) - { - FillEllipse(r,d,pat); - return; - } - - Lock(); - PatternHandler pattern(pat); - pattern.SetColors(d->highcolor, d->lowcolor); - oldpensize = d->pensize; - d->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 && CHECK_Y(yc-y) && (CHECK_X(xc) || CHECK_X(xc+x)) ) - HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc+x)),ROUND(yc-y),&pattern); - if ( useQuad2 && CHECK_Y(yc-y) && (CHECK_X(xc) || CHECK_X(xc-x)) ) - HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc-x)),ROUND(yc-y),&pattern); - if ( useQuad3 && CHECK_Y(yc+y) && (CHECK_X(xc) || CHECK_X(xc-x)) ) - HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc-x)),ROUND(yc+y),&pattern); - if ( useQuad4 && CHECK_Y(yc+y) && (CHECK_X(xc) || CHECK_X(xc+x)) ) - HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc+x)),ROUND(yc+y),&pattern); - if ( (!shortspan && (((startQuad == 1) && (x <= startx)) || ((endQuad == 1) && (x >= endx)))) || - (shortspan && (startQuad == 1) && (x <= startx) && (x >= endx)) ) - StrokeLine(BPoint(xc+x,yc-y),center,d,pat); - if ( (!shortspan && (((startQuad == 2) && (x >= startx)) || ((endQuad == 2) && (x <= endx)))) || - (shortspan && (startQuad == 2) && (x >= startx) && (x <= endx)) ) - StrokeLine(BPoint(xc-x,yc-y),center,d,pat); - if ( (!shortspan && (((startQuad == 3) && (x <= startx)) || ((endQuad == 3) && (x >= endx)))) || - (shortspan && (startQuad == 3) && (x <= startx) && (x >= endx)) ) - StrokeLine(BPoint(xc-x,yc+y),center,d,pat); - if ( (!shortspan && (((startQuad == 4) && (x >= startx)) || ((endQuad == 4) && (x <= endx)))) || - (shortspan && (startQuad == 4) && (x >= startx) && (x <= endx)) ) - StrokeLine(BPoint(xc+x,yc+y),center,d,pat); - - 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 && CHECK_Y(yc-y) && (CHECK_X(xc) || CHECK_X(xc+x)) ) - HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc+x)),ROUND(yc-y),&pattern); - if ( useQuad2 && CHECK_Y(yc-y) && (CHECK_X(xc) || CHECK_X(xc-x)) ) - HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc-x)),ROUND(yc-y),&pattern); - if ( useQuad3 && CHECK_Y(yc+y) && (CHECK_X(xc) || CHECK_X(xc-x)) ) - HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc-x)),ROUND(yc+y),&pattern); - if ( useQuad4 && CHECK_Y(yc+y) && (CHECK_X(xc) || CHECK_X(xc+x)) ) - HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc+x)),ROUND(yc+y),&pattern); - if ( !shortspan ) - { - if ( startQuad == 1 ) - { - if ( CHECK_Y(yc-y) ) - { - if ( x <= startx ) - { - if ( CHECK_X(xc) || CHECK_X(xc+x) ) - HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc+x)),ROUND(yc-y),&pattern); - } - else - { - xclip = ROUND(y*startx/(double)starty); - if ( CHECK_X(xc) || CHECK_X(xc+xclip) ) - HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc+xclip)),ROUND(yc-y),&pattern); - } - } - } - else if ( startQuad == 2 ) - { - if ( CHECK_Y(yc-y) ) - { - if ( x >= startx ) - { - xclip = ROUND(y*startx/(double)starty); - if ( CHECK_X(xc-x) || CHECK_X(xc-xclip) ) - HLine(ROUND(CLIP_X(xc-x)),ROUND(CLIP_X(xc-xclip)),ROUND(yc-y),&pattern); - } - } - } - else if ( startQuad == 3 ) - { - if ( CHECK_Y(yc+y) ) - { - if ( x <= startx ) - { - if ( CHECK_X(xc-x) || CHECK_X(xc) ) - HLine(ROUND(CLIP_X(xc-x)),ROUND(CLIP_X(xc)),ROUND(yc+y),&pattern); - } - else - { - xclip = ROUND(y*startx/(double)starty); - if ( CHECK_X(xc-xclip) || CHECK_X(xc) ) - HLine(ROUND(CLIP_X(xc-xclip)),ROUND(CLIP_X(xc)),ROUND(yc+y),&pattern); - } - } - } - else if ( startQuad == 4 ) - { - if ( CHECK_Y(yc+y) ) - { - if ( x >= startx ) - { - xclip = ROUND(y*startx/(double)starty); - if ( CHECK_X(xc+xclip) || CHECK_X(xc+x) ) - HLine(ROUND(CLIP_X(xc+xclip)),ROUND(CLIP_X(xc+x)),ROUND(yc+y),&pattern); - } - } - } - - if ( endQuad == 1 ) - { - if ( CHECK_Y(yc-y) ) - { - if ( x >= endx ) - { - xclip = ROUND(y*endx/(double)endy); - if ( CHECK_X(xc+xclip) || CHECK_X(xc+x) ) - HLine(ROUND(CLIP_X(xc+xclip)),ROUND(CLIP_X(xc+x)),ROUND(yc-y),&pattern); - } - } - } - else if ( endQuad == 2 ) - { - if ( CHECK_Y(yc-y) ) - { - if ( x <= endx ) - { - if ( CHECK_X(xc-x) || CHECK_X(xc) ) - HLine(ROUND(CLIP_X(xc-x)),ROUND(CLIP_X(xc)),ROUND(yc-y),&pattern); - } - else - { - xclip = ROUND(y*endx/(double)endy); - if ( CHECK_X(xc-xclip) || CHECK_X(xc) ) - HLine(ROUND(CLIP_X(xc-xclip)),ROUND(CLIP_X(xc)),ROUND(yc-y),&pattern); - } - } - } - else if ( endQuad == 3 ) - { - if ( CHECK_Y(yc+y) ) - { - if ( x >= endx ) - { - xclip = ROUND(y*endx/(double)endy); - if ( CHECK_X(xc-x) || CHECK_X(xc-xclip) ) - HLine(ROUND(CLIP_X(xc-x)),ROUND(CLIP_X(xc-xclip)),ROUND(yc+y),&pattern); - } - } - } - else if ( endQuad == 4 ) - { - if ( CHECK_Y(yc+y) ) - { - if ( x <= endx ) - { - if ( CHECK_X(xc) || CHECK_X(xc+x) ) - HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc+x)),ROUND(yc+y),&pattern); - } - else - { - xclip = ROUND(y*endx/(double)endy); - if ( CHECK_X(xc) || CHECK_X(xc+xclip) ) - HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc+xclip)),ROUND(yc+y),&pattern); - } - } - } - } - else - { - startclip = ROUND(y*startx/(double)starty); - endclip = ROUND(y*endx/(double)endy); - if ( startQuad == 1 ) - { - if ( CHECK_Y(yc-y) ) - { - if ( (x <= startx) && (x >= endx) ) - { - if ( CHECK_X(xc+endclip) || CHECK_X(xc+x) ) - HLine(ROUND(CLIP_X(xc+endclip)),ROUND(CLIP_X(xc+x)),ROUND(yc-y),&pattern); - } - else - { - if ( CHECK_X(xc+endclip) || CHECK_X(xc+startclip) ) - HLine(ROUND(CLIP_X(xc+endclip)),ROUND(CLIP_X(xc+startclip)),ROUND(yc-y),&pattern); - } - } - } - else if ( startQuad == 2 ) - { - if ( CHECK_Y(yc-y) ) - { - if ( (x <= startx) && (x >= endx) ) - { - if ( CHECK_X(xc-x) || CHECK_X(xc-startclip) ) - HLine(ROUND(CLIP_X(xc-x)),ROUND(CLIP_X(xc-startclip)),ROUND(yc-y),&pattern); - } - else - { - if ( CHECK_X(xc-endclip) || CHECK_X(xc-startclip) ) - HLine(ROUND(CLIP_X(xc-endclip)),ROUND(CLIP_X(xc-startclip)),ROUND(yc-y),&pattern); - } - } - } - else if ( startQuad == 3 ) - { - if ( CHECK_Y(yc+y) ) - { - if ( (x <= startx) && (x >= endx) ) - { - if ( CHECK_X(xc-x) || CHECK_X(xc-endclip) ) - HLine(ROUND(CLIP_X(xc-x)),ROUND(CLIP_X(xc-endclip)),ROUND(yc+y),&pattern); - } - else - { - if ( CHECK_X(xc-startclip) || CHECK_X(xc-endclip) ) - HLine(ROUND(CLIP_X(xc-startclip)),ROUND(CLIP_X(xc-endclip)),ROUND(yc+y),&pattern); - } - } - } - else if ( startQuad == 4 ) - { - if ( CHECK_Y(yc+y) ) - { - if ( (x <= startx) && (x >= endx) ) - { - if ( CHECK_X(xc+startclip) || CHECK_X(xc+x) ) - HLine(ROUND(CLIP_X(xc+startclip)),ROUND(CLIP_X(xc+x)),ROUND(yc+y),&pattern); - } - else - { - if ( CHECK_X(xc+startclip) || CHECK_X(xc+endclip) ) - HLine(ROUND(CLIP_X(xc+startclip)),ROUND(CLIP_X(xc+endclip)),ROUND(yc+y),&pattern); - } - } - } - } - } - - 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 && CHECK_Y(yc-y) && (CHECK_X(xc) || CHECK_X(xc+x)) ) - HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc+x)),ROUND(yc-y),&pattern); - if ( useQuad2 && CHECK_Y(yc-y) && (CHECK_X(xc) || CHECK_X(xc-x)) ) - HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc-x)),ROUND(yc-y),&pattern); - if ( useQuad3 && CHECK_Y(yc+y) && (CHECK_X(xc) || CHECK_X(xc-x)) ) - HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc-x)),ROUND(yc+y),&pattern); - if ( useQuad4 && CHECK_Y(yc+y) && (CHECK_X(xc) || CHECK_X(xc+x)) ) - HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc+x)),ROUND(yc+y),&pattern); - if ( !shortspan ) - { - if ( startQuad == 1 ) - { - if ( CHECK_Y(yc-y) ) - { - if ( x <= startx ) - { - if ( CHECK_X(xc) || CHECK_X(xc+x) ) - HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc+x)),ROUND(yc-y),&pattern); - } - else - { - xclip = ROUND(y*startx/(double)starty); - if ( CHECK_X(xc) || CHECK_X(xc+xclip) ) - HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc+xclip)),ROUND(yc-y),&pattern); - } - } - } - else if ( startQuad == 2 ) - { - if ( CHECK_Y(yc-y) ) - { - if ( x >= startx ) - { - xclip = ROUND(y*startx/(double)starty); - if ( CHECK_X(xc-x) || CHECK_X(xc-xclip) ) - HLine(ROUND(CLIP_X(xc-x)),ROUND(CLIP_X(xc-xclip)),ROUND(yc-y),&pattern); - } - } - } - else if ( startQuad == 3 ) - { - if ( CHECK_Y(yc+y) ) - { - if ( x <= startx ) - { - if ( CHECK_X(xc-x) || CHECK_X(xc) ) - HLine(ROUND(CLIP_X(xc-x)),ROUND(CLIP_X(xc)),ROUND(yc+y),&pattern); - } - else - { - xclip = ROUND(y*startx/(double)starty); - if ( CHECK_X(xc-xclip) || CHECK_X(xc) ) - HLine(ROUND(CLIP_X(xc-xclip)),ROUND(CLIP_X(xc)),ROUND(yc+y),&pattern); - } - } - } - else if ( startQuad == 4 ) - { - if ( CHECK_Y(yc+y) ) - { - if ( x >= startx ) - { - xclip = ROUND(y*startx/(double)starty); - if ( CHECK_X(xc+xclip) || CHECK_X(xc+x) ) - HLine(ROUND(CLIP_X(xc+xclip)),ROUND(CLIP_X(xc+x)),ROUND(yc+y),&pattern); - } - } - } - - if ( endQuad == 1 ) - { - if ( CHECK_Y(yc-y) ) - { - if ( x >= endx ) - { - xclip = ROUND(y*endx/(double)endy); - if ( CHECK_X(xc+xclip) || CHECK_X(xc+x) ) - HLine(ROUND(CLIP_X(xc+xclip)),ROUND(CLIP_X(xc+x)),ROUND(yc-y),&pattern); - } - } - } - else if ( endQuad == 2 ) - { - if ( CHECK_Y(yc-y) ) - { - if ( x <= endx ) - { - if ( CHECK_X(xc-x) || CHECK_X(xc) ) - HLine(ROUND(CLIP_X(xc-x)),ROUND(CLIP_X(xc)),ROUND(yc-y),&pattern); - } - else - { - xclip = ROUND(y*endx/(double)endy); - if ( CHECK_X(xc-xclip) || CHECK_X(xc) ) - HLine(ROUND(CLIP_X(xc-xclip)),ROUND(CLIP_X(xc)),ROUND(yc-y),&pattern); - } - } - } - else if ( endQuad == 3 ) - { - if ( CHECK_Y(yc+y) ) - { - if ( x >= endx ) - { - xclip = ROUND(y*endx/(double)endy); - if ( CHECK_X(xc-x) || CHECK_X(xc-xclip) ) - HLine(ROUND(CLIP_X(xc-x)),ROUND(CLIP_X(xc-xclip)),ROUND(yc+y),&pattern); - } - } - } - else if ( endQuad == 4 ) - { - if ( CHECK_Y(yc+y) ) - { - if ( x <= endx ) - { - if ( CHECK_X(xc) || CHECK_X(xc+x) ) - HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc+x)),ROUND(yc+y),&pattern); - } - else - { - xclip = ROUND(y*endx/(double)endy); - if ( CHECK_X(xc) || CHECK_X(xc+xclip) ) - HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc+xclip)),ROUND(yc+y),&pattern); - } - } - } - } - else - { - startclip = ROUND(y*startx/(double)starty); - endclip = ROUND(y*endx/(double)endy); - if ( startQuad == 1 ) - { - if ( CHECK_Y(yc-y) ) - { - if ( (x <= startx) && (x >= endx) ) - { - if ( CHECK_X(xc+endclip) || CHECK_X(xc+x) ) - HLine(ROUND(CLIP_X(xc+endclip)),ROUND(CLIP_X(xc+x)),ROUND(yc-y),&pattern); - } - else - { - if ( CHECK_X(xc+endclip) || CHECK_X(xc+startclip) ) - HLine(ROUND(CLIP_X(xc+endclip)),ROUND(CLIP_X(xc+startclip)),ROUND(yc-y),&pattern); - } - } - } - else if ( startQuad == 2 ) - { - if ( CHECK_Y(yc-y) ) - { - if ( (x <= startx) && (x >= endx) ) - { - if ( CHECK_X(xc-x) || CHECK_X(xc-startclip) ) - HLine(ROUND(CLIP_X(xc-x)),ROUND(CLIP_X(xc-startclip)),ROUND(yc-y),&pattern); - } - else - { - if ( CHECK_X(xc-endclip) || CHECK_X(xc-startclip) ) - HLine(ROUND(CLIP_X(xc-endclip)),ROUND(CLIP_X(xc-startclip)),ROUND(yc-y),&pattern); - } - } - } - else if ( startQuad == 3 ) - { - if ( CHECK_Y(yc+y) ) - { - if ( (x <= startx) && (x >= endx) ) - { - if ( CHECK_X(xc-x) || CHECK_X(xc-endclip) ) - HLine(ROUND(CLIP_X(xc-x)),ROUND(CLIP_X(xc-endclip)),ROUND(yc+y),&pattern); - } - else - { - if ( CHECK_X(xc-startclip) || CHECK_X(xc-endclip) ) - HLine(ROUND(CLIP_X(xc-startclip)),ROUND(CLIP_X(xc-endclip)),ROUND(yc+y),&pattern); - } - } - } - else if ( startQuad == 4 ) - { - if ( CHECK_Y(yc+y) ) - { - if ( (x <= startx) && (x >= endx) ) - { - if ( CHECK_X(xc+startclip) || CHECK_X(xc+x) ) - HLine(ROUND(CLIP_X(xc+startclip)),ROUND(CLIP_X(xc+x)),ROUND(yc+y),&pattern); - } - else - { - if ( CHECK_X(xc+startclip) || CHECK_X(xc+endclip) ) - HLine(ROUND(CLIP_X(xc+startclip)),ROUND(CLIP_X(xc+endclip)),ROUND(yc+y),&pattern); - } - } - } - } - } - d->pensize = oldpensize; - 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 d Data structure containing any other data necessary for the call. Always non-NULL. - \param pat 8-byte array containing the pattern to use. Always non-NULL. - - Bounds checking must be done in this call. - I am not sure if this correctly handles cases where the curve backtracks along the diagonal - line. I should probably investigate how the be code handles that, but it is a low priority. -*/ -void AccelerantDriver::FillBezier(BPoint *pts, LayerData *d, const Pattern &pat) -{ - 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; - - AccLineCalc 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; - - 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(); -} - -/*! - \brief Called for all BView::FillEllipse calls - \param BRect enclosing the ellipse to be drawn. - \param d Data structure containing any other data necessary for the call. Always non-NULL. - \param pat 8-byte array containing the pattern to use. Always non-NULL. - - Bounds checking must be done in this call because only part of the ellipse may end up - being clipped. -*/ -void AccelerantDriver::FillEllipse(BRect r, LayerData *d, const Pattern &pat) -{ - 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; - - Lock(); - PatternHandler pattern(pat); - pattern.SetColors(d->highcolor, d->lowcolor); - - if ( CHECK_X(xc) ) - { - if ( CHECK_Y(yc-y) ) - SetPixel(ROUND(xc),ROUND(yc-y),pattern.GetColor(xc,yc-y)); - if ( CHECK_Y(yc+y) ) - SetPixel(ROUND(xc),ROUND(yc+y),pattern.GetColor(xc,yc+y)); - } - - 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 ( CHECK_X(xc-x) || CHECK_X(xc+x) ) - { - if ( CHECK_Y(yc-y) ) - HLine(ROUND(CLIP_X(xc-x)),ROUND(CLIP_X(xc+x)),ROUND(yc-y),&pattern); - if ( CHECK_Y(yc+y) ) - HLine(ROUND(CLIP_X(xc-x)),ROUND(CLIP_X(xc+x)),ROUND(yc+y),&pattern); - } - } - - 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 ( CHECK_X(xc-x) || CHECK_X(xc+x) ) - { - if ( CHECK_Y(yc-y) ) - HLine(ROUND(CLIP_X(xc-x)),ROUND(CLIP_X(xc+x)),ROUND(yc-y),&pattern); - if ( CHECK_Y(yc+y) ) - HLine(ROUND(CLIP_X(xc-x)),ROUND(CLIP_X(xc+x)),ROUND(yc+y),&pattern); - } - } - 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 rect Rectangle which contains the polygon - \param d Data structure containing any other data necessary for the call. Always non-NULL. - \param pat 8-byte array containing the pattern to use. Always non-NULL. - - The points in the array are not guaranteed to be within the framebuffer's - coordinate range. -*/ -void AccelerantDriver::FillPolygon(BPoint *ptlist, int32 numpts, BRect rect, LayerData *d, const Pattern &pat) -{ - /* 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. - */ - Lock(); - if ( !ptlist || (numpts < 3) ) - { - Unlock(); - return; - } - PatternHandler pattern(pat); - pattern.SetColors(d->highcolor, d->lowcolor); - - BPoint *currentPoint, *nextPoint; - BPoint tempNextPoint; - BPoint tempCurrentPoint; - int currentIndex, bestIndex, i, j, y; - AccLineCalc *segmentArray = new AccLineCalc[2*numpts]; - int numSegments = 0; - - /* 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; - return; - } - - 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; i y) - break; - if (segmentArray[i].MaxY() < y) - { - i++; - continue; - } - if (segmentArray[i].MinY() == segmentArray[i].MaxY()) - { - if ( (segmentArray[i].MinX() < mDisplayMode.virtual_width) && - (segmentArray[i].MaxX() >= 0) ) - HLine(CLIP_X(ROUND(segmentArray[i].MinX())), - CLIP_X(ROUND(segmentArray[i].MaxX())), - y, &pattern); - i++; - } - else - { - if ( (segmentArray[i].GetX(y) < mDisplayMode.virtual_width) && - (segmentArray[i+1].GetX(y) >= 0) ) - HLine(CLIP_X(ROUND(segmentArray[i].GetX(y))), - CLIP_X(ROUND(segmentArray[i+1].GetX(y))), - y, &pattern); - i+=2; - } - } - } - } - delete[] segmentArray; - Unlock(); -} - /*! \brief Called for all BView::FillRect calls \param r BRect to be filled. Guaranteed to be in the frame buffer's coordinate space @@ -1469,164 +551,10 @@ void AccelerantDriver::FillRect(BRect r, LayerData *d, const Pattern &pattern) Unlock(); } -/*! - \brief Called for all BView::FillRoundRect calls - \param r Rectangle to fill - \param X radius of the corner arcs - \param Y radius of the corner arcs - \param d Data structure containing any other data necessary for the call. Always non-NULL. - \param pat 8-byte array containing the pattern to use. Always non-NULL. - - Bounds checking must be done in this call because only part of the roundrect may end - up being clipped. -*/ -void AccelerantDriver::FillRoundRect(BRect r, float xrad, float yrad, LayerData *d, const Pattern &pat) -{ - float arc_x; - float yrad2 = yrad*yrad; - int i; - - Lock(); - PatternHandler pattern(pat); - pattern.SetColors(d->highcolor, d->lowcolor); - - for (i=0; i<=(int)yrad; i++) - { - arc_x = xrad*sqrt(1-i*i/yrad2); - if ( CHECK_Y(r.top+yrad-i) ) - HLine(ROUND(CLIP_X(r.left+xrad-arc_x)), ROUND(CLIP_X(r.right-xrad+arc_x)), - ROUND(r.top+yrad-i), &pattern); - if ( CHECK_Y(r.bottom-yrad+i) ) - HLine(ROUND(CLIP_X(r.left+xrad-arc_x)), ROUND(CLIP_X(r.right-xrad+arc_x)), - ROUND(r.bottom-yrad+i), &pattern); - } - FillRect(BRect(CLIP_X(r.left),CLIP_Y(r.top+yrad), - CLIP_X(r.right),CLIP_Y(r.bottom-yrad)), d, pat); - - Unlock(); -} - //void AccelerantDriver::FillShape(SShape *sh, LayerData *d, const Pattern &pat) //{ //} -/*! - \brief Called for all BView::FillTriangle calls - \param pts Array of 3 BPoints. Always non-NULL. - \param r BRect enclosing the triangle. While it will definitely enclose the triangle, - it may not be within the frame buffer's bounds. - \param d Data structure containing any other data necessary for the call. Always non-NULL. - \param pat 8-byte array containing the pattern to use. Always non-NULL. - - Bounds checking must be done in this call because only part of the triangle may end - up being clipped. -*/ -void AccelerantDriver::FillTriangle(BPoint *pts, BRect r, LayerData *d, const Pattern &pat) -{ - if(!pts || !d) - return; - - Lock(); - BPoint first, second, third; - PatternHandler pattern(pat); - pattern.SetColors(d->highcolor, d->lowcolor); - - // 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,d,pat); - return; - } - - Lock(); - PatternHandler pattern(pat); - pattern.SetColors(d->highcolor, d->lowcolor); - - thick = (int)d->pensize; - 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); - } - } - - /* SetThickPixel does bounds checking, so we don't have to worry about it here */ - if ( useQuad1 || - (!shortspan && (((startQuad == 1) && (x <= startx)) || ((endQuad == 1) && (x >= endx)))) || - (shortspan && (startQuad == 1) && (x <= startx) && (x >= endx)) ) - SetThickPixel(ROUND(xc+x),ROUND(yc-y),thick,&pattern); - if ( useQuad2 || - (!shortspan && (((startQuad == 2) && (x >= startx)) || ((endQuad == 2) && (x <= endx)))) || - (shortspan && (startQuad == 2) && (x >= startx) && (x <= endx)) ) - SetThickPixel(ROUND(xc-x),ROUND(yc-y),thick,&pattern); - if ( useQuad3 || - (!shortspan && (((startQuad == 3) && (x <= startx)) || ((endQuad == 3) && (x >= endx)))) || - (shortspan && (startQuad == 3) && (x <= startx) && (x >= endx)) ) - SetThickPixel(ROUND(xc-x),ROUND(yc+y),thick,&pattern); - if ( useQuad4 || - (!shortspan && (((startQuad == 4) && (x >= startx)) || ((endQuad == 4) && (x <= endx)))) || - (shortspan && (startQuad == 4) && (x >= startx) && (x <= endx)) ) - SetThickPixel(ROUND(xc+x),ROUND(yc+y),thick,&pattern); - - 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 || - (!shortspan && (((startQuad == 1) && (x <= startx)) || ((endQuad == 1) && (x >= endx)))) || - (shortspan && (startQuad == 1) && (x <= startx) && (x >= endx)) ) - SetThickPixel(ROUND(xc+x),ROUND(yc-y),thick,&pattern); - if ( useQuad2 || - (!shortspan && (((startQuad == 2) && (x >= startx)) || ((endQuad == 2) && (x <= endx)))) || - (shortspan && (startQuad == 2) && (x >= startx) && (x <= endx)) ) - SetThickPixel(ROUND(xc-x),ROUND(yc-y),thick,&pattern); - if ( useQuad3 || - (!shortspan && (((startQuad == 3) && (x <= startx)) || ((endQuad == 3) && (x >= endx)))) || - (shortspan && (startQuad == 3) && (x <= startx) && (x >= endx)) ) - SetThickPixel(ROUND(xc-x),ROUND(yc+y),thick,&pattern); - if ( useQuad4 || - (!shortspan && (((startQuad == 4) && (x >= startx)) || ((endQuad == 4) && (x <= endx)))) || - (shortspan && (startQuad == 4) && (x >= startx) && (x <= endx)) ) - SetThickPixel(ROUND(xc+x),ROUND(yc+y),thick,&pattern); - } - - 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 || - (!shortspan && (((startQuad == 1) && (x <= startx)) || ((endQuad == 1) && (x >= endx)))) || - (shortspan && (startQuad == 1) && (x <= startx) && (x >= endx)) ) - SetThickPixel(ROUND(xc+x),ROUND(yc-y),thick,&pattern); - if ( useQuad2 || - (!shortspan && (((startQuad == 2) && (x >= startx)) || ((endQuad == 2) && (x <= endx)))) || - (shortspan && (startQuad == 2) && (x >= startx) && (x <= endx)) ) - SetThickPixel(ROUND(xc-x),ROUND(yc-y),thick,&pattern); - if ( useQuad3 || - (!shortspan && (((startQuad == 3) && (x <= startx)) || ((endQuad == 3) && (x >= endx)))) || - (shortspan && (startQuad == 3) && (x <= startx) && (x >= endx)) ) - SetThickPixel(ROUND(xc-x),ROUND(yc+y),thick,&pattern); - if ( useQuad4 || - (!shortspan && (((startQuad == 4) && (x >= startx)) || ((endQuad == 4) && (x <= endx)))) || - (shortspan && (startQuad == 4) && (x >= startx) && (x <= endx)) ) - SetThickPixel(ROUND(xc+x),ROUND(yc+y),thick,&pattern); - } - 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 d Data structure containing any other data necessary for the call. Always non-NULL. - \param pat 8-byte array containing the pattern to use. Always non-NULL. - - Bounds checking must be done in this call. -*/ -void AccelerantDriver::StrokeBezier(BPoint *pts, LayerData *d, const Pattern &pat) -{ - 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; - - Lock(); - PatternHandler pattern(pat); - pattern.SetColors(d->highcolor, d->lowcolor); - - 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); - /* SetThickPixel does bounds checking, so we don't have to worry about it */ - if ( (x!=lastx) || (y!=lasty) ) - SetThickPixel(x,y,ROUND(d->pensize),&pattern); - lastx = x; - lasty = y; - - X += dx; - dx += ddx; - ddx += dddx; - Y += dy; - dy += ddy; - ddy += dddy; - } - Unlock(); -} - -/*! - \brief Called for all BView::StrokeEllipse calls - \param r BRect enclosing the ellipse to be drawn. - \param d Data structure containing any other data necessary for the call. Always non-NULL. - \param pat 8-byte array containing the pattern to use. Always non-NULL. - - Bounds checking must be done in this call because only part of the ellipse may end up - being clipped. -*/ -void AccelerantDriver::StrokeEllipse(BRect r, LayerData *d, const Pattern &pat) -{ - 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 thick; - - Lock(); - thick = (int)d->pensize; - PatternHandler pattern(pat); - pattern.SetColors(d->highcolor, d->lowcolor); - - /* SetThickPixel does bounds checking, so we don't have to worry about it */ - - SetThickPixel(ROUND(xc+x),ROUND(yc-y),thick,&pattern); - SetThickPixel(ROUND(xc-x),ROUND(yc-y),thick,&pattern); - SetThickPixel(ROUND(xc-x),ROUND(yc+y),thick,&pattern); - SetThickPixel(ROUND(xc+x),ROUND(yc+y),thick,&pattern); - - 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; - } - - SetThickPixel(ROUND(xc+x),ROUND(yc-y),thick,&pattern); - SetThickPixel(ROUND(xc-x),ROUND(yc-y),thick,&pattern); - SetThickPixel(ROUND(xc-x),ROUND(yc+y),thick,&pattern); - SetThickPixel(ROUND(xc+x),ROUND(yc+y),thick,&pattern); - } - - 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; - } - - SetThickPixel(ROUND(xc+x),ROUND(yc-y),thick,&pattern); - SetThickPixel(ROUND(xc-x),ROUND(yc-y),thick,&pattern); - SetThickPixel(ROUND(xc-x),ROUND(yc+y),thick,&pattern); - SetThickPixel(ROUND(xc+x),ROUND(yc+y),thick,&pattern); - } - Unlock(); -} - -/*! - \brief Draws a line. Really. - \param start Starting point - \param end Ending point - \param d Data structure containing any other data necessary for the call. Always non-NULL. - \param pat 8-byte array containing the pattern to use. Always non-NULL. - - The endpoints themselves are guaranteed to be in bounds, but clipping for lines with - a thickness greater than 1 will need to be done. - This is capable of handling lines with invalid points. -*/ -void AccelerantDriver::StrokeLine(BPoint start, BPoint end, LayerData *d, const Pattern &pat) -{ - int x1 = ROUND(start.x); - int y1 = ROUND(start.y); - int x2 = ROUND(end.x); - int y2 = ROUND(end.y); - int dx = x2 - x1; - int dy = y2 - y1; - int steps, k; - double xInc, yInc; - double x = x1; - double y = y1; - int thick; - - Lock(); - thick = (int)d->pensize; - PatternHandler pattern(pat); - pattern.SetColors(d->highcolor, d->lowcolor); - - if ( abs(dx) > abs(dy) ) - steps = abs(dx); - else - steps = abs(dy); - xInc = dx / (double) steps; - yInc = dy / (double) steps; - - /* SetThickPixel does bounds checking, so we don't have to worry about it */ - SetThickPixel(ROUND(x),ROUND(y),thick,&pattern); - for (k=0; kpensize; - PatternHandler pattern(pat); - pattern.SetColors(d->highcolor, d->lowcolor); - - HLineThick(ROUND(r.left), ROUND(r.right), ROUND(r.top), thick, &pattern); - StrokeLine(r.RightTop(), r.RightBottom(), d, pat); - HLineThick(ROUND(r.right), ROUND(r.left), ROUND(r.bottom), thick, &pattern); - StrokeLine(r.LeftTop(), r.LeftBottom(), d, pat); - Unlock(); -} - -/*! - \brief Called for all BView::StrokeRoundRect calls - \param r The rect itself - \param xrad X radius of the corner arcs - \param yrad Y radius of the corner arcs - \param d Data structure containing any other data necessary for the call. Always non-NULL. - \param pat 8-byte array containing the pattern to use. Always non-NULL. - - Bounds checking must be done in this call because only part of the roundrect may end - up being clipped. -*/ -void AccelerantDriver::StrokeRoundRect(BRect r, float xrad, float yrad, LayerData *d, const Pattern &pat) -{ - float hLeft, hRight; - float vTop, vBottom; - float bLeft, bRight, bTop, bBottom; - Lock(); - int thick = (int)d->pensize; - PatternHandler pattern(pat); - pattern.SetColors(d->highcolor, d->lowcolor); - - hLeft = r.left + xrad; - hRight = r.right - xrad; - vTop = r.top + yrad; - vBottom = r.bottom - yrad; - bLeft = hLeft + xrad; - bRight = hRight -xrad; - bTop = vTop + yrad; - bBottom = vBottom - yrad; - StrokeArc(BRect(bRight, r.top, r.right, bTop), 0, 90, d, pat); - HLineThick(ROUND(hRight), ROUND(hLeft), ROUND(r.top), thick, &pattern); - - StrokeArc(BRect(r.left,r.top,bLeft,bTop), 90, 90, d, pat); - StrokeLine(BPoint(r.left,vTop),BPoint(r.left,vBottom),d,pat); - - StrokeArc(BRect(r.left,bBottom,bLeft,r.bottom), 180, 90, d, pat); - HLineThick(ROUND(hLeft), ROUND(hRight), ROUND(r.bottom), thick, &pattern); - - StrokeArc(BRect(bRight,bBottom,r.right,r.bottom), 270, 90, d, pat); - StrokeLine(BPoint(r.right,vBottom),BPoint(r.right,vTop),d,pat); - Unlock(); -} - //void AccelerantDriver::StrokeShape(SShape *sh, LayerData *d, const Pattern &pat) //{ //} -/*! - \brief Called for all BView::StrokeTriangle calls - \param pts Array of 3 BPoints. Always non-NULL. - \param r BRect enclosing the triangle. While it will definitely enclose the triangle, - it may not be within the frame buffer's bounds. - \param d Data structure containing any other data necessary for the call. Always non-NULL. - \param pat 8-byte array containing the pattern to use. Always non-NULL. - - Bounds checking must be done in this call because only part of the triangle may end - up being clipped. -*/ -void AccelerantDriver::StrokeTriangle(BPoint *pts, BRect r, LayerData *d, const Pattern &pat) -{ - /* Bounds checking is handled by StrokeLine and the functions it calls */ - Lock(); - StrokeLine(pts[0],pts[1],d,pat); - StrokeLine(pts[1],pts[2],d,pat); - StrokeLine(pts[2],pts[0],d,pat); - Unlock(); -} - /*! \brief Draws a series of lines - optimized for speed \param pts Array of BPoints pairs @@ -2812,12 +1269,17 @@ void AccelerantDriver::HLine(int32 x1, int32 x2, int32 y, PatternHandler *pat) for (x=x1; x<=x2; x++) fb[x] = pat->GetColor(x,y).GetColor8(); } break; - case B_RGB16_BIG: - case B_RGB16_LITTLE: case B_RGB15_BIG: case B_RGBA15_BIG: case B_RGB15_LITTLE: case B_RGBA15_LITTLE: + { + uint16 *fb = (uint16 *)((uint8 *)mFrameBufferConfig.frame_buffer + y*mFrameBufferConfig.bytes_per_row); + for (x=x1; x<=x2; x++) + fb[x] = pat->GetColor(x,y).GetColor15(); + } break; + case B_RGB16_BIG: + case B_RGB16_LITTLE: { uint16 *fb = (uint16 *)((uint8 *)mFrameBufferConfig.frame_buffer + y*mFrameBufferConfig.bytes_per_row); for (x=x1; x<=x2; x++) @@ -2881,12 +1343,21 @@ void AccelerantDriver::HLineThick(int32 x1, int32 x2, int32 y, int32 thick, Patt fb += mFrameBufferConfig.bytes_per_row; } } break; - case B_RGB16_BIG: - case B_RGB16_LITTLE: case B_RGB15_BIG: case B_RGBA15_BIG: case B_RGB15_LITTLE: case B_RGBA15_LITTLE: + { + uint16 *fb = (uint16 *)((uint8 *)mFrameBufferConfig.frame_buffer + y*mFrameBufferConfig.bytes_per_row); + for (y=y1; y<=y2; y++) + { + for (x=x1; x<=x2; x++) + fb[x] = pat->GetColor(x,y).GetColor15(); + fb = (uint16 *)((uint8 *)fb + mFrameBufferConfig.bytes_per_row); + } + } break; + case B_RGB16_BIG: + case B_RGB16_LITTLE: { uint16 *fb = (uint16 *)((uint8 *)mFrameBufferConfig.frame_buffer + y*mFrameBufferConfig.bytes_per_row); for (y=y1; y<=y2; y++) diff --git a/src/servers/app/server/AccelerantDriver.h b/src/servers/app/server/AccelerantDriver.h index 96b116597a..98c8a1e359 100644 --- a/src/servers/app/server/AccelerantDriver.h +++ b/src/servers/app/server/AccelerantDriver.h @@ -28,54 +28,13 @@ #ifndef _ACCELERANTDRIVER_H_ #define _ACCELERANTDRIVER_H_ -#if 0 -#include -#include -#include -#include -#include -#include -#include -#include // for clipping_rect definition -#include -#endif #include #include "DisplayDriver.h" #include "PatternHandler.h" #include "FontServer.h" -#if 0 -class VDWindow; -class RGBColor; -class PortLink; -#endif class ServerBitmap; class ServerCursor; -class AccLineCalc -{ -public: - AccLineCalc(); - AccLineCalc(const BPoint &pta, const BPoint &ptb); - void SetPoints(const BPoint &pta, const BPoint &ptb); - float GetX(float y); - float GetY(float x); - float Slope(void) { return slope; } - float Offset(void) { return offset; } - float MinX(); - float MinY(); - float MaxX(); - float MaxY(); - void Swap(AccLineCalc &from); -private: - float slope; - float offset; - BPoint start, end; - float minx; - float miny; - float maxx; - float maxy; -}; - class AccelerantDriver : public DisplayDriver { public: @@ -90,14 +49,8 @@ public: virtual void DrawBitmap(ServerBitmap *bmp, BRect src, BRect dest, LayerData *d); virtual void DrawString(const char *string, int32 length, BPoint pt, LayerData *d, escapement_delta *edelta=NULL); - virtual void FillArc(BRect r, float angle, float span, LayerData *d, const Pattern &pat); - virtual void FillBezier(BPoint *pts, LayerData *d, const Pattern &pat); - virtual void FillEllipse(BRect r, LayerData *d, const Pattern &pat); - virtual void FillPolygon(BPoint *ptlist, int32 numpts, BRect rect, LayerData *d, const Pattern &pat); virtual void FillRect(BRect r, LayerData *d, const Pattern &pat); - virtual void FillRoundRect(BRect r, float xrad, float yrad, LayerData *d, const Pattern &pat); // virtual void FillShape(SShape *sh, LayerData *d, const Pattern &pat); - virtual void FillTriangle(BPoint *pts, BRect r, LayerData *d, const Pattern &pat); virtual void HideCursor(void); virtual void MoveCursorTo(float x, float y); @@ -106,15 +59,7 @@ public: virtual void ObscureCursor(void); virtual void SetCursor(ServerCursor *csr); - virtual void StrokeArc(BRect r, float angle, float span, LayerData *d, const Pattern &pat); - virtual void StrokeBezier(BPoint *pts, LayerData *d, const Pattern &pat); - virtual void StrokeEllipse(BRect r, LayerData *d, const Pattern &pat); - virtual void StrokeLine(BPoint start, BPoint end, LayerData *d, const Pattern &pat); - virtual void StrokePolygon(BPoint *ptlist, int32 numpts, BRect rect, LayerData *d, const Pattern &pat, bool is_closed=true); - virtual void StrokeRect(BRect r, LayerData *d, const Pattern &pat); - virtual void StrokeRoundRect(BRect r, float xrad, float yrad, LayerData *d, const Pattern &pat); // virtual void StrokeShape(SShape *sh, LayerData *d, const Pattern &pat); - virtual void StrokeTriangle(BPoint *pts, BRect r, LayerData *d, const Pattern &pat); virtual void StrokeLineArray(BPoint *pts, int32 numlines, RGBColor *colors, LayerData *d); virtual void SetMode(int32 mode); virtual bool DumpToFile(const char *path); diff --git a/src/servers/app/server/BitmapDriver.cpp b/src/servers/app/server/BitmapDriver.cpp index dc80eca04e..610d828739 100644 --- a/src/servers/app/server/BitmapDriver.cpp +++ b/src/servers/app/server/BitmapDriver.cpp @@ -26,7 +26,6 @@ // //------------------------------------------------------------------------------ #include "Angle.h" -#include "AccelerantDriver.h" #include "PatternHandler.h" #include "BitmapDriver.h" #include "ServerProtocol.h" @@ -191,740 +190,6 @@ void BitmapDriver::DrawBitmap(ServerBitmap *bitmap, BRect source, BRect dest, La 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 Data structure containing any other data necessary for the call. Always non-NULL. - \param pat 8-byte array containing the pattern to use. Always non-NULL. - - Bounds checking must be done in this call because only part of the arc may end up - being clipped. -*/ -void BitmapDriver::FillArc(BRect r, float angle, float span, LayerData *d, const Pattern &pat) -{ - 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; - float oldpensize; - BPoint center(xc,yc); - - // Watch out for bozos giving us whacko spans - if ( (span >= 360) || (span <= -360) ) - { - FillEllipse(r,d,pat); - return; - } - - Lock(); - PatternHandler pattern(pat); - pattern.SetColors(d->highcolor, d->lowcolor); - oldpensize = d->pensize; - d->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 && CHECK_Y(yc-y) && (CHECK_X(xc) || CHECK_X(xc+x)) ) - HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc+x)),ROUND(yc-y),&pattern); - if ( useQuad2 && CHECK_Y(yc-y) && (CHECK_X(xc) || CHECK_X(xc-x)) ) - HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc-x)),ROUND(yc-y),&pattern); - if ( useQuad3 && CHECK_Y(yc+y) && (CHECK_X(xc) || CHECK_X(xc-x)) ) - HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc-x)),ROUND(yc+y),&pattern); - if ( useQuad4 && CHECK_Y(yc+y) && (CHECK_X(xc) || CHECK_X(xc+x)) ) - HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc+x)),ROUND(yc+y),&pattern); - if ( (!shortspan && (((startQuad == 1) && (x <= startx)) || ((endQuad == 1) && (x >= endx)))) || - (shortspan && (startQuad == 1) && (x <= startx) && (x >= endx)) ) - StrokeLine(BPoint(xc+x,yc-y),center,d,pat); - if ( (!shortspan && (((startQuad == 2) && (x >= startx)) || ((endQuad == 2) && (x <= endx)))) || - (shortspan && (startQuad == 2) && (x >= startx) && (x <= endx)) ) - StrokeLine(BPoint(xc-x,yc-y),center,d,pat); - if ( (!shortspan && (((startQuad == 3) && (x <= startx)) || ((endQuad == 3) && (x >= endx)))) || - (shortspan && (startQuad == 3) && (x <= startx) && (x >= endx)) ) - StrokeLine(BPoint(xc-x,yc+y),center,d,pat); - if ( (!shortspan && (((startQuad == 4) && (x >= startx)) || ((endQuad == 4) && (x <= endx)))) || - (shortspan && (startQuad == 4) && (x >= startx) && (x <= endx)) ) - StrokeLine(BPoint(xc+x,yc+y),center,d,pat); - - 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 && CHECK_Y(yc-y) && (CHECK_X(xc) || CHECK_X(xc+x)) ) - HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc+x)),ROUND(yc-y),&pattern); - if ( useQuad2 && CHECK_Y(yc-y) && (CHECK_X(xc) || CHECK_X(xc-x)) ) - HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc-x)),ROUND(yc-y),&pattern); - if ( useQuad3 && CHECK_Y(yc+y) && (CHECK_X(xc) || CHECK_X(xc-x)) ) - HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc-x)),ROUND(yc+y),&pattern); - if ( useQuad4 && CHECK_Y(yc+y) && (CHECK_X(xc) || CHECK_X(xc+x)) ) - HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc+x)),ROUND(yc+y),&pattern); - if ( !shortspan ) - { - if ( startQuad == 1 ) - { - if ( CHECK_Y(yc-y) ) - { - if ( x <= startx ) - { - if ( CHECK_X(xc) || CHECK_X(xc+x) ) - HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc+x)),ROUND(yc-y),&pattern); - } - else - { - xclip = ROUND(y*startx/(double)starty); - if ( CHECK_X(xc) || CHECK_X(xc+xclip) ) - HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc+xclip)),ROUND(yc-y),&pattern); - } - } - } - else if ( startQuad == 2 ) - { - if ( CHECK_Y(yc-y) ) - { - if ( x >= startx ) - { - xclip = ROUND(y*startx/(double)starty); - if ( CHECK_X(xc-x) || CHECK_X(xc-xclip) ) - HLine(ROUND(CLIP_X(xc-x)),ROUND(CLIP_X(xc-xclip)),ROUND(yc-y),&pattern); - } - } - } - else if ( startQuad == 3 ) - { - if ( CHECK_Y(yc+y) ) - { - if ( x <= startx ) - { - if ( CHECK_X(xc-x) || CHECK_X(xc) ) - HLine(ROUND(CLIP_X(xc-x)),ROUND(CLIP_X(xc)),ROUND(yc+y),&pattern); - } - else - { - xclip = ROUND(y*startx/(double)starty); - if ( CHECK_X(xc-xclip) || CHECK_X(xc) ) - HLine(ROUND(CLIP_X(xc-xclip)),ROUND(CLIP_X(xc)),ROUND(yc+y),&pattern); - } - } - } - else if ( startQuad == 4 ) - { - if ( CHECK_Y(yc+y) ) - { - if ( x >= startx ) - { - xclip = ROUND(y*startx/(double)starty); - if ( CHECK_X(xc+xclip) || CHECK_X(xc+x) ) - HLine(ROUND(CLIP_X(xc+xclip)),ROUND(CLIP_X(xc+x)),ROUND(yc+y),&pattern); - } - } - } - - if ( endQuad == 1 ) - { - if ( CHECK_Y(yc-y) ) - { - if ( x >= endx ) - { - xclip = ROUND(y*endx/(double)endy); - if ( CHECK_X(xc+xclip) || CHECK_X(xc+x) ) - HLine(ROUND(CLIP_X(xc+xclip)),ROUND(CLIP_X(xc+x)),ROUND(yc-y),&pattern); - } - } - } - else if ( endQuad == 2 ) - { - if ( CHECK_Y(yc-y) ) - { - if ( x <= endx ) - { - if ( CHECK_X(xc-x) || CHECK_X(xc) ) - HLine(ROUND(CLIP_X(xc-x)),ROUND(CLIP_X(xc)),ROUND(yc-y),&pattern); - } - else - { - xclip = ROUND(y*endx/(double)endy); - if ( CHECK_X(xc-xclip) || CHECK_X(xc) ) - HLine(ROUND(CLIP_X(xc-xclip)),ROUND(CLIP_X(xc)),ROUND(yc-y),&pattern); - } - } - } - else if ( endQuad == 3 ) - { - if ( CHECK_Y(yc+y) ) - { - if ( x >= endx ) - { - xclip = ROUND(y*endx/(double)endy); - if ( CHECK_X(xc-x) || CHECK_X(xc-xclip) ) - HLine(ROUND(CLIP_X(xc-x)),ROUND(CLIP_X(xc-xclip)),ROUND(yc+y),&pattern); - } - } - } - else if ( endQuad == 4 ) - { - if ( CHECK_Y(yc+y) ) - { - if ( x <= endx ) - { - if ( CHECK_X(xc) || CHECK_X(xc+x) ) - HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc+x)),ROUND(yc+y),&pattern); - } - else - { - xclip = ROUND(y*endx/(double)endy); - if ( CHECK_X(xc) || CHECK_X(xc+xclip) ) - HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc+xclip)),ROUND(yc+y),&pattern); - } - } - } - } - else - { - startclip = ROUND(y*startx/(double)starty); - endclip = ROUND(y*endx/(double)endy); - if ( startQuad == 1 ) - { - if ( CHECK_Y(yc-y) ) - { - if ( (x <= startx) && (x >= endx) ) - { - if ( CHECK_X(xc+endclip) || CHECK_X(xc+x) ) - HLine(ROUND(CLIP_X(xc+endclip)),ROUND(CLIP_X(xc+x)),ROUND(yc-y),&pattern); - } - else - { - if ( CHECK_X(xc+endclip) || CHECK_X(xc+startclip) ) - HLine(ROUND(CLIP_X(xc+endclip)),ROUND(CLIP_X(xc+startclip)),ROUND(yc-y),&pattern); - } - } - } - else if ( startQuad == 2 ) - { - if ( CHECK_Y(yc-y) ) - { - if ( (x <= startx) && (x >= endx) ) - { - if ( CHECK_X(xc-x) || CHECK_X(xc-startclip) ) - HLine(ROUND(CLIP_X(xc-x)),ROUND(CLIP_X(xc-startclip)),ROUND(yc-y),&pattern); - } - else - { - if ( CHECK_X(xc-endclip) || CHECK_X(xc-startclip) ) - HLine(ROUND(CLIP_X(xc-endclip)),ROUND(CLIP_X(xc-startclip)),ROUND(yc-y),&pattern); - } - } - } - else if ( startQuad == 3 ) - { - if ( CHECK_Y(yc+y) ) - { - if ( (x <= startx) && (x >= endx) ) - { - if ( CHECK_X(xc-x) || CHECK_X(xc-endclip) ) - HLine(ROUND(CLIP_X(xc-x)),ROUND(CLIP_X(xc-endclip)),ROUND(yc+y),&pattern); - } - else - { - if ( CHECK_X(xc-startclip) || CHECK_X(xc-endclip) ) - HLine(ROUND(CLIP_X(xc-startclip)),ROUND(CLIP_X(xc-endclip)),ROUND(yc+y),&pattern); - } - } - } - else if ( startQuad == 4 ) - { - if ( CHECK_Y(yc+y) ) - { - if ( (x <= startx) && (x >= endx) ) - { - if ( CHECK_X(xc+startclip) || CHECK_X(xc+x) ) - HLine(ROUND(CLIP_X(xc+startclip)),ROUND(CLIP_X(xc+x)),ROUND(yc+y),&pattern); - } - else - { - if ( CHECK_X(xc+startclip) || CHECK_X(xc+endclip) ) - HLine(ROUND(CLIP_X(xc+startclip)),ROUND(CLIP_X(xc+endclip)),ROUND(yc+y),&pattern); - } - } - } - } - } - - 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 && CHECK_Y(yc-y) && (CHECK_X(xc) || CHECK_X(xc+x)) ) - HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc+x)),ROUND(yc-y),&pattern); - if ( useQuad2 && CHECK_Y(yc-y) && (CHECK_X(xc) || CHECK_X(xc-x)) ) - HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc-x)),ROUND(yc-y),&pattern); - if ( useQuad3 && CHECK_Y(yc+y) && (CHECK_X(xc) || CHECK_X(xc-x)) ) - HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc-x)),ROUND(yc+y),&pattern); - if ( useQuad4 && CHECK_Y(yc+y) && (CHECK_X(xc) || CHECK_X(xc+x)) ) - HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc+x)),ROUND(yc+y),&pattern); - if ( !shortspan ) - { - if ( startQuad == 1 ) - { - if ( CHECK_Y(yc-y) ) - { - if ( x <= startx ) - { - if ( CHECK_X(xc) || CHECK_X(xc+x) ) - HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc+x)),ROUND(yc-y),&pattern); - } - else - { - xclip = ROUND(y*startx/(double)starty); - if ( CHECK_X(xc) || CHECK_X(xc+xclip) ) - HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc+xclip)),ROUND(yc-y),&pattern); - } - } - } - else if ( startQuad == 2 ) - { - if ( CHECK_Y(yc-y) ) - { - if ( x >= startx ) - { - xclip = ROUND(y*startx/(double)starty); - if ( CHECK_X(xc-x) || CHECK_X(xc-xclip) ) - HLine(ROUND(CLIP_X(xc-x)),ROUND(CLIP_X(xc-xclip)),ROUND(yc-y),&pattern); - } - } - } - else if ( startQuad == 3 ) - { - if ( CHECK_Y(yc+y) ) - { - if ( x <= startx ) - { - if ( CHECK_X(xc-x) || CHECK_X(xc) ) - HLine(ROUND(CLIP_X(xc-x)),ROUND(CLIP_X(xc)),ROUND(yc+y),&pattern); - } - else - { - xclip = ROUND(y*startx/(double)starty); - if ( CHECK_X(xc-xclip) || CHECK_X(xc) ) - HLine(ROUND(CLIP_X(xc-xclip)),ROUND(CLIP_X(xc)),ROUND(yc+y),&pattern); - } - } - } - else if ( startQuad == 4 ) - { - if ( CHECK_Y(yc+y) ) - { - if ( x >= startx ) - { - xclip = ROUND(y*startx/(double)starty); - if ( CHECK_X(xc+xclip) || CHECK_X(xc+x) ) - HLine(ROUND(CLIP_X(xc+xclip)),ROUND(CLIP_X(xc+x)),ROUND(yc+y),&pattern); - } - } - } - - if ( endQuad == 1 ) - { - if ( CHECK_Y(yc-y) ) - { - if ( x >= endx ) - { - xclip = ROUND(y*endx/(double)endy); - if ( CHECK_X(xc+xclip) || CHECK_X(xc+x) ) - HLine(ROUND(CLIP_X(xc+xclip)),ROUND(CLIP_X(xc+x)),ROUND(yc-y),&pattern); - } - } - } - else if ( endQuad == 2 ) - { - if ( CHECK_Y(yc-y) ) - { - if ( x <= endx ) - { - if ( CHECK_X(xc-x) || CHECK_X(xc) ) - HLine(ROUND(CLIP_X(xc-x)),ROUND(CLIP_X(xc)),ROUND(yc-y),&pattern); - } - else - { - xclip = ROUND(y*endx/(double)endy); - if ( CHECK_X(xc-xclip) || CHECK_X(xc) ) - HLine(ROUND(CLIP_X(xc-xclip)),ROUND(CLIP_X(xc)),ROUND(yc-y),&pattern); - } - } - } - else if ( endQuad == 3 ) - { - if ( CHECK_Y(yc+y) ) - { - if ( x >= endx ) - { - xclip = ROUND(y*endx/(double)endy); - if ( CHECK_X(xc-x) || CHECK_X(xc-xclip) ) - HLine(ROUND(CLIP_X(xc-x)),ROUND(CLIP_X(xc-xclip)),ROUND(yc+y),&pattern); - } - } - } - else if ( endQuad == 4 ) - { - if ( CHECK_Y(yc+y) ) - { - if ( x <= endx ) - { - if ( CHECK_X(xc) || CHECK_X(xc+x) ) - HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc+x)),ROUND(yc+y),&pattern); - } - else - { - xclip = ROUND(y*endx/(double)endy); - if ( CHECK_X(xc) || CHECK_X(xc+xclip) ) - HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc+xclip)),ROUND(yc+y),&pattern); - } - } - } - } - else - { - startclip = ROUND(y*startx/(double)starty); - endclip = ROUND(y*endx/(double)endy); - if ( startQuad == 1 ) - { - if ( CHECK_Y(yc-y) ) - { - if ( (x <= startx) && (x >= endx) ) - { - if ( CHECK_X(xc+endclip) || CHECK_X(xc+x) ) - HLine(ROUND(CLIP_X(xc+endclip)),ROUND(CLIP_X(xc+x)),ROUND(yc-y),&pattern); - } - else - { - if ( CHECK_X(xc+endclip) || CHECK_X(xc+startclip) ) - HLine(ROUND(CLIP_X(xc+endclip)),ROUND(CLIP_X(xc+startclip)),ROUND(yc-y),&pattern); - } - } - } - else if ( startQuad == 2 ) - { - if ( CHECK_Y(yc-y) ) - { - if ( (x <= startx) && (x >= endx) ) - { - if ( CHECK_X(xc-x) || CHECK_X(xc-startclip) ) - HLine(ROUND(CLIP_X(xc-x)),ROUND(CLIP_X(xc-startclip)),ROUND(yc-y),&pattern); - } - else - { - if ( CHECK_X(xc-endclip) || CHECK_X(xc-startclip) ) - HLine(ROUND(CLIP_X(xc-endclip)),ROUND(CLIP_X(xc-startclip)),ROUND(yc-y),&pattern); - } - } - } - else if ( startQuad == 3 ) - { - if ( CHECK_Y(yc+y) ) - { - if ( (x <= startx) && (x >= endx) ) - { - if ( CHECK_X(xc-x) || CHECK_X(xc-endclip) ) - HLine(ROUND(CLIP_X(xc-x)),ROUND(CLIP_X(xc-endclip)),ROUND(yc+y),&pattern); - } - else - { - if ( CHECK_X(xc-startclip) || CHECK_X(xc-endclip) ) - HLine(ROUND(CLIP_X(xc-startclip)),ROUND(CLIP_X(xc-endclip)),ROUND(yc+y),&pattern); - } - } - } - else if ( startQuad == 4 ) - { - if ( CHECK_Y(yc+y) ) - { - if ( (x <= startx) && (x >= endx) ) - { - if ( CHECK_X(xc+startclip) || CHECK_X(xc+x) ) - HLine(ROUND(CLIP_X(xc+startclip)),ROUND(CLIP_X(xc+x)),ROUND(yc+y),&pattern); - } - else - { - if ( CHECK_X(xc+startclip) || CHECK_X(xc+endclip) ) - HLine(ROUND(CLIP_X(xc+startclip)),ROUND(CLIP_X(xc+endclip)),ROUND(yc+y),&pattern); - } - } - } - } - } - d->pensize = oldpensize; - 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 d Data structure containing any other data necessary for the call. Always non-NULL. - \param pat 8-byte array containing the pattern to use. Always non-NULL. - - Bounds checking must be done in this call. -*/ -void BitmapDriver::FillBezier(BPoint *pts, LayerData *d, const Pattern &pat) -{ - 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; - - AccLineCalc 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; - - 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(); -} - -/*! - \brief Called for all BView::FillEllipse calls - \param r BRect enclosing the ellipse to be drawn. - \param d Data structure containing any other data necessary for the call. Always non-NULL. - \param pat 8-byte array containing the pattern to use. Always non-NULL. - - Bounds checking must be done in this call because only part of the ellipse may end up - being clipped. -*/ -void BitmapDriver::FillEllipse(BRect r, LayerData *ldata, const Pattern &pat) -{ -// Ellipse code shamelessly stolen from the graphics library gd v2.0.1 and bolted on -// to support our API - long d, b_sq, b_sq_4, b_sq_6; - long a_sq, a_sq_4, a_sq_6; - int x, y, switchem; - long lsqrt (long); - int pix, half, pstart; - int32 thick = (int32)ldata->pensize; - - half = thick / 2; - int32 w=int32(r.Width()/2), - h=int32(r.Height()/2); - int32 cx=(int32)r.left+w; - int32 cy=(int32)r.top+h; - - d = 2 * (long) h *h + (long) w *w - 2 * (long) w *w * h; - b_sq = (long) h *h; - b_sq_4 = 4 * (long) h *h; - b_sq_6 = 6 * (long) h *h; - a_sq = (long) w *w; - a_sq_4 = 4 * (long) w *w; - a_sq_6 = 6 * (long) w *w; - - x = 0; - y = -h; -// switchem = a_sq / lsqrt (a_sq + b_sq); - switchem = a_sq / (int32)sqrt(a_sq + b_sq); - - while (x <= switchem) - { - pstart = y - half; - for (pix = pstart; pix < pstart + thick; pix++) - { - Line( BPoint(cx - x, cy + pix), BPoint(cx + x, cy + pix), ldata, pat_solidhigh); - Line( BPoint(cx - x, cy - pix), BPoint(cx + x, cy - pix), ldata, pat_solidhigh); - } - if (d < 0) - d += b_sq_4 * x++ + b_sq_6; - else - d += b_sq_4 * x++ + b_sq_6 + a_sq_4 * (++y); - } - - /* Middlesplat! - ** Go a little further if the thickness is not nominal... - */ - if (thick > 1) - { - int xp = x; - int yp = y; - int dp = d; - int thick2 = thick + 2; - int half2 = half + 1; - - while (xp <= switchem + half) - { - pstart = yp - half2; - for (pix = pstart; pix < pstart + thick2; pix++) - { - Line( BPoint(cx - xp, cy + pix), BPoint(cx + xp, cy + pix), ldata, pat_solidhigh); - Line( BPoint(cx - xp, cy - pix), BPoint(cx + xp, cy - pix), ldata, pat_solidhigh); - } - if (dp < 0) - dp += b_sq_4 * xp++ + b_sq_6; - else - dp += b_sq_4 * xp++ + b_sq_6 + a_sq_4 * (++yp); - } - } - - d += -2 * (long) b_sq + 2 * (long) a_sq - 2 * (long) b_sq *(x - 1) + 2 * (long) a_sq *(y - 1); - - while (y <= 0) - { - pstart = x - half; - for (pix = pstart; pix < pstart + thick; pix++) - { - Line( BPoint(cx - pix, cy + y), BPoint(cx + pix, cy + y), ldata, pat_solidhigh); - Line( BPoint(cx - pix, cy - y), BPoint(cx + pix, cy - y), ldata, pat_solidhigh); - } - - if (d < 0) - d += a_sq_4 * y++ + a_sq_6 + b_sq_4 * (++x); - else - d += a_sq_4 * y++ + a_sq_6; - } -} - -/*! - \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 rect Rectangle which contains the polygon - \param d Data structure containing any other data necessary for the call. Always non-NULL. - \param pat 8-byte array containing the pattern to use. Always non-NULL. - - The points in the array are not guaranteed to be within the framebuffer's - coordinate range. -*/ -void BitmapDriver::FillPolygon(BPoint *ptlist, int32 numpts, BRect rect, LayerData *d, const Pattern &pat) -{ -} - - /*! \brief Called for all BView::FillRect calls \param r BRect to be filled. Guaranteed to be in the frame buffer's coordinate space @@ -945,158 +210,6 @@ void BitmapDriver::FillRect(BRect r, LayerData *d, const Pattern &pat) Unlock(); } -/*! - \brief Called for all BView::FillRoundRect calls - \param r The rectangle itself - \param xrad X radius of the corner arcs - \param yrad Y radius of the corner arcs - \param d Data structure containing any other data necessary for the call. Always non-NULL. - \param pat 8-byte array containing the pattern to use. Always non-NULL. - - Bounds checking must be done in this call because only part of the roundrect may end - up being clipped. -*/ -void BitmapDriver::FillRoundRect(BRect r, float xrad, float yrad, LayerData *d, const Pattern &pat) -{ - float arc_x; - float yrad2 = yrad*yrad; - int i; - - Lock(); - PatternHandler pattern(pat); - pattern.SetColors(d->highcolor, d->lowcolor); - - for (i=0; i<=(int)yrad; i++) - { - arc_x = xrad*sqrt(1-i*i/yrad2); - if ( CHECK_Y(r.top+yrad-i) ) - HLine(ROUND(CLIP_X(r.left+xrad-arc_x)), ROUND(CLIP_X(r.right-xrad+arc_x)), - ROUND(r.top+yrad-i), &pattern); - if ( CHECK_Y(r.bottom-yrad+i) ) - HLine(ROUND(CLIP_X(r.left+xrad-arc_x)), ROUND(CLIP_X(r.right-xrad+arc_x)), - ROUND(r.bottom-yrad+i), &pattern); - } - FillRect(BRect(CLIP_X(r.left),CLIP_Y(r.top+yrad), - CLIP_X(r.right),CLIP_Y(r.bottom-yrad)), d, pat); - - Unlock(); -} - -/*! - \brief Called for all BView::FillTriangle calls - \param pts Array of 3 BPoints. Always non-NULL. - \param r BRect enclosing the triangle. While it will definitely enclose the triangle, - it may not be within the frame buffer's bounds. - \param d Data structure containing any other data necessary for the call. Always non-NULL. - \param pat 8-byte array containing the pattern to use. Always non-NULL. - - Bounds checking must be done in this call because only part of the triangle may end - up being clipped. -*/ -void BitmapDriver::FillTriangle(BPoint *pts, BRect r, LayerData *d, const Pattern &pat) -{ - if(!pts || !d) - return; - - Lock(); - if(_target) - { - BPoint first, second, third; - - // Sort points according to their y values - if(pts[0].y < pts[1].y) - { - first=pts[0]; - second=pts[1]; - } - else - { - first=pts[1]; - second=pts[0]; - } - - if(second.yBitsPerPixel()) @@ -1236,503 +349,6 @@ void BitmapDriver::SetMode(int32 space) // No need to reset a bitmap's color space } - -/*! - \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 Data structure containing any other data necessary for the call. Always non-NULL. - \param pat 8-byte array containing the pattern to use. Always non-NULL. - - Bounds checking must be done in this call because only part of the arc may end up - being clipped. -*/ -void BitmapDriver::StrokeArc(BRect r, float angle, float span, LayerData *d, const Pattern &pat) -{ -// TODO: Add pattern support - 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 startQuad, endQuad; - bool useQuad1, useQuad2, useQuad3, useQuad4; - bool shortspan = false; - int thick = (int)d->pensize; - - // Watch out for bozos giving us whacko spans - if ( (span >= 360) || (span <= -360) ) - { - StrokeEllipse(r,d,pat); - 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)) ) - SetThickPixel(ROUND(xc+x),ROUND(yc-y),thick,d->highcolor); - if ( useQuad2 || - (!shortspan && (((startQuad == 2) && (x >= startx)) || ((endQuad == 2) && (x <= endx)))) || - (shortspan && (startQuad == 2) && (x >= startx) && (x <= endx)) ) - SetThickPixel(ROUND(xc-x),ROUND(yc-y),thick,d->highcolor); - if ( useQuad3 || - (!shortspan && (((startQuad == 3) && (x <= startx)) || ((endQuad == 3) && (x >= endx)))) || - (shortspan && (startQuad == 3) && (x <= startx) && (x >= endx)) ) - SetThickPixel(ROUND(xc-x),ROUND(yc+y),thick,d->highcolor); - if ( useQuad4 || - (!shortspan && (((startQuad == 4) && (x >= startx)) || ((endQuad == 4) && (x <= endx)))) || - (shortspan && (startQuad == 4) && (x >= startx) && (x <= endx)) ) - SetThickPixel(ROUND(xc+x),ROUND(yc+y),thick,d->highcolor); - - 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 || - (!shortspan && (((startQuad == 1) && (x <= startx)) || ((endQuad == 1) && (x >= endx)))) || - (shortspan && (startQuad == 1) && (x <= startx) && (x >= endx)) ) - SetThickPixel(ROUND(xc+x),ROUND(yc-y),thick,d->highcolor); - if ( useQuad2 || - (!shortspan && (((startQuad == 2) && (x >= startx)) || ((endQuad == 2) && (x <= endx)))) || - (shortspan && (startQuad == 2) && (x >= startx) && (x <= endx)) ) - SetThickPixel(ROUND(xc-x),ROUND(yc-y),thick,d->highcolor); - if ( useQuad3 || - (!shortspan && (((startQuad == 3) && (x <= startx)) || ((endQuad == 3) && (x >= endx)))) || - (shortspan && (startQuad == 3) && (x <= startx) && (x >= endx)) ) - SetThickPixel(ROUND(xc-x),ROUND(yc+y),thick,d->highcolor); - if ( useQuad4 || - (!shortspan && (((startQuad == 4) && (x >= startx)) || ((endQuad == 4) && (x <= endx)))) || - (shortspan && (startQuad == 4) && (x >= startx) && (x <= endx)) ) - SetThickPixel(ROUND(xc+x),ROUND(yc+y),thick,d->highcolor); - } - - 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 || - (!shortspan && (((startQuad == 1) && (x <= startx)) || ((endQuad == 1) && (x >= endx)))) || - (shortspan && (startQuad == 1) && (x <= startx) && (x >= endx)) ) - SetThickPixel(ROUND(xc+x),ROUND(yc-y),thick,d->highcolor); - if ( useQuad2 || - (!shortspan && (((startQuad == 2) && (x >= startx)) || ((endQuad == 2) && (x <= endx)))) || - (shortspan && (startQuad == 2) && (x >= startx) && (x <= endx)) ) - SetThickPixel(ROUND(xc-x),ROUND(yc-y),thick,d->highcolor); - if ( useQuad3 || - (!shortspan && (((startQuad == 3) && (x <= startx)) || ((endQuad == 3) && (x >= endx)))) || - (shortspan && (startQuad == 3) && (x <= startx) && (x >= endx)) ) - SetThickPixel(ROUND(xc-x),ROUND(yc+y),thick,d->highcolor); - if ( useQuad4 || - (!shortspan && (((startQuad == 4) && (x >= startx)) || ((endQuad == 4) && (x <= endx)))) || - (shortspan && (startQuad == 4) && (x >= startx) && (x <= endx)) ) - SetThickPixel(ROUND(xc+x),ROUND(yc+y),thick,d->highcolor); - } -} - -/*! - \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 d Data structure containing any other data necessary for the call. Always non-NULL. - \param pat 8-byte array containing the pattern to use. Always non-NULL. - - Bounds checking must be done in this call. -*/ -void BitmapDriver::StrokeBezier(BPoint *pts, LayerData *d, const Pattern &pat) -{ -// TODO: Add pattern support - double Ax, Bx, Cx, Dx; - double Ay, By, Cy, Dy; - int x, y; - int lastx=-1, lasty=-1; - double t; - double dt = .001; - 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) ) - SetThickPixel(x,y,ROUND(d->pensize),d->highcolor); - lastx = x; - lasty = y; - - X += dx; - dx += ddx; - ddx += dddx; - Y += dy; - dy += ddy; - ddy += dddy; - } -} - -/*! - \brief Called for all BView::StrokeEllipse calls - \param r BRect enclosing the ellipse to be drawn. - \param d Data structure containing any other data necessary for the call. Always non-NULL. - \param pat 8-byte array containing the pattern to use. Always non-NULL. - - Bounds checking must be done in this call because only part of the ellipse may end up - being clipped. -*/ -void BitmapDriver::StrokeEllipse(BRect r, LayerData *ldata, const Pattern &pat) -{ -// Ellipse code shamelessly stolen from the graphics library gd v2.0.1 and bolted on -// to support our API - long d, b_sq, b_sq_4, b_sq_6; - long a_sq, a_sq_4, a_sq_6; - int x, y, switchem; - long lsqrt (long); - int pix, half, pstart; - int32 thick = (int32)ldata->pensize; - - half = thick / 2; - int32 w=int32(r.Width()/2), - h=int32(r.Height()/2); - int32 cx=(int32)r.left+w; - int32 cy=(int32)r.top+h; - - d = 2 * (long) h *h + (long) w *w - 2 * (long) w *w * h; - b_sq = (long) h *h; - b_sq_4 = 4 * (long) h *h; - b_sq_6 = 6 * (long) h *h; - a_sq = (long) w *w; - a_sq_4 = 4 * (long) w *w; - a_sq_6 = 6 * (long) w *w; - - x = 0; - y = -h; -// switchem = a_sq / lsqrt (a_sq + b_sq); - switchem = a_sq / (int32)sqrt(a_sq + b_sq); - - while (x <= switchem) - { - pstart = y - half; - for (pix = pstart; pix < pstart + thick; pix++) - { - SetPixel(cx + x, cy + pix, ldata->highcolor); - SetPixel(cx - x, cy + pix, ldata->highcolor); - SetPixel(cx + x, cy - pix, ldata->highcolor); - SetPixel(cx - x, cy - pix, ldata->highcolor); - } - if (d < 0) - d += b_sq_4 * x++ + b_sq_6; - else - d += b_sq_4 * x++ + b_sq_6 + a_sq_4 * (++y); - } - - /* Middlesplat! - ** Go a little further if the thickness is not nominal... - */ - if (thick > 1) - { - int xp = x; - int yp = y; - int dp = d; - int thick2 = thick + 2; - int half2 = half + 1; - - while (xp <= switchem + half) - { - pstart = yp - half2; - for (pix = pstart; pix < pstart + thick2; pix++) - { - SetPixel(cx + xp, cy + pix, ldata->highcolor); - SetPixel(cx - xp, cy + pix, ldata->highcolor); - SetPixel(cx + xp, cy - pix, ldata->highcolor); - SetPixel(cx - xp, cy - pix, ldata->highcolor); - } - if (dp < 0) - dp += b_sq_4 * xp++ + b_sq_6; - else - dp += b_sq_4 * xp++ + b_sq_6 + a_sq_4 * (++yp); - } - } - - d += -2 * (long) b_sq + 2 * (long) a_sq - 2 * (long) b_sq *(x - 1) + 2 * (long) a_sq *(y - 1); - - while (y <= 0) - { - pstart = x - half; - for (pix = pstart; pix < pstart + thick; pix++) - { - SetPixel (cx + pix, cy + y, ldata->highcolor); - SetPixel (cx - pix, cy + y, ldata->highcolor); - SetPixel (cx + pix, cy - y, ldata->highcolor); - SetPixel (cx - pix, cy - y, ldata->highcolor); - } - - if (d < 0) - d += a_sq_4 * y++ + a_sq_6 + b_sq_4 * (++x); - else - d += a_sq_4 * y++ + a_sq_6; - } - -} - -/*! - \brief Draws a line. Really. - \param start Starting point - \param end Ending point - \param d Data structure containing any other data necessary for the call. Always non-NULL. - \param pat 8-byte array containing the pattern to use. Always non-NULL. - - The endpoints themselves are guaranteed to be in bounds, but clipping for lines with - a thickness greater than 1 will need to be done. -*/ -void BitmapDriver::StrokeLine(BPoint start, BPoint end, LayerData *d, const Pattern &pat) -{ - Lock(); - if(_target) - { - // Courtesy YNOP's SecondDriver with minor changes by DW - int oct=0; - int xoff=(int32)end.x; - int yoff=(int32)end.y; - int32 x2=(int32)start.x-xoff; - int32 y2=(int32)start.y-yoff; - int32 x1=0; - int32 y1=0; - if(y2<0){ y2=-y2; oct+=4; }//bit2=1 - if(x2<0){ x2=-x2; oct+=2;}//bit1=1 - if(x2highcolor);break; - case 1:SetPixel(( y)+xoff,( x)+yoff,d->highcolor);break; - case 3:SetPixel((-y)+xoff,( x)+yoff,d->highcolor);break; - case 2:SetPixel((-x)+xoff,( y)+yoff,d->highcolor);break; - case 6:SetPixel((-x)+xoff,(-y)+yoff,d->highcolor);break; - case 7:SetPixel((-y)+xoff,(-x)+yoff,d->highcolor);break; - case 5:SetPixel(( y)+xoff,(-x)+yoff,d->highcolor);break; - case 4:SetPixel(( x)+xoff,(-y)+yoff,d->highcolor);break; - } - x++; - sum-=Dy; - if(sum < 0) - { - y++; - sum += Dx; - } - } - } - Unlock(); -} - -/*! - \brief Called for all BView::StrokePolygon calls - \param ptlist Array of BPoints defining the polygon. - \param numpts Number of points in the BPoint array. - \param rect Rectangle which contains the polygon - \param d Data structure containing any other data necessary for the call. Always non-NULL. - \param pat 8-byte array containing the pattern to use. Always non-NULL. - - The points in the array are not guaranteed to be within the framebuffer's - coordinate range. -*/ -void BitmapDriver::StrokePolygon(BPoint *ptlist, int32 numpts, BRect rect, LayerData *d, const Pattern &pat, bool is_closed) -{ - Lock(); - if(_target) - { - for(int32 i=0; i<(numpts-1); i++) - Line(ptlist[i],ptlist[i+1],d,pat); - - if(is_closed) - Line(ptlist[numpts-1],ptlist[0],d,pat); - } - Unlock(); -} - -/*! - \brief Called for all BView::StrokeRect calls - \param r BRect to be filled. Guaranteed to be in the frame buffer's coordinate space - \param d Data structure containing any other data necessary for the call. Always non-NULL. - \param pat 8-byte array containing the pattern to use. Always non-NULL. - -*/ -void BitmapDriver::StrokeRect(BRect r, LayerData *d, const Pattern &pat) -{ - Lock(); - if(_target) - { - Line(r.LeftTop(),r.RightTop(),d,pat); - Line(r.RightTop(),r.RightBottom(),d,pat); - Line(r.RightBottom(),r.LeftBottom(),d,pat); - Line(r.LeftTop(),r.LeftBottom(),d,pat); - } - Unlock(); -} - -/*! - \brief Called for all BView::StrokeRoundRect calls - \param r The rect itself - \param xrad X radius of the corner arcs - \param yrad Y radius of the corner arcs - \param d Data structure containing any other data necessary for the call. Always non-NULL. - \param pat 8-byte array containing the pattern to use. Always non-NULL. - - Bounds checking must be done in this call because only part of the roundrect may end - up being clipped. -*/ -void BitmapDriver::StrokeRoundRect(BRect r, float xrad, float yrad, LayerData *d, const Pattern &pat) -{ - float hLeft, hRight; - float vTop, vBottom; - float bLeft, bRight, bTop, bBottom; - Lock(); - PatternHandler pattern(pat); - pattern.SetColors(d->highcolor, d->lowcolor); - - hLeft = r.left + xrad; - hRight = r.right - xrad; - vTop = r.top + yrad; - vBottom = r.bottom - yrad; - bLeft = hLeft + xrad; - bRight = hRight -xrad; - bTop = vTop + yrad; - bBottom = vBottom - yrad; - StrokeArc(BRect(bRight, r.top, r.right, bTop), 0, 90, d, pat); - Line(BPoint(hLeft,r.top), BPoint(hRight, r.top), d, pat); - - StrokeArc(BRect(r.left,r.top,bLeft,bTop), 90, 90, d, pat); - Line(BPoint(r.left,vTop),BPoint(r.left,vBottom),d,pat); - - StrokeArc(BRect(r.left,bBottom,bLeft,r.bottom), 180, 90, d, pat); - Line(BPoint(hLeft,r.bottom), BPoint(hRight, r.bottom), d, pat); - - StrokeArc(BRect(bRight,bBottom,r.right,r.bottom), 270, 90, d, pat); - StrokeLine(BPoint(r.right,vBottom),BPoint(r.right,vTop),d,pat); - Unlock(); -} - -/*! - \brief Called for all BView::StrokeTriangle calls - \param pts Array of 3 BPoints. Always non-NULL. - \param r BRect enclosing the triangle. While it will definitely enclose the triangle, - it may not be within the frame buffer's bounds. - \param d Data structure containing any other data necessary for the call. Always non-NULL. - \param pat 8-byte array containing the pattern to use. Always non-NULL. - - Bounds checking must be done in this call because only part of the triangle may end - up being clipped. -*/ -void BitmapDriver::StrokeTriangle(BPoint *pts, BRect r, LayerData *d, const Pattern &pat) -{ - Lock(); - if(_target) - { - Line(pts[0],pts[1],d,pat); - Line(pts[1],pts[2],d,pat); - Line(pts[2],pts[0],d,pat); - } - Unlock(); -} - void BitmapDriver::SetPixelPattern(int x, int y, uint8 *pattern, uint8 patternindex) { // This function is designed to add pattern support to this thing. Should be @@ -2709,7 +1325,6 @@ rgb_color BitmapDriver::GetBlitColor(rgb_color src, rgb_color dest, LayerData *d */ void BitmapDriver::HLine(int32 x1, int32 x2, int32 y, PatternHandler *pat) { -/* // TODO: Finish porting over from AccelerantDriver int x; if ( x1 > x2 ) { @@ -2717,32 +1332,30 @@ void BitmapDriver::HLine(int32 x1, int32 x2, int32 y, PatternHandler *pat) x2 = x1; x1 = x; } - switch (mDisplayMode.space) + switch(_target->BitsPerPixel()) { - case B_CMAP8: - case B_GRAY8: + case 8: { - uint8 *fb = (uint8 *)mFrameBufferConfig.frame_buffer + y*mFrameBufferConfig.bytes_per_row; + uint8 *fb = (uint8 *)_target->Bits() + y*_target->BytesPerRow(); for (x=x1; x<=x2; x++) fb[x] = pat->GetColor(x,y).GetColor8(); } break; - case B_RGB16_BIG: - case B_RGB16_LITTLE: - case B_RGB15_BIG: - case B_RGBA15_BIG: - case B_RGB15_LITTLE: - case B_RGBA15_LITTLE: + case 15: { - uint16 *fb = (uint16 *)((uint8 *)mFrameBufferConfig.frame_buffer + y*mFrameBufferConfig.bytes_per_row); + uint16 *fb = (uint16 *)((uint8 *)_target->Bits() + y*_target->BytesPerRow()); + for (x=x1; x<=x2; x++) + fb[x] = pat->GetColor(x,y).GetColor15(); + } break; + case 16: + { + uint16 *fb = (uint16 *)((uint8 *)_target->Bits() + y*_target->BytesPerRow()); for (x=x1; x<=x2; x++) fb[x] = pat->GetColor(x,y).GetColor16(); } break; - case B_RGB32_BIG: - case B_RGBA32_BIG: - case B_RGB32_LITTLE: - case B_RGBA32_LITTLE: + case 24: + case 32: { - uint32 *fb = (uint32 *)((uint8 *)mFrameBufferConfig.frame_buffer + y*mFrameBufferConfig.bytes_per_row); + uint32 *fb = (uint32 *)((uint8 *)_target->Bits() + y*_target->BytesPerRow()); rgb_color color; for (x=x1; x<=x2; x++) { @@ -2753,5 +1366,83 @@ void BitmapDriver::HLine(int32 x1, int32 x2, int32 y, PatternHandler *pat) default: printf("Error: Unknown color space\n"); } -*/ +} + +/*! + \brief Draws a horizontal line + \param x1 The first x coordinate (not guaranteed to be in bounds) + \param x2 The second x coordinate (not guaranteed to be in bounds) + \param y The y coordinate (not guaranteed to be in bounds) + \param thick The thickness of the line + \param pat The PatternHandler which detemines pixel colors +*/ +void BitmapDriver::HLineThick(int32 x1, int32 x2, int32 y, int32 thick, PatternHandler *pat) +{ + int x, y1, y2; + int bytesPerRow = _target->BytesPerRow(); + + if ( x1 > x2 ) + { + x = x2; + x2 = x1; + x1 = x; + } + y1 = y-thick/2; + y2 = y+thick/2; + if ( (x2 < 0) || (x1 >= _target->Width()) || (!CHECK_Y(y1) && !CHECK_Y(y2)) ) + return; + x1 = CLIP_X(x1); + x2 = CLIP_X(x2); + y1 = CLIP_Y(y1); + y2 = CLIP_Y(y2); + switch(_target->BitsPerPixel()) + { + case 8: + { + uint8 *fb = (uint8 *)_target->Bits() + y*bytesPerRow; + for (y=y1; y<=y2; y++) + { + for (x=x1; x<=x2; x++) + fb[x] = pat->GetColor(x,y).GetColor8(); + fb += bytesPerRow; + } + } break; + case 15: + { + uint16 *fb = (uint16 *)((uint8 *)_target->Bits() + y*bytesPerRow); + for (y=y1; y<=y2; y++) + { + for (x=x1; x<=x2; x++) + fb[x] = pat->GetColor(x,y).GetColor15(); + fb = (uint16 *)((uint8 *)fb + bytesPerRow); + } + } break; + case 16: + { + uint16 *fb = (uint16 *)((uint8 *)_target->Bits() + y*bytesPerRow); + for (y=y1; y<=y2; y++) + { + for (x=x1; x<=x2; x++) + fb[x] = pat->GetColor(x,y).GetColor16(); + fb = (uint16 *)((uint8 *)fb + bytesPerRow); + } + } break; + case 24: + case 32: + { + uint32 *fb = (uint32 *)((uint8 *)_target->Bits() + y*bytesPerRow); + rgb_color color; + for (y=y1; y<=y2; y++) + { + for (x=x1; x<=x2; x++) + { + color = pat->GetColor(x,y).GetColor32(); + fb[x] = (color.alpha << 24) | (color.red << 16) | (color.green << 8) | (color.blue); + } + fb = (uint32 *)((uint8 *)fb + bytesPerRow); + } + } break; + default: + printf("Error: Unknown color space\n"); + } } diff --git a/src/servers/app/server/BitmapDriver.h b/src/servers/app/server/BitmapDriver.h index 036918b7e4..87e80da01c 100644 --- a/src/servers/app/server/BitmapDriver.h +++ b/src/servers/app/server/BitmapDriver.h @@ -79,14 +79,8 @@ public: // virtual void DrawPicture(SPicture *pic, BPoint pt); virtual void DrawString(const char *string, int32 length, BPoint pt, LayerData *d, escapement_delta *delta=NULL); - virtual void FillArc(BRect r, float angle, float span, LayerData *d, const Pattern &pat); - virtual void FillBezier(BPoint *pts, LayerData *d, const Pattern &pat); - virtual void FillEllipse(BRect r, LayerData *d, const Pattern &pat); - virtual void FillPolygon(BPoint *ptlist, int32 numpts, BRect rect, LayerData *d, const Pattern &pat); virtual void FillRect(BRect r, LayerData *d, const Pattern &pat); - virtual void FillRoundRect(BRect r, float xrad, float yrad, LayerData *d, const Pattern &pat); // virtual void FillShape(SShape *sh, LayerData *d, const Pattern &pat); - virtual void FillTriangle(BPoint *pts, BRect r, LayerData *d, const Pattern &pat); virtual void HideCursor(void); virtual void MoveCursorTo(float x, float y); @@ -95,15 +89,7 @@ public: virtual void ObscureCursor(void); virtual void SetCursor(ServerCursor *cursor); - virtual void StrokeArc(BRect r, float angle, float span, LayerData *d, const Pattern &pat); - virtual void StrokeBezier(BPoint *pts, LayerData *d, const Pattern &pat); - virtual void StrokeEllipse(BRect r, LayerData *d, const Pattern &pat); - virtual void StrokeLine(BPoint start, BPoint end, LayerData *d, const Pattern &pat); - virtual void StrokePolygon(BPoint *ptlist, int32 numpts, BRect rect, LayerData *d, const Pattern &pat, bool is_closed=true); - virtual void StrokeRect(BRect r, LayerData *d, const Pattern &pat); - virtual void StrokeRoundRect(BRect r, float xrad, float yrad, LayerData *d, const Pattern &pat); // virtual void StrokeShape(SShape *sh, LayerData *d, const Pattern &pat); - virtual void StrokeTriangle(BPoint *pts, BRect r, LayerData *d, const Pattern &pat); // virtual void StrokeLineArray(BPoint *pts, int32 numlines, RGBColor *colors, LayerData *d); virtual void SetMode(int32 mode); float StringWidth(const char *string, int32 length, LayerData *d); diff --git a/src/servers/app/server/Clipper.cpp b/src/servers/app/server/Clipper.cpp index 73e56f13f1..03b8ee49ee 100644 --- a/src/servers/app/server/Clipper.cpp +++ b/src/servers/app/server/Clipper.cpp @@ -36,37 +36,37 @@ Clipper::~Clipper() { } -void Clipper::DrawBitmap(BRegion* clip_reg, BPicture* clip_pic, ServerBitmap *bmp, BRect src, BRect dest, LayerData *d) +void Clipper::DrawBitmap(BRegion* clip_reg, ServerBitmap *bmp, BRect src, BRect dest, LayerData *d) { fDriver->DrawBitmap(bmp,src,dest,d); } -void Clipper::DrawString(BRegion* clip_reg, BPicture* clip_pic, const char *string, int32 length, BPoint pt, LayerData *d, escapement_delta *edelta) +void Clipper::DrawString(BRegion* clip_reg, const char *string, int32 length, BPoint pt, LayerData *d, escapement_delta *edelta) { fDriver->DrawString(string,length,pt,d,edelta); } -void Clipper::FillArc(BRegion* clip_reg, BPicture* clip_pic, BRect r, float angle, float span, LayerData *d, const Pattern &pat) +void Clipper::FillArc(BRegion* clip_reg, BRect r, float angle, float span, LayerData *d, const Pattern &pat) { fDriver->FillArc(r,angle,span,d,pat); } -void Clipper::FillBezier(BRegion* clip_reg, BPicture* clip_pic, BPoint *pts, LayerData *d, const Pattern &pat) +void Clipper::FillBezier(BRegion* clip_reg, BPoint *pts, LayerData *d, const Pattern &pat) { fDriver->FillBezier(pts,d,pat); } -void Clipper::FillEllipse(BRegion* clip_reg, BPicture* clip_pic, BRect r, LayerData *d, const Pattern &pat) +void Clipper::FillEllipse(BRegion* clip_reg, BRect r, LayerData *d, const Pattern &pat) { fDriver->FillEllipse(r,d,pat); } -void Clipper::FillPolygon(BRegion* clip_reg, BPicture* clip_pic, BPoint *ptlist, int32 numpts, BRect rect, LayerData *d, const Pattern &pat) +void Clipper::FillPolygon(BRegion* clip_reg, BPoint *ptlist, int32 numpts, BRect rect, LayerData *d, const Pattern &pat) { fDriver->FillPolygon(ptlist,numpts,rect,d,pat); } -void Clipper::FillRect(BRegion* clip_reg, BPicture* clip_pic, BRect r, LayerData *d, const Pattern &pat) +void Clipper::FillRect(BRegion* clip_reg, BRect r, LayerData *d, const Pattern &pat) { BRegion reg; @@ -76,7 +76,7 @@ void Clipper::FillRect(BRegion* clip_reg, BPicture* clip_pic, BRect r, LayerData fDriver->FillRegion(®,d,pat); } -void Clipper::FillRegion(BRegion* clip_reg, BPicture* clip_pic, BRegion *r, LayerData *d, const Pattern &pat) +void Clipper::FillRegion(BRegion* clip_reg, BRegion *r, LayerData *d, const Pattern &pat) { BRegion reg; @@ -86,9 +86,9 @@ void Clipper::FillRegion(BRegion* clip_reg, BPicture* clip_pic, BRegion *r, Laye fDriver->FillRegion(®,d,pat); } -void Clipper::FillRoundRect(BRegion* clip_reg, BPicture* clip_pic, BRect r, float xrad, float yrad, LayerData *d, const Pattern &pat) +void Clipper::FillRoundRect(BRegion* clip_reg, BRect r, float xrad, float yrad, LayerData *d, const Pattern &pat) { - if ( !clip_reg && !clip_pic ) + if ( !clip_reg ) fDriver->FillRoundRect(r,xrad,yrad,d,pat); else { @@ -103,64 +103,64 @@ void Clipper::FillRoundRect(BRegion* clip_reg, BPicture* clip_pic, BRect r, floa reg.Exclude(corner_rect); corner_rect.OffsetTo(r.right-xrad,r.bottom-yrad); reg.Exclude(corner_rect); - FillRegion(clip_reg,clip_pic,®,d,pat); + FillRegion(clip_reg,®,d,pat); arc_rect.OffsetTo(r.left,r.top); - FillArc(clip_reg,clip_pic,arc_rect,90,90,d,pat); + FillArc(clip_reg,arc_rect,90,90,d,pat); arc_rect.OffsetTo(r.left,r.bottom-2*yrad); - FillArc(clip_reg,clip_pic,arc_rect,180,90,d,pat); + FillArc(clip_reg,arc_rect,180,90,d,pat); arc_rect.OffsetTo(r.right-2*xrad,r.bottom-2*yrad); - FillArc(clip_reg,clip_pic,arc_rect,270,90,d,pat); + FillArc(clip_reg,arc_rect,270,90,d,pat); arc_rect.OffsetTo(r.right-2*xrad,r.top); - FillArc(clip_reg,clip_pic,arc_rect,0,90,d,pat); + FillArc(clip_reg,arc_rect,0,90,d,pat); } } -void Clipper::FillTriangle(BRegion* clip_reg, BPicture* clip_pic, BPoint *pts, BRect r, LayerData *d, const Pattern &pat) +void Clipper::FillTriangle(BRegion* clip_reg, BPoint *pts, BRect r, LayerData *d, const Pattern &pat) { fDriver->FillTriangle(pts,r,d,pat); } -void Clipper::StrokeArc(BRegion* clip_reg, BPicture* clip_pic, BRect r, float angle, float span, LayerData *d, const Pattern &pat) +void Clipper::StrokeArc(BRegion* clip_reg, BRect r, float angle, float span, LayerData *d, const Pattern &pat) { fDriver->StrokeArc(r,angle,span,d,pat); } -void Clipper::StrokeBezier(BRegion* clip_reg, BPicture* clip_pic, BPoint *pts, LayerData *d, const Pattern &pat) +void Clipper::StrokeBezier(BRegion* clip_reg, BPoint *pts, LayerData *d, const Pattern &pat) { fDriver->StrokeBezier(pts,d,pat); } -void Clipper::StrokeEllipse(BRegion* clip_reg, BPicture* clip_pic, BRect r, LayerData *d, const Pattern &pat) +void Clipper::StrokeEllipse(BRegion* clip_reg, BRect r, LayerData *d, const Pattern &pat) { fDriver->StrokeEllipse(r,d,pat); } -void Clipper::StrokeLine(BRegion* clip_reg, BPicture* clip_pic, BPoint start, BPoint end, LayerData *d, const Pattern &pat) +void Clipper::StrokeLine(BRegion* clip_reg, BPoint start, BPoint end, LayerData *d, const Pattern &pat) { fDriver->StrokeLine(start,end,d,pat); } -void Clipper::StrokePolygon(BRegion* clip_reg, BPicture* clip_pic, BPoint *ptlist, int32 numpts, BRect rect, LayerData *d, const Pattern &pat, bool is_closed) +void Clipper::StrokePolygon(BRegion* clip_reg, BPoint *ptlist, int32 numpts, BRect rect, LayerData *d, const Pattern &pat, bool is_closed) { fDriver->StrokePolygon(ptlist,numpts,rect,d,pat,is_closed); } -void Clipper::StrokeRect(BRegion* clip_reg, BPicture* clip_pic, BRect r, LayerData *d, const Pattern &pat) +void Clipper::StrokeRect(BRegion* clip_reg, BRect r, LayerData *d, const Pattern &pat) { fDriver->StrokeRect(r,d,pat); } -void Clipper::StrokeRoundRect(BRegion* clip_reg, BPicture* clip_pic, BRect r, float xrad, float yrad, LayerData *d, const Pattern &pat) +void Clipper::StrokeRoundRect(BRegion* clip_reg, BRect r, float xrad, float yrad, LayerData *d, const Pattern &pat) { fDriver->StrokeRoundRect(r,xrad,yrad,d,pat); } -void Clipper::StrokeTriangle(BRegion* clip_reg, BPicture* clip_pic, BPoint *pts, BRect r, LayerData *d, const Pattern &pat) +void Clipper::StrokeTriangle(BRegion* clip_reg, BPoint *pts, BRect r, LayerData *d, const Pattern &pat) { fDriver->StrokeTriangle(pts,r,d,pat); } -void Clipper::StrokeLineArray(BRegion* clip_reg, BPicture* clip_pic, BPoint *pts, int32 numlines, RGBColor *colors, LayerData *d) +void Clipper::StrokeLineArray(BRegion* clip_reg, BPoint *pts, int32 numlines, RGBColor *colors, LayerData *d) { fDriver->StrokeLineArray(pts,numlines,colors,d); } diff --git a/src/servers/app/server/Clipper.h b/src/servers/app/server/Clipper.h index c5d1dc3099..5f8d92d54c 100644 --- a/src/servers/app/server/Clipper.h +++ b/src/servers/app/server/Clipper.h @@ -38,29 +38,29 @@ public: Clipper(DisplayDriver* driver); ~Clipper(); - void DrawBitmap(BRegion* clip_reg, BPicture* clip_pic, ServerBitmap *bmp, BRect src, BRect dest, LayerData *d); - void DrawString(BRegion* clip_reg, BPicture* clip_pic, const char *string, int32 length, BPoint pt, LayerData *d, escapement_delta *edelta=NULL); + void DrawBitmap(BRegion* clip_reg, ServerBitmap *bmp, BRect src, BRect dest, LayerData *d); + void DrawString(BRegion* clip_reg, const char *string, int32 length, BPoint pt, LayerData *d, escapement_delta *edelta=NULL); - void FillArc(BRegion* clip_reg, BPicture* clip_pic, BRect r, float angle, float span, LayerData *d, const Pattern &pat); - void FillBezier(BRegion* clip_reg, BPicture* clip_pic, BPoint *pts, LayerData *d, const Pattern &pat); - void FillEllipse(BRegion* clip_reg, BPicture* clip_pic, BRect r, LayerData *d, const Pattern &pat); - void FillPolygon(BRegion* clip_reg, BPicture* clip_pic, BPoint *ptlist, int32 numpts, BRect rect, LayerData *d, const Pattern &pat); - void FillRect(BRegion* clip_reg, BPicture* clip_pic, BRect r, LayerData *d, const Pattern &pat); - void FillRegion(BRegion* clip_reg, BPicture* clip_pic, BRegion* r, LayerData *d, const Pattern &pat); - void FillRoundRect(BRegion* clip_reg, BPicture* clip_pic, BRect r, float xrad, float yrad, LayerData *d, const Pattern &pat); -// void FillShape(BRegion* clip_reg, BPicture* clip_pic, SShape *sh, LayerData *d, const Pattern &pat); - void FillTriangle(BRegion* clip_reg, BPicture* clip_pic, BPoint *pts, BRect r, LayerData *d, const Pattern &pat); + void FillArc(BRegion* clip_reg, BRect r, float angle, float span, LayerData *d, const Pattern &pat); + void FillBezier(BRegion* clip_reg, BPoint *pts, LayerData *d, const Pattern &pat); + void FillEllipse(BRegion* clip_reg, BRect r, LayerData *d, const Pattern &pat); + void FillPolygon(BRegion* clip_reg, BPoint *ptlist, int32 numpts, BRect rect, LayerData *d, const Pattern &pat); + void FillRect(BRegion* clip_reg, BRect r, LayerData *d, const Pattern &pat); + void FillRegion(BRegion* clip_reg, BRegion* r, LayerData *d, const Pattern &pat); + void FillRoundRect(BRegion* clip_reg, BRect r, float xrad, float yrad, LayerData *d, const Pattern &pat); +// void FillShape(BRegion* clip_reg, SShape *sh, LayerData *d, const Pattern &pat); + void FillTriangle(BRegion* clip_reg, BPoint *pts, BRect r, LayerData *d, const Pattern &pat); - void StrokeArc(BRegion* clip_reg, BPicture* clip_pic, BRect r, float angle, float span, LayerData *d, const Pattern &pat); - void StrokeBezier(BRegion* clip_reg, BPicture* clip_pic, BPoint *pts, LayerData *d, const Pattern &pat); - void StrokeEllipse(BRegion* clip_reg, BPicture* clip_pic, BRect r, LayerData *d, const Pattern &pat); - void StrokeLine(BRegion* clip_reg, BPicture* clip_pic, BPoint start, BPoint end, LayerData *d, const Pattern &pat); - void StrokePolygon(BRegion* clip_reg, BPicture* clip_pic, BPoint *ptlist, int32 numpts, BRect rect, LayerData *d, const Pattern &pat, bool is_closed=true); - void StrokeRect(BRegion* clip_reg, BPicture* clip_pic, BRect r, LayerData *d, const Pattern &pat); - void StrokeRoundRect(BRegion* clip_reg, BPicture* clip_pic, BRect r, float xrad, float yrad, LayerData *d, const Pattern &pat); -// void StrokeShape(BRegion* clip_reg, BPicture* clip_pic, SShape *sh, LayerData *d, const Pattern &pat); - void StrokeTriangle(BRegion* clip_reg, BPicture* clip_pic, BPoint *pts, BRect r, LayerData *d, const Pattern &pat); - void StrokeLineArray(BRegion* clip_reg, BPicture* clip_pic, BPoint *pts, int32 numlines, RGBColor *colors, LayerData *d); + void StrokeArc(BRegion* clip_reg, BRect r, float angle, float span, LayerData *d, const Pattern &pat); + void StrokeBezier(BRegion* clip_reg, BPoint *pts, LayerData *d, const Pattern &pat); + void StrokeEllipse(BRegion* clip_reg, BRect r, LayerData *d, const Pattern &pat); + void StrokeLine(BRegion* clip_reg, BPoint start, BPoint end, LayerData *d, const Pattern &pat); + void StrokePolygon(BRegion* clip_reg, BPoint *ptlist, int32 numpts, BRect rect, LayerData *d, const Pattern &pat, bool is_closed=true); + void StrokeRect(BRegion* clip_reg, BRect r, LayerData *d, const Pattern &pat); + void StrokeRoundRect(BRegion* clip_reg, BRect r, float xrad, float yrad, LayerData *d, const Pattern &pat); +// void StrokeShape(BRegion* clip_reg, SShape *sh, LayerData *d, const Pattern &pat); + void StrokeTriangle(BRegion* clip_reg, BPoint *pts, BRect r, LayerData *d, const Pattern &pat); + void StrokeLineArray(BRegion* clip_reg, BPoint *pts, int32 numlines, RGBColor *colors, LayerData *d); private: DisplayDriver* fDriver; }; diff --git a/src/servers/app/server/DisplayDriver.cpp b/src/servers/app/server/DisplayDriver.cpp index 6845c1b983..215bbe0141 100644 --- a/src/servers/app/server/DisplayDriver.cpp +++ b/src/servers/app/server/DisplayDriver.cpp @@ -27,8 +27,89 @@ //------------------------------------------------------------------------------ #include #include "DisplayDriver.h" +#include "LayerData.h" #include "ServerCursor.h" +#define CLIP_X(a) ( (a < 0) ? 0 : ((a > _buffer_width-1) ? \ + _buffer_width-1 : a) ) +#define CLIP_Y(a) ( (a < 0) ? 0 : ((a > _buffer_height-1) ? \ + _buffer_height-1 : a) ) +#define CHECK_X(a) ( (a >= 0) || (a <= _buffer_width-1) ) +#define CHECK_Y(a) ( (a >= 0) || (a <= _buffer_height-1) ) + +/* TODO: Add handling of draw modes */ + +AccLineCalc::AccLineCalc() +{ +} + +AccLineCalc::AccLineCalc(const BPoint &pta, const BPoint &ptb) +{ + start=pta; + end=ptb; + slope=(start.y-end.y)/(start.x-end.x); + offset=start.y-(slope * start.x); + minx = MIN(start.x,end.x); + maxx = MAX(start.x,end.x); + miny = MIN(start.y,end.y); + maxy = MAX(start.y,end.y); +} + +void AccLineCalc::SetPoints(const BPoint &pta, const BPoint &ptb) +{ + start=pta; + end=ptb; + slope=(start.y-end.y)/(start.x-end.x); + offset=start.y-(slope * start.x); + minx = MIN(start.x,end.x); + maxx = MAX(start.x,end.x); + miny = MIN(start.y,end.y); + maxy = MAX(start.y,end.y); +} + +void AccLineCalc::Swap(AccLineCalc &from) +{ + BPoint pta, ptb; + pta = start; + ptb = end; + SetPoints(from.start,from.end); + from.SetPoints(pta,ptb); +} + +float AccLineCalc::GetX(float y) +{ + if (start.x == end.x) + return start.x; + return ( (y-offset)/slope ); +} + +float AccLineCalc::MinX() +{ + return minx; +} + +float AccLineCalc::MaxX() +{ + return maxx; +} + +float AccLineCalc::GetY(float x) +{ + if ( start.x == end.x ) + return start.y; + return ( (slope * x) + offset ); +} + +float AccLineCalc::MinY() +{ + return miny; +} + +float AccLineCalc::MaxY() +{ + return maxy; +} + /*! \brief Sets up internal variables needed by all DisplayDriver subclasses @@ -150,6 +231,533 @@ void DisplayDriver::DrawString(const char *string, int32 length, BPoint pt, Laye */ void DisplayDriver::FillArc(BRect r, float angle, float span, LayerData *d, const Pattern &pat) { + 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; + float oldpensize; + BPoint center(xc,yc); + + // Watch out for bozos giving us whacko spans + if ( (span >= 360) || (span <= -360) ) + { + FillEllipse(r,d,pat); + return; + } + + Lock(); + PatternHandler pattern(pat); + pattern.SetColors(d->highcolor, d->lowcolor); + oldpensize = d->pensize; + d->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 && CHECK_Y(yc-y) && (CHECK_X(xc) || CHECK_X(xc+x)) ) + HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc+x)),ROUND(yc-y),&pattern); + if ( useQuad2 && CHECK_Y(yc-y) && (CHECK_X(xc) || CHECK_X(xc-x)) ) + HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc-x)),ROUND(yc-y),&pattern); + if ( useQuad3 && CHECK_Y(yc+y) && (CHECK_X(xc) || CHECK_X(xc-x)) ) + HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc-x)),ROUND(yc+y),&pattern); + if ( useQuad4 && CHECK_Y(yc+y) && (CHECK_X(xc) || CHECK_X(xc+x)) ) + HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc+x)),ROUND(yc+y),&pattern); + if ( (!shortspan && (((startQuad == 1) && (x <= startx)) || ((endQuad == 1) && (x >= endx)))) || + (shortspan && (startQuad == 1) && (x <= startx) && (x >= endx)) ) + StrokeLine(BPoint(xc+x,yc-y),center,d,pat); + if ( (!shortspan && (((startQuad == 2) && (x >= startx)) || ((endQuad == 2) && (x <= endx)))) || + (shortspan && (startQuad == 2) && (x >= startx) && (x <= endx)) ) + StrokeLine(BPoint(xc-x,yc-y),center,d,pat); + if ( (!shortspan && (((startQuad == 3) && (x <= startx)) || ((endQuad == 3) && (x >= endx)))) || + (shortspan && (startQuad == 3) && (x <= startx) && (x >= endx)) ) + StrokeLine(BPoint(xc-x,yc+y),center,d,pat); + if ( (!shortspan && (((startQuad == 4) && (x >= startx)) || ((endQuad == 4) && (x <= endx)))) || + (shortspan && (startQuad == 4) && (x >= startx) && (x <= endx)) ) + StrokeLine(BPoint(xc+x,yc+y),center,d,pat); + + 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 && CHECK_Y(yc-y) && (CHECK_X(xc) || CHECK_X(xc+x)) ) + HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc+x)),ROUND(yc-y),&pattern); + if ( useQuad2 && CHECK_Y(yc-y) && (CHECK_X(xc) || CHECK_X(xc-x)) ) + HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc-x)),ROUND(yc-y),&pattern); + if ( useQuad3 && CHECK_Y(yc+y) && (CHECK_X(xc) || CHECK_X(xc-x)) ) + HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc-x)),ROUND(yc+y),&pattern); + if ( useQuad4 && CHECK_Y(yc+y) && (CHECK_X(xc) || CHECK_X(xc+x)) ) + HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc+x)),ROUND(yc+y),&pattern); + if ( !shortspan ) + { + if ( startQuad == 1 ) + { + if ( CHECK_Y(yc-y) ) + { + if ( x <= startx ) + { + if ( CHECK_X(xc) || CHECK_X(xc+x) ) + HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc+x)),ROUND(yc-y),&pattern); + } + else + { + xclip = ROUND(y*startx/(double)starty); + if ( CHECK_X(xc) || CHECK_X(xc+xclip) ) + HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc+xclip)),ROUND(yc-y),&pattern); + } + } + } + else if ( startQuad == 2 ) + { + if ( CHECK_Y(yc-y) ) + { + if ( x >= startx ) + { + xclip = ROUND(y*startx/(double)starty); + if ( CHECK_X(xc-x) || CHECK_X(xc-xclip) ) + HLine(ROUND(CLIP_X(xc-x)),ROUND(CLIP_X(xc-xclip)),ROUND(yc-y),&pattern); + } + } + } + else if ( startQuad == 3 ) + { + if ( CHECK_Y(yc+y) ) + { + if ( x <= startx ) + { + if ( CHECK_X(xc-x) || CHECK_X(xc) ) + HLine(ROUND(CLIP_X(xc-x)),ROUND(CLIP_X(xc)),ROUND(yc+y),&pattern); + } + else + { + xclip = ROUND(y*startx/(double)starty); + if ( CHECK_X(xc-xclip) || CHECK_X(xc) ) + HLine(ROUND(CLIP_X(xc-xclip)),ROUND(CLIP_X(xc)),ROUND(yc+y),&pattern); + } + } + } + else if ( startQuad == 4 ) + { + if ( CHECK_Y(yc+y) ) + { + if ( x >= startx ) + { + xclip = ROUND(y*startx/(double)starty); + if ( CHECK_X(xc+xclip) || CHECK_X(xc+x) ) + HLine(ROUND(CLIP_X(xc+xclip)),ROUND(CLIP_X(xc+x)),ROUND(yc+y),&pattern); + } + } + } + + if ( endQuad == 1 ) + { + if ( CHECK_Y(yc-y) ) + { + if ( x >= endx ) + { + xclip = ROUND(y*endx/(double)endy); + if ( CHECK_X(xc+xclip) || CHECK_X(xc+x) ) + HLine(ROUND(CLIP_X(xc+xclip)),ROUND(CLIP_X(xc+x)),ROUND(yc-y),&pattern); + } + } + } + else if ( endQuad == 2 ) + { + if ( CHECK_Y(yc-y) ) + { + if ( x <= endx ) + { + if ( CHECK_X(xc-x) || CHECK_X(xc) ) + HLine(ROUND(CLIP_X(xc-x)),ROUND(CLIP_X(xc)),ROUND(yc-y),&pattern); + } + else + { + xclip = ROUND(y*endx/(double)endy); + if ( CHECK_X(xc-xclip) || CHECK_X(xc) ) + HLine(ROUND(CLIP_X(xc-xclip)),ROUND(CLIP_X(xc)),ROUND(yc-y),&pattern); + } + } + } + else if ( endQuad == 3 ) + { + if ( CHECK_Y(yc+y) ) + { + if ( x >= endx ) + { + xclip = ROUND(y*endx/(double)endy); + if ( CHECK_X(xc-x) || CHECK_X(xc-xclip) ) + HLine(ROUND(CLIP_X(xc-x)),ROUND(CLIP_X(xc-xclip)),ROUND(yc+y),&pattern); + } + } + } + else if ( endQuad == 4 ) + { + if ( CHECK_Y(yc+y) ) + { + if ( x <= endx ) + { + if ( CHECK_X(xc) || CHECK_X(xc+x) ) + HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc+x)),ROUND(yc+y),&pattern); + } + else + { + xclip = ROUND(y*endx/(double)endy); + if ( CHECK_X(xc) || CHECK_X(xc+xclip) ) + HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc+xclip)),ROUND(yc+y),&pattern); + } + } + } + } + else + { + startclip = ROUND(y*startx/(double)starty); + endclip = ROUND(y*endx/(double)endy); + if ( startQuad == 1 ) + { + if ( CHECK_Y(yc-y) ) + { + if ( (x <= startx) && (x >= endx) ) + { + if ( CHECK_X(xc+endclip) || CHECK_X(xc+x) ) + HLine(ROUND(CLIP_X(xc+endclip)),ROUND(CLIP_X(xc+x)),ROUND(yc-y),&pattern); + } + else + { + if ( CHECK_X(xc+endclip) || CHECK_X(xc+startclip) ) + HLine(ROUND(CLIP_X(xc+endclip)),ROUND(CLIP_X(xc+startclip)),ROUND(yc-y),&pattern); + } + } + } + else if ( startQuad == 2 ) + { + if ( CHECK_Y(yc-y) ) + { + if ( (x <= startx) && (x >= endx) ) + { + if ( CHECK_X(xc-x) || CHECK_X(xc-startclip) ) + HLine(ROUND(CLIP_X(xc-x)),ROUND(CLIP_X(xc-startclip)),ROUND(yc-y),&pattern); + } + else + { + if ( CHECK_X(xc-endclip) || CHECK_X(xc-startclip) ) + HLine(ROUND(CLIP_X(xc-endclip)),ROUND(CLIP_X(xc-startclip)),ROUND(yc-y),&pattern); + } + } + } + else if ( startQuad == 3 ) + { + if ( CHECK_Y(yc+y) ) + { + if ( (x <= startx) && (x >= endx) ) + { + if ( CHECK_X(xc-x) || CHECK_X(xc-endclip) ) + HLine(ROUND(CLIP_X(xc-x)),ROUND(CLIP_X(xc-endclip)),ROUND(yc+y),&pattern); + } + else + { + if ( CHECK_X(xc-startclip) || CHECK_X(xc-endclip) ) + HLine(ROUND(CLIP_X(xc-startclip)),ROUND(CLIP_X(xc-endclip)),ROUND(yc+y),&pattern); + } + } + } + else if ( startQuad == 4 ) + { + if ( CHECK_Y(yc+y) ) + { + if ( (x <= startx) && (x >= endx) ) + { + if ( CHECK_X(xc+startclip) || CHECK_X(xc+x) ) + HLine(ROUND(CLIP_X(xc+startclip)),ROUND(CLIP_X(xc+x)),ROUND(yc+y),&pattern); + } + else + { + if ( CHECK_X(xc+startclip) || CHECK_X(xc+endclip) ) + HLine(ROUND(CLIP_X(xc+startclip)),ROUND(CLIP_X(xc+endclip)),ROUND(yc+y),&pattern); + } + } + } + } + } + + 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 && CHECK_Y(yc-y) && (CHECK_X(xc) || CHECK_X(xc+x)) ) + HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc+x)),ROUND(yc-y),&pattern); + if ( useQuad2 && CHECK_Y(yc-y) && (CHECK_X(xc) || CHECK_X(xc-x)) ) + HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc-x)),ROUND(yc-y),&pattern); + if ( useQuad3 && CHECK_Y(yc+y) && (CHECK_X(xc) || CHECK_X(xc-x)) ) + HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc-x)),ROUND(yc+y),&pattern); + if ( useQuad4 && CHECK_Y(yc+y) && (CHECK_X(xc) || CHECK_X(xc+x)) ) + HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc+x)),ROUND(yc+y),&pattern); + if ( !shortspan ) + { + if ( startQuad == 1 ) + { + if ( CHECK_Y(yc-y) ) + { + if ( x <= startx ) + { + if ( CHECK_X(xc) || CHECK_X(xc+x) ) + HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc+x)),ROUND(yc-y),&pattern); + } + else + { + xclip = ROUND(y*startx/(double)starty); + if ( CHECK_X(xc) || CHECK_X(xc+xclip) ) + HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc+xclip)),ROUND(yc-y),&pattern); + } + } + } + else if ( startQuad == 2 ) + { + if ( CHECK_Y(yc-y) ) + { + if ( x >= startx ) + { + xclip = ROUND(y*startx/(double)starty); + if ( CHECK_X(xc-x) || CHECK_X(xc-xclip) ) + HLine(ROUND(CLIP_X(xc-x)),ROUND(CLIP_X(xc-xclip)),ROUND(yc-y),&pattern); + } + } + } + else if ( startQuad == 3 ) + { + if ( CHECK_Y(yc+y) ) + { + if ( x <= startx ) + { + if ( CHECK_X(xc-x) || CHECK_X(xc) ) + HLine(ROUND(CLIP_X(xc-x)),ROUND(CLIP_X(xc)),ROUND(yc+y),&pattern); + } + else + { + xclip = ROUND(y*startx/(double)starty); + if ( CHECK_X(xc-xclip) || CHECK_X(xc) ) + HLine(ROUND(CLIP_X(xc-xclip)),ROUND(CLIP_X(xc)),ROUND(yc+y),&pattern); + } + } + } + else if ( startQuad == 4 ) + { + if ( CHECK_Y(yc+y) ) + { + if ( x >= startx ) + { + xclip = ROUND(y*startx/(double)starty); + if ( CHECK_X(xc+xclip) || CHECK_X(xc+x) ) + HLine(ROUND(CLIP_X(xc+xclip)),ROUND(CLIP_X(xc+x)),ROUND(yc+y),&pattern); + } + } + } + + if ( endQuad == 1 ) + { + if ( CHECK_Y(yc-y) ) + { + if ( x >= endx ) + { + xclip = ROUND(y*endx/(double)endy); + if ( CHECK_X(xc+xclip) || CHECK_X(xc+x) ) + HLine(ROUND(CLIP_X(xc+xclip)),ROUND(CLIP_X(xc+x)),ROUND(yc-y),&pattern); + } + } + } + else if ( endQuad == 2 ) + { + if ( CHECK_Y(yc-y) ) + { + if ( x <= endx ) + { + if ( CHECK_X(xc-x) || CHECK_X(xc) ) + HLine(ROUND(CLIP_X(xc-x)),ROUND(CLIP_X(xc)),ROUND(yc-y),&pattern); + } + else + { + xclip = ROUND(y*endx/(double)endy); + if ( CHECK_X(xc-xclip) || CHECK_X(xc) ) + HLine(ROUND(CLIP_X(xc-xclip)),ROUND(CLIP_X(xc)),ROUND(yc-y),&pattern); + } + } + } + else if ( endQuad == 3 ) + { + if ( CHECK_Y(yc+y) ) + { + if ( x >= endx ) + { + xclip = ROUND(y*endx/(double)endy); + if ( CHECK_X(xc-x) || CHECK_X(xc-xclip) ) + HLine(ROUND(CLIP_X(xc-x)),ROUND(CLIP_X(xc-xclip)),ROUND(yc+y),&pattern); + } + } + } + else if ( endQuad == 4 ) + { + if ( CHECK_Y(yc+y) ) + { + if ( x <= endx ) + { + if ( CHECK_X(xc) || CHECK_X(xc+x) ) + HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc+x)),ROUND(yc+y),&pattern); + } + else + { + xclip = ROUND(y*endx/(double)endy); + if ( CHECK_X(xc) || CHECK_X(xc+xclip) ) + HLine(ROUND(CLIP_X(xc)),ROUND(CLIP_X(xc+xclip)),ROUND(yc+y),&pattern); + } + } + } + } + else + { + startclip = ROUND(y*startx/(double)starty); + endclip = ROUND(y*endx/(double)endy); + if ( startQuad == 1 ) + { + if ( CHECK_Y(yc-y) ) + { + if ( (x <= startx) && (x >= endx) ) + { + if ( CHECK_X(xc+endclip) || CHECK_X(xc+x) ) + HLine(ROUND(CLIP_X(xc+endclip)),ROUND(CLIP_X(xc+x)),ROUND(yc-y),&pattern); + } + else + { + if ( CHECK_X(xc+endclip) || CHECK_X(xc+startclip) ) + HLine(ROUND(CLIP_X(xc+endclip)),ROUND(CLIP_X(xc+startclip)),ROUND(yc-y),&pattern); + } + } + } + else if ( startQuad == 2 ) + { + if ( CHECK_Y(yc-y) ) + { + if ( (x <= startx) && (x >= endx) ) + { + if ( CHECK_X(xc-x) || CHECK_X(xc-startclip) ) + HLine(ROUND(CLIP_X(xc-x)),ROUND(CLIP_X(xc-startclip)),ROUND(yc-y),&pattern); + } + else + { + if ( CHECK_X(xc-endclip) || CHECK_X(xc-startclip) ) + HLine(ROUND(CLIP_X(xc-endclip)),ROUND(CLIP_X(xc-startclip)),ROUND(yc-y),&pattern); + } + } + } + else if ( startQuad == 3 ) + { + if ( CHECK_Y(yc+y) ) + { + if ( (x <= startx) && (x >= endx) ) + { + if ( CHECK_X(xc-x) || CHECK_X(xc-endclip) ) + HLine(ROUND(CLIP_X(xc-x)),ROUND(CLIP_X(xc-endclip)),ROUND(yc+y),&pattern); + } + else + { + if ( CHECK_X(xc-startclip) || CHECK_X(xc-endclip) ) + HLine(ROUND(CLIP_X(xc-startclip)),ROUND(CLIP_X(xc-endclip)),ROUND(yc+y),&pattern); + } + } + } + else if ( startQuad == 4 ) + { + if ( CHECK_Y(yc+y) ) + { + if ( (x <= startx) && (x >= endx) ) + { + if ( CHECK_X(xc+startclip) || CHECK_X(xc+x) ) + HLine(ROUND(CLIP_X(xc+startclip)),ROUND(CLIP_X(xc+x)),ROUND(yc+y),&pattern); + } + else + { + if ( CHECK_X(xc+startclip) || CHECK_X(xc+endclip) ) + HLine(ROUND(CLIP_X(xc+startclip)),ROUND(CLIP_X(xc+endclip)),ROUND(yc+y),&pattern); + } + } + } + } + } + d->pensize = oldpensize; + Unlock(); } /*! @@ -160,9 +768,76 @@ void DisplayDriver::FillArc(BRect r, float angle, float span, LayerData *d, cons \param pat 8-byte array containing the const Pattern &to use. Always non-NULL. Bounds checking must be done in this call. + Does not work quite right, need to redo this. */ void DisplayDriver::FillBezier(BPoint *pts, LayerData *d, const Pattern &pat) { + 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; + + AccLineCalc 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; + + 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(); } /*! @@ -176,6 +851,78 @@ void DisplayDriver::FillBezier(BPoint *pts, LayerData *d, const Pattern &pat) */ void DisplayDriver::FillEllipse(BRect r, LayerData *d, const Pattern &pat) { + 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; + + Lock(); + PatternHandler pattern(pat); + pattern.SetColors(d->highcolor, d->lowcolor); + + if ( CHECK_X(xc) ) + { + if ( CHECK_Y(yc-y) ) + SetPixel(ROUND(xc),ROUND(yc-y),pattern.GetColor(xc,yc-y)); + if ( CHECK_Y(yc+y) ) + SetPixel(ROUND(xc),ROUND(yc+y),pattern.GetColor(xc,yc+y)); + } + + 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 ( CHECK_X(xc-x) || CHECK_X(xc+x) ) + { + if ( CHECK_Y(yc-y) ) + HLine(ROUND(CLIP_X(xc-x)),ROUND(CLIP_X(xc+x)),ROUND(yc-y),&pattern); + if ( CHECK_Y(yc+y) ) + HLine(ROUND(CLIP_X(xc-x)),ROUND(CLIP_X(xc+x)),ROUND(yc+y),&pattern); + } + } + + 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 ( CHECK_X(xc-x) || CHECK_X(xc+x) ) + { + if ( CHECK_Y(yc-y) ) + HLine(ROUND(CLIP_X(xc-x)),ROUND(CLIP_X(xc+x)),ROUND(yc-y),&pattern); + if ( CHECK_Y(yc+y) ) + HLine(ROUND(CLIP_X(xc-x)),ROUND(CLIP_X(xc+x)),ROUND(yc+y),&pattern); + } + } + Unlock(); } /*! @@ -191,6 +938,128 @@ void DisplayDriver::FillEllipse(BRect r, LayerData *d, const Pattern &pat) */ void DisplayDriver::FillPolygon(BPoint *ptlist, int32 numpts, BRect rect, LayerData *d, const Pattern &pat) { + /* 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. + */ + Lock(); + if ( !ptlist || (numpts < 3) ) + { + Unlock(); + return; + } + PatternHandler pattern(pat); + pattern.SetColors(d->highcolor, d->lowcolor); + + BPoint *currentPoint, *nextPoint; + BPoint tempNextPoint; + BPoint tempCurrentPoint; + int currentIndex, bestIndex, i, j, y; + AccLineCalc *segmentArray = new AccLineCalc[2*numpts]; + int numSegments = 0; + + /* 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; + return; + } + + 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; i y) + break; + if (segmentArray[i].MaxY() < y) + { + i++; + continue; + } + if (segmentArray[i].MinY() == segmentArray[i].MaxY()) + { + if ( (segmentArray[i].MinX() < _buffer_width) && + (segmentArray[i].MaxX() >= 0) ) + HLine(CLIP_X(ROUND(segmentArray[i].MinX())), + CLIP_X(ROUND(segmentArray[i].MaxX())), + y, &pattern); + i++; + } + else + { + if ( (segmentArray[i].GetX(y) < _buffer_width) && + (segmentArray[i+1].GetX(y) >= 0) ) + HLine(CLIP_X(ROUND(segmentArray[i].GetX(y))), + CLIP_X(ROUND(segmentArray[i+1].GetX(y))), + y, &pattern); + i+=2; + } + } + } + } + delete[] segmentArray; + Unlock(); } /*! @@ -237,6 +1106,28 @@ void DisplayDriver::FillRegion(BRegion *r, LayerData *d, const Pattern &pat) */ void DisplayDriver::FillRoundRect(BRect r, float xrad, float yrad, LayerData *d, const Pattern &pat) { + float arc_x; + float yrad2 = yrad*yrad; + int i; + + Lock(); + PatternHandler pattern(pat); + pattern.SetColors(d->highcolor, d->lowcolor); + + for (i=0; i<=(int)yrad; i++) + { + arc_x = xrad*sqrt(1-i*i/yrad2); + if ( CHECK_Y(r.top+yrad-i) ) + HLine(ROUND(CLIP_X(r.left+xrad-arc_x)), ROUND(CLIP_X(r.right-xrad+arc_x)), + ROUND(r.top+yrad-i), &pattern); + if ( CHECK_Y(r.bottom-yrad+i) ) + HLine(ROUND(CLIP_X(r.left+xrad-arc_x)), ROUND(CLIP_X(r.right-xrad+arc_x)), + ROUND(r.bottom-yrad+i), &pattern); + } + FillRect(BRect(CLIP_X(r.left),CLIP_Y(r.top+yrad), + CLIP_X(r.right),CLIP_Y(r.bottom-yrad)), d, pat); + + Unlock(); } //void DisplayDriver::FillShape(SShape *sh, LayerData *d, const Pattern &pat) @@ -256,6 +1147,108 @@ void DisplayDriver::FillRoundRect(BRect r, float xrad, float yrad, LayerData *d, */ void DisplayDriver::FillTriangle(BPoint *pts, BRect r, LayerData *d, const Pattern &pat) { + if(!pts || !d) + return; + + Lock(); + BPoint first, second, third; + PatternHandler pattern(pat); + pattern.SetColors(d->highcolor, d->lowcolor); + + // 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,d,pat); + return; + } + + Lock(); + PatternHandler pattern(pat); + pattern.SetColors(d->highcolor, d->lowcolor); + + thick = (int)d->pensize; + 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); + } + } + + /* SetThickPixel does bounds checking, so we don't have to worry about it here */ + if ( useQuad1 || + (!shortspan && (((startQuad == 1) && (x <= startx)) || ((endQuad == 1) && (x >= endx)))) || + (shortspan && (startQuad == 1) && (x <= startx) && (x >= endx)) ) + SetThickPixel(ROUND(xc+x),ROUND(yc-y),thick,&pattern); + if ( useQuad2 || + (!shortspan && (((startQuad == 2) && (x >= startx)) || ((endQuad == 2) && (x <= endx)))) || + (shortspan && (startQuad == 2) && (x >= startx) && (x <= endx)) ) + SetThickPixel(ROUND(xc-x),ROUND(yc-y),thick,&pattern); + if ( useQuad3 || + (!shortspan && (((startQuad == 3) && (x <= startx)) || ((endQuad == 3) && (x >= endx)))) || + (shortspan && (startQuad == 3) && (x <= startx) && (x >= endx)) ) + SetThickPixel(ROUND(xc-x),ROUND(yc+y),thick,&pattern); + if ( useQuad4 || + (!shortspan && (((startQuad == 4) && (x >= startx)) || ((endQuad == 4) && (x <= endx)))) || + (shortspan && (startQuad == 4) && (x >= startx) && (x <= endx)) ) + SetThickPixel(ROUND(xc+x),ROUND(yc+y),thick,&pattern); + + 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 || + (!shortspan && (((startQuad == 1) && (x <= startx)) || ((endQuad == 1) && (x >= endx)))) || + (shortspan && (startQuad == 1) && (x <= startx) && (x >= endx)) ) + SetThickPixel(ROUND(xc+x),ROUND(yc-y),thick,&pattern); + if ( useQuad2 || + (!shortspan && (((startQuad == 2) && (x >= startx)) || ((endQuad == 2) && (x <= endx)))) || + (shortspan && (startQuad == 2) && (x >= startx) && (x <= endx)) ) + SetThickPixel(ROUND(xc-x),ROUND(yc-y),thick,&pattern); + if ( useQuad3 || + (!shortspan && (((startQuad == 3) && (x <= startx)) || ((endQuad == 3) && (x >= endx)))) || + (shortspan && (startQuad == 3) && (x <= startx) && (x >= endx)) ) + SetThickPixel(ROUND(xc-x),ROUND(yc+y),thick,&pattern); + if ( useQuad4 || + (!shortspan && (((startQuad == 4) && (x >= startx)) || ((endQuad == 4) && (x <= endx)))) || + (shortspan && (startQuad == 4) && (x >= startx) && (x <= endx)) ) + SetThickPixel(ROUND(xc+x),ROUND(yc+y),thick,&pattern); + } + + 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 || + (!shortspan && (((startQuad == 1) && (x <= startx)) || ((endQuad == 1) && (x >= endx)))) || + (shortspan && (startQuad == 1) && (x <= startx) && (x >= endx)) ) + SetThickPixel(ROUND(xc+x),ROUND(yc-y),thick,&pattern); + if ( useQuad2 || + (!shortspan && (((startQuad == 2) && (x >= startx)) || ((endQuad == 2) && (x <= endx)))) || + (shortspan && (startQuad == 2) && (x >= startx) && (x <= endx)) ) + SetThickPixel(ROUND(xc-x),ROUND(yc-y),thick,&pattern); + if ( useQuad3 || + (!shortspan && (((startQuad == 3) && (x <= startx)) || ((endQuad == 3) && (x >= endx)))) || + (shortspan && (startQuad == 3) && (x <= startx) && (x >= endx)) ) + SetThickPixel(ROUND(xc-x),ROUND(yc+y),thick,&pattern); + if ( useQuad4 || + (!shortspan && (((startQuad == 4) && (x >= startx)) || ((endQuad == 4) && (x <= endx)))) || + (shortspan && (startQuad == 4) && (x >= startx) && (x <= endx)) ) + SetThickPixel(ROUND(xc+x),ROUND(yc+y),thick,&pattern); + } + Unlock(); } /*! @@ -384,6 +1531,61 @@ void DisplayDriver::StrokeArc(BRect r, float angle, float span, LayerData *d, co */ void DisplayDriver::StrokeBezier(BPoint *pts, LayerData *d, const Pattern &pat) { + 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; + + Lock(); + PatternHandler pattern(pat); + pattern.SetColors(d->highcolor, d->lowcolor); + + 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); + /* SetThickPixel does bounds checking, so we don't have to worry about it */ + if ( (x!=lastx) || (y!=lasty) ) + SetThickPixel(x,y,ROUND(d->pensize),&pattern); + lastx = x; + lasty = y; + + X += dx; + dx += ddx; + ddx += dddx; + Y += dy; + dy += ddy; + ddy += dddy; + } + Unlock(); } /*! @@ -397,6 +1599,73 @@ void DisplayDriver::StrokeBezier(BPoint *pts, LayerData *d, const Pattern &pat) */ void DisplayDriver::StrokeEllipse(BRect r, LayerData *d, const Pattern &pat) { + 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 thick; + + Lock(); + thick = (int)d->pensize; + PatternHandler pattern(pat); + pattern.SetColors(d->highcolor, d->lowcolor); + + /* SetThickPixel does bounds checking, so we don't have to worry about it */ + + SetThickPixel(ROUND(xc+x),ROUND(yc-y),thick,&pattern); + SetThickPixel(ROUND(xc-x),ROUND(yc-y),thick,&pattern); + SetThickPixel(ROUND(xc-x),ROUND(yc+y),thick,&pattern); + SetThickPixel(ROUND(xc+x),ROUND(yc+y),thick,&pattern); + + 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; + } + + SetThickPixel(ROUND(xc+x),ROUND(yc-y),thick,&pattern); + SetThickPixel(ROUND(xc-x),ROUND(yc-y),thick,&pattern); + SetThickPixel(ROUND(xc-x),ROUND(yc+y),thick,&pattern); + SetThickPixel(ROUND(xc+x),ROUND(yc+y),thick,&pattern); + } + + 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; + } + + SetThickPixel(ROUND(xc+x),ROUND(yc-y),thick,&pattern); + SetThickPixel(ROUND(xc-x),ROUND(yc-y),thick,&pattern); + SetThickPixel(ROUND(xc-x),ROUND(yc+y),thick,&pattern); + SetThickPixel(ROUND(xc+x),ROUND(yc+y),thick,&pattern); + } + Unlock(); } /*! @@ -411,6 +1680,39 @@ void DisplayDriver::StrokeEllipse(BRect r, LayerData *d, const Pattern &pat) */ void DisplayDriver::StrokeLine(BPoint start, BPoint end, LayerData *d, const Pattern &pat) { + int x1 = ROUND(start.x); + int y1 = ROUND(start.y); + int x2 = ROUND(end.x); + int y2 = ROUND(end.y); + int dx = x2 - x1; + int dy = y2 - y1; + int steps, k; + double xInc, yInc; + double x = x1; + double y = y1; + int thick; + + Lock(); + thick = (int)d->pensize; + PatternHandler pattern(pat); + pattern.SetColors(d->highcolor, d->lowcolor); + + if ( abs(dx) > abs(dy) ) + steps = abs(dx); + else + steps = abs(dy); + xInc = dx / (double) steps; + yInc = dy / (double) steps; + + /* SetThickPixel does bounds checking, so we don't have to worry about it */ + SetThickPixel(ROUND(x),ROUND(y),thick,&pattern); + for (k=0; kpensize; + PatternHandler pattern(pat); + pattern.SetColors(d->highcolor, d->lowcolor); + + HLineThick(ROUND(r.left), ROUND(r.right), ROUND(r.top), thick, &pattern); + StrokeLine(r.RightTop(), r.RightBottom(), d, pat); + HLineThick(ROUND(r.right), ROUND(r.left), ROUND(r.bottom), thick, &pattern); + StrokeLine(r.LeftTop(), r.LeftBottom(), d, pat); + Unlock(); } /*! @@ -472,6 +1791,34 @@ void DisplayDriver::StrokeRegion(BRegion *r, LayerData *d, const Pattern &pat) */ void DisplayDriver::StrokeRoundRect(BRect r, float xrad, float yrad, LayerData *d, const Pattern &pat) { + float hLeft, hRight; + float vTop, vBottom; + float bLeft, bRight, bTop, bBottom; + Lock(); + int thick = (int)d->pensize; + PatternHandler pattern(pat); + pattern.SetColors(d->highcolor, d->lowcolor); + + hLeft = r.left + xrad; + hRight = r.right - xrad; + vTop = r.top + yrad; + vBottom = r.bottom - yrad; + bLeft = hLeft + xrad; + bRight = hRight -xrad; + bTop = vTop + yrad; + bBottom = vBottom - yrad; + StrokeArc(BRect(bRight, r.top, r.right, bTop), 0, 90, d, pat); + HLineThick(ROUND(hRight), ROUND(hLeft), ROUND(r.top), thick, &pattern); + + StrokeArc(BRect(r.left,r.top,bLeft,bTop), 90, 90, d, pat); + StrokeLine(BPoint(r.left,vTop),BPoint(r.left,vBottom),d,pat); + + StrokeArc(BRect(r.left,bBottom,bLeft,r.bottom), 180, 90, d, pat); + HLineThick(ROUND(hLeft), ROUND(hRight), ROUND(r.bottom), thick, &pattern); + + StrokeArc(BRect(bRight,bBottom,r.right,r.bottom), 270, 90, d, pat); + StrokeLine(BPoint(r.right,vBottom),BPoint(r.right,vTop),d,pat); + Unlock(); } //void DisplayDriver::StrokeShape(SShape *sh, LayerData *d, const Pattern &pat) @@ -491,6 +1838,12 @@ void DisplayDriver::StrokeRoundRect(BRect r, float xrad, float yrad, LayerData * */ void DisplayDriver::StrokeTriangle(BPoint *pts, BRect r, LayerData *d, const Pattern &pat) { + /* Bounds checking is handled by StrokeLine and the functions it calls */ + Lock(); + StrokeLine(pts[0],pts[1],d,pat); + StrokeLine(pts[1],pts[2],d,pat); + StrokeLine(pts[2],pts[0],d,pat); + Unlock(); } /*! @@ -850,3 +2203,50 @@ ServerCursor *DisplayDriver::_GetCursor(void) return _cursor; } +/*! + \brief Draws a pixel in the specified color + \param x The x coordinate (guaranteed to be in bounds) + \param y The y coordinate (guaranteed to be in bounds) + \param col The color to draw + Must be implemented in subclasses +*/ +void DisplayDriver::SetPixel(int x, int y, RGBColor col) +{ +} + +/*! + \brief Draws a point of a specified thickness + \param x The x coordinate (not guaranteed to be in bounds) + \param y The y coordinate (not guaranteed to be in bounds) + \param thick The thickness of the point + \param pat The PatternHandler which detemines pixel colors + Must be implemented in subclasses +*/ +void DisplayDriver::SetThickPixel(int x, int y, int thick, PatternHandler *pat) +{ +} + +/*! + \brief Draws a horizontal line + \param x1 The first x coordinate (guaranteed to be in bounds) + \param x2 The second x coordinate (guaranteed to be in bounds) + \param y The y coordinate (guaranteed to be in bounds) + \param pat The PatternHandler which detemines pixel colors + Must be implemented in subclasses +*/ +void DisplayDriver::HLine(int32 x1, int32 x2, int32 y, PatternHandler *pat) +{ +} + +/*! + \brief Draws a horizontal line + \param x1 The first x coordinate (not guaranteed to be in bounds) + \param x2 The second x coordinate (not guaranteed to be in bounds) + \param y The y coordinate (not guaranteed to be in bounds) + \param thick The thickness of the line + \param pat The PatternHandler which detemines pixel colors + Must be implemented in subclasses +*/ +void DisplayDriver::HLineThick(int32 x1, int32 x2, int32 y, int32 thick, PatternHandler *pat) +{ +} diff --git a/src/servers/app/server/RGBColor.cpp b/src/servers/app/server/RGBColor.cpp index 5d3d0ca573..1c3fff033c 100644 --- a/src/servers/app/server/RGBColor.cpp +++ b/src/servers/app/server/RGBColor.cpp @@ -121,9 +121,24 @@ uint8 RGBColor::GetColor8(void) return color8; } +/*! + \brief Returns the color as the closest 15-bit color + \return 15-bit value of the current color plus 1-bit alpha +*/ +uint16 RGBColor::GetColor15(void) +{ + if(update15) + { + color15=FindClosestColor15(color32); + update15=false; + } + + return color15; +} + /*! \brief Returns the color as the closest 16-bit color - \return 16-bit value of the current color, including alpha + \return 16-bit value of the current color */ uint16 RGBColor::GetColor16(void) {