More drawing fuctions, and start adding bounds checking

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2645 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
shadow303 2003-02-07 01:03:39 +00:00
parent 26dd5fd531
commit 79e622060c
2 changed files with 697 additions and 36 deletions

View File

@ -26,6 +26,8 @@
//
//------------------------------------------------------------------------------
#include "AccelerantDriver.h"
#include "Angle.h"
#include "FontFamily.h"
#include "ServerCursor.h"
#include "ServerBitmap.h"
#include "LayerData.h"
@ -36,13 +38,53 @@
#define RUN_UNDER_R5
#define CLIP_X(a) ( (a < 0) ? 0 : ((a > mDisplayMode.virtual_width-1) ? \
mDisplayMode.virtual_width-1 : a) )
#define CLIP_Y(a) ( (a < 0) ? 0 : ((a > mDisplayMode.virtual_height-1) ? \
mDisplayMode.virtual_height-1 : a) )
#define CHECK_X(a) ( (a >= 0) || (a <= mDisplayMode.virtual_width-1) )
#define CHECK_Y(a) ( (a >= 0) || (a <= mDisplayMode.virtual_height-1) )
/* Stuff to investigate:
Effect of pensize on fill operations
Pattern details - start point, rectangles drawn counter-clockwise?
Maybe the pattern is always relative to (0,0)
Do I need to deal with things that may be clipped entirely?
*/
/* Need to check which functions should move the pen position */
class AccLineCalc
{
public:
AccLineCalc(const BPoint &pta, const BPoint &ptb);
float GetX(float y);
float GetY(float x);
float Slope(void) { return slope; }
float Offset(void) { return offset; }
private:
float slope;
float offset;
BPoint start, end;
};
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);
}
float AccLineCalc::GetX(float y)
{
return ( (y-offset)/slope );
}
float AccLineCalc::GetY(float x)
{
return ( (slope * x) + offset );
}
/*!
\brief Sets up internal variables needed by AccelerantDriver
@ -236,6 +278,150 @@ void AccelerantDriver::DrawBitmap(ServerBitmap *bmp, BRect src, BRect dest, Laye
*/
void AccelerantDriver::DrawString(const char *string, int32 length, BPoint pt, LayerData *d, escapement_delta *delta=NULL)
{
#if 0
if(!string || !d || !d->font)
return;
_Lock();
pt.y--; // because of Be's backward compatibility hack
ServerFont *font=d->font;
FontStyle *style=font->Style();
if(!style)
{
_Unlock();
return;
}
FT_Face face;
FT_GlyphSlot slot;
FT_Matrix rmatrix,smatrix;
FT_UInt glyph_index, previous=0;
FT_Vector pen,delta,space,nonspace;
int16 error=0;
int32 strlength,i;
Angle rotation(font->Rotation()), shear(font->Shear());
bool antialias=( (font->Size()<18 && font->Flags()& B_DISABLE_ANTIALIASING==0)
|| font->Flags()& B_FORCE_ANTIALIASING)?true:false;
// Originally, I thought to do this shear checking here, but it really should be
// done in BFont::SetShear()
float shearangle=shear.Value();
if(shearangle>135)
shearangle=135;
if(shearangle<45)
shearangle=45;
if(shearangle>90)
shear=90+((180-shearangle)*2);
else
shear=90-(90-shearangle)*2;
error=FT_New_Face(ftlib, style->GetPath(), 0, &face);
if(error)
{
printf("Couldn't create face object\n");
_Unlock();
return;
}
slot=face->glyph;
bool use_kerning=FT_HAS_KERNING(face) && font->Spacing()==B_STRING_SPACING;
error=FT_Set_Char_Size(face, 0,int32(font->Size())*64,72,72);
if(error)
{
_Unlock();
return;
}
// if we do any transformation, we do a call to FT_Set_Transform() here
// First, rotate
rmatrix.xx = (FT_Fixed)( rotation.Cosine()*0x10000);
rmatrix.xy = (FT_Fixed)( rotation.Sine()*0x10000);
rmatrix.yx = (FT_Fixed)(-rotation.Sine()*0x10000);
rmatrix.yy = (FT_Fixed)( rotation.Cosine()*0x10000);
// Next, shear
smatrix.xx = (FT_Fixed)(0x10000);
smatrix.xy = (FT_Fixed)(-shear.Cosine()*0x10000);
smatrix.yx = (FT_Fixed)(0);
smatrix.yy = (FT_Fixed)(0x10000);
//FT_Matrix_Multiply(&rmatrix,&smatrix);
FT_Matrix_Multiply(&smatrix,&rmatrix);
// Set up the increment value for escapement padding
space.x=int32(d->edelta.space * rotation.Cosine()*64);
space.y=int32(d->edelta.space * rotation.Sine()*64);
nonspace.x=int32(d->edelta.nonspace * rotation.Cosine()*64);
nonspace.y=int32(d->edelta.nonspace * rotation.Sine()*64);
// set the pen position in 26.6 cartesian space coordinates
pen.x=(int32)pt.x * 64;
pen.y=(int32)pt.y * 64;
slot=face->glyph;
strlength=strlen(string);
if(length<strlength)
strlength=length;
for(i=0;i<strlength;i++)
{
//FT_Set_Transform(face,&smatrix,&pen);
FT_Set_Transform(face,&rmatrix,&pen);
// Handle escapement padding option
if((uint8)string[i]<=0x20)
{
pen.x+=space.x;
pen.y+=space.y;
}
else
{
pen.x+=nonspace.x;
pen.y+=nonspace.y;
}
// get kerning and move pen
if(use_kerning && previous && glyph_index)
{
FT_Get_Kerning(face, previous, glyph_index,ft_kerning_default, &delta);
pen.x+=delta.x;
pen.y+=delta.y;
}
error=FT_Load_Char(face,string[i],
((antialias)?FT_LOAD_RENDER:FT_LOAD_RENDER | FT_LOAD_MONOCHROME) );
if(!error)
{
if(antialias)
BlitGray2RGB32(&slot->bitmap,
BPoint(slot->bitmap_left,pt.y-(slot->bitmap_top-pt.y)), d);
else
BlitMono2RGB32(&slot->bitmap,
BPoint(slot->bitmap_left,pt.y-(slot->bitmap_top-pt.y)), d);
}
else
printf("Couldn't load character %c\n", string[i]);
// increment pen position
pen.x+=slot->advance.x;
pen.y+=slot->advance.y;
previous=glyph_index;
}
FT_Done_Face(face);
_Unlock();
#endif
}
/*!
@ -251,6 +437,169 @@ void AccelerantDriver::DrawString(const char *string, int32 length, BPoint pt, L
*/
void AccelerantDriver::FillArc(BRect r, float angle, float span, LayerData *d, int8 *pat)
{
/* Need to add bounds checking code */
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;
// Watch out for bozos giving us whacko spans
if ( (span >= 360) || (span <= -360) )
{
StrokeEllipse(r,d,pat);
return;
}
_Lock();
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);
}
}
/*
if ( useQuad1 ||
(!shortspan && (((startQuad == 1) && (x <= startx)) || ((endQuad == 1) && (x >= endx)))) ||
(shortspan && (startQuad == 1) && (x <= startx) && (x >= endx)) )
SetThickPixel(xc+x,yc-y,thick,d->highcolor);
if ( useQuad2 ||
(!shortspan && (((startQuad == 2) && (x >= startx)) || ((endQuad == 2) && (x <= endx)))) ||
(shortspan && (startQuad == 2) && (x >= startx) && (x <= endx)) )
SetThickPixel(xc-x,yc-y,thick,d->highcolor);
if ( useQuad3 ||
(!shortspan && (((startQuad == 3) && (x <= startx)) || ((endQuad == 3) && (x >= endx)))) ||
(shortspan && (startQuad == 3) && (x <= startx) && (x >= endx)) )
SetThickPixel(xc-x,yc+y,thick,d->highcolor);
if ( useQuad4 ||
(!shortspan && (((startQuad == 4) && (x >= startx)) || ((endQuad == 4) && (x <= endx)))) ||
(shortspan && (startQuad == 4) && (x >= startx) && (x <= endx)) )
SetThickPixel(xc+x,yc+y,thick,d->highcolor);
*/
if ( useQuad1 ||
(!shortspan && (((startQuad == 1) && (x <= startx)) || ((endQuad == 1) && (x >= endx)))) )
{
if ( useQuad2 ||
(!shortspan && (((startQuad == 2) && (x >= startx)) || ((endQuad == 2) && (x <= endx)))) )
{
HLine(xc-x, xc+x, yc-y, 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 ||
(!shortspan && (((startQuad == 1) && (x <= startx)) || ((endQuad == 1) && (x >= endx)))) ||
(shortspan && (startQuad == 1) && (x <= startx) && (x >= endx)) )
SetThickPixel(xc+x,yc-y,thick,d->highcolor);
if ( useQuad2 ||
(!shortspan && (((startQuad == 2) && (x >= startx)) || ((endQuad == 2) && (x <= endx)))) ||
(shortspan && (startQuad == 2) && (x >= startx) && (x <= endx)) )
SetThickPixel(xc-x,yc-y,thick,d->highcolor);
if ( useQuad3 ||
(!shortspan && (((startQuad == 3) && (x <= startx)) || ((endQuad == 3) && (x >= endx)))) ||
(shortspan && (startQuad == 3) && (x <= startx) && (x >= endx)) )
SetThickPixel(xc-x,yc+y,thick,d->highcolor);
if ( useQuad4 ||
(!shortspan && (((startQuad == 4) && (x >= startx)) || ((endQuad == 4) && (x <= endx)))) ||
(shortspan && (startQuad == 4) && (x >= startx) && (x <= endx)) )
SetThickPixel(xc+x,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(xc+x,yc-y,thick,d->highcolor);
if ( useQuad2 ||
(!shortspan && (((startQuad == 2) && (x >= startx)) || ((endQuad == 2) && (x <= endx)))) ||
(shortspan && (startQuad == 2) && (x >= startx) && (x <= endx)) )
SetThickPixel(xc-x,yc-y,thick,d->highcolor);
if ( useQuad3 ||
(!shortspan && (((startQuad == 3) && (x <= startx)) || ((endQuad == 3) && (x >= endx)))) ||
(shortspan && (startQuad == 3) && (x <= startx) && (x >= endx)) )
SetThickPixel(xc-x,yc+y,thick,d->highcolor);
if ( useQuad4 ||
(!shortspan && (((startQuad == 4) && (x >= startx)) || ((endQuad == 4) && (x <= endx)))) ||
(shortspan && (startQuad == 4) && (x >= startx) && (x <= endx)) )
SetThickPixel(xc+x,yc+y,thick,d->highcolor);
}
_Unlock();
}
/*!
@ -349,14 +698,26 @@ void AccelerantDriver::FillEllipse(BRect r, LayerData *d, int8 *pat)
_Lock();
if ( (r.bottom < 0) || (r.top > mDisplayMode.virtual_height-1) ||
(r.right < 0) || (r.left > mDisplayMode.virtual_width-1) )
{
_Unlock();
return;
}
/*
SetThickPixel(xc+x,yc-y,thick,d->highcolor);
SetThickPixel(xc-x,yc-y,thick,d->highcolor);
SetThickPixel(xc-x,yc+y,thick,d->highcolor);
SetThickPixel(xc+x,yc+y,thick,d->highcolor);
*/
SetPixel(xc,yc-y,d->highcolor);
SetPixel(xc,yc+y,d->highcolor);
if ( CHECK_X(xc) )
{
if ( CHECK_Y(yc-y) )
SetPixel(xc,yc-y,d->highcolor);
if ( CHECK_Y(yc+y) )
SetPixel(xc,yc+y,d->highcolor);
}
p = ROUND (Ry2 - (Rx2 * ry) + (.25 * Rx2));
while (px < py)
@ -378,8 +739,13 @@ void AccelerantDriver::FillEllipse(BRect r, LayerData *d, int8 *pat)
SetThickPixel(xc-x,yc+y,thick,d->highcolor);
SetThickPixel(xc+x,yc+y,thick,d->highcolor);
*/
HLine(xc-x,xc+x,yc-y,d->highcolor);
HLine(xc-x,xc+x,yc+y,d->highcolor);
if ( CHECK_X(xc-x) || CHECK_X(xc+x) )
{
if ( CHECK_Y(yc-y) )
HLine(CLIP_X(xc-x),CLIP_X(xc+x),yc-y,d,pat);
if ( CHECK_Y(yc+y) )
HLine(CLIP_X(xc-x),CLIP_X(xc+x),yc+y,d,pat);
}
}
p = ROUND(Ry2*(x+.5)*(x+.5) + Rx2*(y-1)*(y-1) - Rx2*Ry2);
@ -402,8 +768,13 @@ void AccelerantDriver::FillEllipse(BRect r, LayerData *d, int8 *pat)
SetThickPixel(xc-x,yc+y,thick,d->highcolor);
SetThickPixel(xc+x,yc+y,thick,d->highcolor);
*/
HLine(xc-x,xc+x,yc-y,d->highcolor);
HLine(xc-x,xc+x,yc+y,d->highcolor);
if ( CHECK_X(xc-x) || CHECK_X(xc+x) )
{
if ( CHECK_Y(yc-y) )
HLine(CLIP_X(xc-x),CLIP_X(xc+x),yc-y,d,pat);
if ( CHECK_Y(yc+y) )
HLine(CLIP_X(xc-x),CLIP_X(xc+x),yc+y,d,pat);
}
}
_Unlock();
}
@ -421,6 +792,10 @@ void AccelerantDriver::FillEllipse(BRect r, LayerData *d, int8 *pat)
*/
void AccelerantDriver::FillPolygon(BPoint *ptlist, int32 numpts, BRect rect, LayerData *d, int8 *pat)
{
/* The current plan is to transform the polygon into trianles and rectangles, and
use the apporiate commands to draw each part. Maybe I'll come up with something
better later.
*/
}
/*!
@ -439,7 +814,22 @@ void AccelerantDriver::FillRect(BRect r, LayerData *d, int8 *pat)
switch (mDisplayMode.space)
{
case B_CMAP8:
case B_GRAY8:
{
uint8 *fb = (uint8 *)mFrameBufferConfig.frame_buffer + (int)r.top*mFrameBufferConfig.bytes_per_row;
int x,y;
uint8 drawcolor = d->highcolor.GetColor8();
for (y=(int)r.top; y<=(int)r.bottom; y++)
{
/* If there is no pattern, we could replace this
loop with a memset.
*/
for (x=(int)r.left; x<=r.right; x++)
{
fb[x] = drawcolor;
}
fb += mFrameBufferConfig.bytes_per_row;
}
} break;
case B_RGB16_BIG:
case B_RGB16_LITTLE:
@ -448,6 +838,17 @@ void AccelerantDriver::FillRect(BRect r, LayerData *d, int8 *pat)
case B_RGB15_LITTLE:
case B_RGBA15_LITTLE:
{
uint16 *fb = (uint16 *)((uint8 *)mFrameBufferConfig.frame_buffer + (int)r.top*mFrameBufferConfig.bytes_per_row);
int x,y;
uint16 drawcolor = d->highcolor.GetColor16();
for (y=(int)r.top; y<=(int)r.bottom; y++)
{
for (x=(int)r.left; x<=r.right; x++)
{
fb[x] = drawcolor;
}
fb = (uint16 *)((uint8 *)fb + mFrameBufferConfig.bytes_per_row);
}
} break;
case B_RGB32_BIG:
case B_RGBA32_BIG:
@ -492,16 +893,26 @@ void AccelerantDriver::FillRoundRect(BRect r, float xrad, float yrad, LayerData
int i;
_Lock();
if ( (r.bottom < 0) || (r.top > mDisplayMode.virtual_height-1) ||
(r.right < 0) || (r.left > mDisplayMode.virtual_width-1) )
{
_Unlock();
return;
}
for (i=0; i<ROUND(yrad); i++)
{
arc_x = xrad*sqrt(1-i*i/yrad2);
StrokeLine(BPoint(r.left+xrad-arc_x,r.top+i),
BPoint(r.right-xrad+arc_x,r.top+i), d, pat);
StrokeLine(BPoint(r.left+xrad-arc_x,r.bottom-i),
BPoint(r.right-xrad+arc_x,r.bottom-i), d, pat);
if ( CHECK_Y(r.top+i) )
HLine(CLIP_X(r.left+xrad-arc_x), CLIP_X(r.right-xrad+arc_x),
r.top+i, d, pat);
if ( CHECK_Y(r.bottom-i) )
HLine(CLIP_X(r.left+xrad-arc_x), CLIP_X(r.right-xrad+arc_x),
r.bottom-i, d, pat);
}
FillRect(BRect(r.left,r.top+yrad,r.right,r.bottom-yrad), d, pat);
FillRect(BRect(CLIP_X(r.left),CLIP_Y(r.top+yrad),
CLIP_X(r.right),CLIP_Y(r.bottom-yrad)), d, pat);
_Unlock();
}
@ -523,6 +934,110 @@ void AccelerantDriver::FillRoundRect(BRect r, float xrad, float yrad, LayerData
*/
void AccelerantDriver::FillTriangle(BPoint *pts, BRect r, LayerData *d, int8 *pat)
{
if(!pts || !d || !pat)
return;
_Lock();
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.y<pts[2].y)
{
third=pts[2];
}
else
{
// second is lower than "third", so we must ensure that this third point
// isn't higher than our first point
third=second;
if(first.y<pts[2].y)
second=pts[2];
else
{
second=first;
first=pts[2];
}
}
// Now that the points are sorted, check to see if they all have the same
// y value
if(first.y==second.y && second.y==third.y)
{
BPoint start,end;
start.y=first.y;
end.y=first.y;
start.x=MIN(first.x,MIN(second.x,third.x));
end.x=MAX(first.x,MAX(second.x,third.x));
if ( CHECK_Y(start.y) && (CHECK_X(start.x) || CHECK_X(end.x)) )
HLine(CLIP_X(start.x), CLIP_X(end.x), start.y, d, pat);
_Unlock();
return;
}
int32 i;
// Special case #1: first and second in the same row
if(first.y==second.y)
{
AccLineCalc lineA(first, third);
AccLineCalc lineB(second, third);
if ( CHECK_Y(first.y) && (CHECK_X(first.x) || CHECK_X(second.x)) )
HLine(CLIP_X(first.x), CLIP_X(second.x), first.y, d, pat);
for(i=int32(first.y+1);i<third.y;i++)
if ( CHECK_Y(i) && (CHECK_X(lineA.GetX(i)) || CHECK_X(lineB.GetX(i))) )
HLine(CLIP_X(lineA.GetX(i)), CLIP_X(lineB.GetX(i)), i, d, pat);
_Unlock();
return;
}
// Special case #2: second and third in the same row
if(second.y==third.y)
{
AccLineCalc lineA(first, second);
AccLineCalc lineB(first, third);
if ( CHECK_Y(second.y) && (CHECK_X(second.x) || CHECK_X(third.x)) )
HLine(CLIP_X(second.x), CLIP_X(third.x), second.y, d, pat);
for(i=int32(first.y+1);i<third.y;i++)
if ( CHECK_Y(i) && (CHECK_X(lineA.GetX(i)) || CHECK_X(lineB.GetX(i))) )
HLine(CLIP_X(lineA.GetX(i)), CLIP_X(lineB.GetX(i)), i, d, pat);
_Unlock();
return;
}
// Normal case.
// Calculate the y deltas for the two lines and we set the maximum for the
// first loop to the lesser of the two so that we can change lines.
int32 dy1=int32(second.y-first.y),
dy2=int32(third.y-first.y),
max;
max=int32(first.y+MIN(dy1,dy2));
AccLineCalc lineA(first, second);
AccLineCalc lineB(first, third);
AccLineCalc lineC(second, third);
for(i=int32(first.y+1);i<max;i++)
if ( CHECK_Y(i) && (CHECK_X(lineA.GetX(i)) || CHECK_X(lineB.GetX(i))) )
HLine(CLIP_X(lineA.GetX(i)), CLIP_X(lineB.GetX(i)), i, d, pat);
for(i=max; i<third.y; i++)
if ( CHECK_Y(i) && (CHECK_X(lineC.GetX(i)) || CHECK_X(lineB.GetX(i))) )
HLine(CLIP_X(lineC.GetX(i)), CLIP_X(lineB.GetX(i)), i, d, pat);
_Unlock();
}
/*!
@ -621,6 +1136,7 @@ void AccelerantDriver::InvertRect(BRect r)
printf("ScreenDriver::15-bit mode unimplemented\n");
break;
case B_CMAP8:
case B_GRAY8:
// TODO: Implement
printf("ScreenDriver::8-bit mode unimplemented\n");
break;
@ -1083,13 +1599,12 @@ void AccelerantDriver::StrokePolygon(BPoint *ptlist, int32 numpts, BRect rect, L
*/
void AccelerantDriver::StrokeRect(BRect r, LayerData *d, int8 *pat)
{
/* Optimize later with HLine and VLine calls, once they support patterns */
/* Maybe this should be drawn counterclockwise ? */
_Lock();
StrokeLine(r.LeftTop(),r.RightTop(),d,pat);
StrokeLine(r.RightTop(),r.RightBottom(),d,pat);
StrokeLine(r.RightBottom(),r.LeftBottom(),d,pat);
StrokeLine(r.LeftTop(),r.LeftBottom(),d,pat);
HLine(r.left, r.right, r.top, d, pat);
StrokeLine(r.RightTop(), r.RightBottom(), d, pat);
HLine(r.right, r.left, r.bottom, d, pat);
StrokeLine(r.LeftTop(), r.LeftBottom(), d, pat);
_Unlock();
}
@ -1122,14 +1637,14 @@ void AccelerantDriver::StrokeRoundRect(BRect r, float xrad, float yrad, LayerDat
bRight = hRight -xrad;
bTop = vTop + yrad;
bBottom = vBottom - yrad;
StrokeArc(BRect(bRight,r.top,r.right,bTop), 0, 90, d, pat);
StrokeLine(BPoint(hRight,r.top),BPoint(hLeft,r.top),d,pat);
StrokeArc(BRect(bRight, r.top, r.right, bTop), 0, 90, d, pat);
HLine(hRight, hLeft, r.top, d, pat);
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);
StrokeLine(BPoint(hLeft,r.bottom),BPoint(hRight,r.bottom),d,pat);
HLine(hLeft, 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);
@ -1242,7 +1757,75 @@ bool AccelerantDriver::DumpToFile(const char *path)
*/
float AccelerantDriver::StringWidth(const char *string, int32 length, LayerData *d)
{
return 0.0;
if(!string || !d || !d->font)
return 0.0;
_Lock();
ServerFont *font=d->font;
FontStyle *style=font->Style();
if(!style)
{
_Unlock();
return 0.0;
}
FT_Face face;
FT_GlyphSlot slot;
FT_UInt glyph_index, previous=0;
FT_Vector pen,delta;
int16 error=0;
int32 strlength,i;
float returnval;
error=FT_New_Face(ftlib, style->GetPath(), 0, &face);
if(error)
{
_Unlock();
return 0.0;
}
slot=face->glyph;
bool use_kerning=FT_HAS_KERNING(face) && font->Spacing()==B_STRING_SPACING;
error=FT_Set_Char_Size(face, 0,int32(font->Size())*64,72,72);
if(error)
{
_Unlock();
return 0.0;
}
// set the pen position in 26.6 cartesian space coordinates
pen.x=0;
slot=face->glyph;
strlength=strlen(string);
if(length<strlength)
strlength=length;
for(i=0;i<strlength;i++)
{
// get kerning and move pen
if(use_kerning && previous && glyph_index)
{
FT_Get_Kerning(face, previous, glyph_index,ft_kerning_default, &delta);
pen.x+=delta.x;
}
error=FT_Load_Char(face,string[i],FT_LOAD_MONOCHROME);
// increment pen position
pen.x+=slot->advance.x;
previous=glyph_index;
}
FT_Done_Face(face);
returnval=pen.x>>6;
_Unlock();
return returnval;
}
/*!
@ -1259,7 +1842,62 @@ float AccelerantDriver::StringWidth(const char *string, int32 length, LayerData
*/
float AccelerantDriver::StringHeight(const char *string, int32 length, LayerData *d)
{
return 0.0;
if(!string || !d || !d->font)
return 0.0;
_Lock();
ServerFont *font=d->font;
FontStyle *style=font->Style();
if(!style)
{
_Unlock();
return 0.0;
}
FT_Face face;
FT_GlyphSlot slot;
int16 error=0;
int32 strlength,i;
float returnval=0.0,ascent=0.0,descent=0.0;
error=FT_New_Face(ftlib, style->GetPath(), 0, &face);
if(error)
{
_Unlock();
return 0.0;
}
slot=face->glyph;
error=FT_Set_Char_Size(face, 0,int32(font->Size())*64,72,72);
if(error)
{
_Unlock();
return 0.0;
}
slot=face->glyph;
strlength=strlen(string);
if(length<strlength)
strlength=length;
for(i=0;i<strlength;i++)
{
FT_Load_Char(face,string[i],FT_LOAD_RENDER);
if(slot->metrics.horiBearingY<slot->metrics.height)
descent=MAX((slot->metrics.height-slot->metrics.horiBearingY)>>6,descent);
else
ascent=MAX(slot->bitmap.rows,ascent);
}
_Unlock();
FT_Done_Face(face);
returnval=ascent+descent;
_Unlock();
return returnval;
}
/*!
@ -1342,7 +1980,10 @@ void AccelerantDriver::SetPixel(int x, int y, RGBColor col)
switch (mDisplayMode.space)
{
case B_CMAP8:
case B_GRAY8:
{
uint8 *fb = (uint8 *)mFrameBufferConfig.frame_buffer + y*mFrameBufferConfig.bytes_per_row;
fb[x] = col.GetColor8();
} break;
case B_RGB16_BIG:
case B_RGB16_LITTLE:
@ -1351,6 +1992,8 @@ void AccelerantDriver::SetPixel(int x, int y, RGBColor col)
case B_RGB15_LITTLE:
case B_RGBA15_LITTLE:
{
uint16 *fb = (uint16 *)((uint8 *)mFrameBufferConfig.frame_buffer + y*mFrameBufferConfig.bytes_per_row);
fb[x] = col.GetColor16();
} break;
case B_RGB32_BIG:
case B_RGBA32_BIG:
@ -1372,7 +2015,22 @@ void AccelerantDriver::SetThickPixel(int x, int y, int thick, RGBColor col)
switch (mDisplayMode.space)
{
case B_CMAP8:
case B_GRAY8:
{
int i,j;
uint8 *fb = (uint8 *)mFrameBufferConfig.frame_buffer + (y-thick/2)*mFrameBufferConfig.bytes_per_row + x-thick/2;
uint8 drawcolor = col.GetColor8();
for (i=0; i<thick; i++)
{
/* If there is no pattern, we could replace this
loop with a memset.
*/
for (j=0; j<thick; j++)
{
fb[j] = drawcolor;
}
fb += mFrameBufferConfig.bytes_per_row;
}
} break;
case B_RGB16_BIG:
case B_RGB16_LITTLE:
@ -1381,6 +2039,17 @@ void AccelerantDriver::SetThickPixel(int x, int y, int thick, RGBColor col)
case B_RGB15_LITTLE:
case B_RGBA15_LITTLE:
{
int i,j;
uint16 *fb = (uint16 *)((uint8 *)mFrameBufferConfig.frame_buffer + (y-thick/2)*mFrameBufferConfig.bytes_per_row) + x-thick/2;
uint16 drawcolor = col.GetColor16();
for (i=0; i<thick; i++)
{
for (j=0; j<thick; j++)
{
fb[j] = drawcolor;
}
fb = (uint16 *)((uint8 *)fb + mFrameBufferConfig.bytes_per_row);
}
} break;
case B_RGB32_BIG:
case B_RGBA32_BIG:
@ -1405,12 +2074,12 @@ void AccelerantDriver::SetThickPixel(int x, int y, int thick, RGBColor col)
}
}
/* Need to replace this with one that takes patterns */
void AccelerantDriver::HLine(int32 x1, int32 x2, int32 y, RGBColor col)
void AccelerantDriver::HLine(int32 x1, int32 x2, int32 y, LayerData *d, int8 *pat)
{
switch (mDisplayMode.space)
{
case B_CMAP8:
case B_GRAY8:
{
} break;
case B_RGB16_BIG:
@ -1427,7 +2096,7 @@ void AccelerantDriver::HLine(int32 x1, int32 x2, int32 y, RGBColor col)
case B_RGBA32_LITTLE:
{
uint32 *fb = (uint32 *)((uint8 *)mFrameBufferConfig.frame_buffer + y*mFrameBufferConfig.bytes_per_row);
rgb_color color = col.GetColor32();
rgb_color color = d->highcolor.GetColor32();
uint32 drawcolor = (color.alpha << 24) | (color.red << 16) | (color.green << 8) | (color.blue);
int x;
if ( x1 > x2 )
@ -1450,10 +2119,8 @@ void AccelerantDriver::BlitBitmap(ServerBitmap *sourcebmp, BRect sourcerect, BRe
if(!sourcebmp)
return;
/* Need to fix this
if(sourcebmp->BitsPerPixel() != fbuffer->gcinfo.bits_per_pixel)
if(sourcebmp->BitsPerPixel() != GetDepthFromColorspace(mDisplayMode.space))
return;
*/
uint8 colorspace_size=sourcebmp->BitsPerPixel()/8;
// First, clip source rect to destination
@ -1574,10 +2241,8 @@ void AccelerantDriver::ExtractToBitmap(ServerBitmap *destbmp, BRect destrect, BR
if(!destbmp)
return;
/* Need to fix this
if(destbmp->BitsPerPixel() != fbuffer->gcinfo.bits_per_pixel)
if(destbmp->BitsPerPixel() != GetDepthFromColorspace(mDisplayMode.space))
return;
*/
uint8 colorspace_size=destbmp->BitsPerPixel()/8;
// First, clip source rect to destination
@ -1662,11 +2327,7 @@ int AccelerantDriver::OpenGraphicsDevice(int deviceNumber)
char path[PATH_MAX];
DIR *directory;
struct dirent *entry;
#if 0
//card_fd = open("/dev/graphics/1002_4755_000400",B_READ_WRITE);
card_fd = open("/dev/graphics/nv10_010000",B_READ_WRITE);
//card_fd = open("/dev/graphics/stub",B_READ_WRITE);
#endif
directory = opendir("/dev/graphics");
if ( !directory )
return -1;

View File

@ -115,7 +115,7 @@ protected:
void ExtractToBitmap(ServerBitmap *destbmp, BRect destrect, BRect sourcerect);
void SetPixelPattern(int x, int y, uint8 *pattern, uint8 patternindex);
void Line(BPoint start, BPoint end, LayerData *d, int8 *pat);
void HLine(int32 x1, int32 x2, int32 y, RGBColor col);
void HLine(int32 x1, int32 x2, int32 y, LayerData *d, int8 *pat);
rgb_color GetBlitColor(rgb_color src, rgb_color dest, LayerData *d, bool use_high=true);
void SetPixel(int x, int y, RGBColor col);
void SetPixel32(int x, int y, rgb_color col);