* cleanup, removed use of pointers and allocations

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21650 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus
2007-07-18 17:02:44 +00:00
parent 6369b909b2
commit eb9f93f347
2 changed files with 255 additions and 410 deletions
+245 -376
View File
@@ -46,38 +46,20 @@
#include "Painter.h" #include "Painter.h"
#if ALIASED_DRAWING
// in this case, we _cannot_ use the outline rasterizer.
# define USE_OUTLINE_RASTERIZER 0
#else
// in this case, we can optionally use the outline rasterizer (faster).
// NOTE: The outline rasterizer is different from the "general purpose"
// rasterizer and can speed up the stroking of lines. It has some problems
// though, for example the butts of the lines are not anti-aliased. So we
// use the much more powerfull general purpose rasterizer, and live with the
// performance hit for now. See _StrokePath().
// NOTE: The outline rasterizer will still be used for lines with 1 pixel width!
# define USE_OUTLINE_RASTERIZER 0
#endif
#define CHECK_CLIPPING if (!fValidClipping) return BRect(0, 0, -1, -1); #define CHECK_CLIPPING if (!fValidClipping) return BRect(0, 0, -1, -1);
// constructor // constructor
Painter::Painter() Painter::Painter()
: fBuffer(NULL), : fBuffer(),
fPixelFormat(NULL), fPixelFormat(fBuffer, &fPatternHandler),
fBaseRenderer(NULL), fBaseRenderer(fPixelFormat),
fOutlineRenderer(NULL), fUnpackedScanline(),
fOutlineRasterizer(NULL), fPackedScanline(),
fUnpackedScanline(NULL), fRasterizer(),
fPackedScanline(NULL), fRenderer(fBaseRenderer),
fRasterizer(NULL), fRendererBin(fBaseRenderer),
fRenderer(NULL),
fRendererBin(NULL),
fLineProfile(),
fPath(), fPath(),
fCurve(fPath), fCurve(fPath),
@@ -95,26 +77,25 @@ Painter::Painter()
fLineJoinMode(B_MITER_JOIN), fLineJoinMode(B_MITER_JOIN),
fMiterLimit(B_DEFAULT_MITER_LIMIT), fMiterLimit(B_DEFAULT_MITER_LIMIT),
fPatternHandler(new PatternHandler()), fPatternHandler(),
fTextRenderer(AGGTextRenderer::Default()) fTextRenderer(AGGTextRenderer::Default())
{ {
fPixelFormat.SetDrawingMode(fDrawingMode, fAlphaSrcMode, fAlphaFncMode, false);
// Usually, the drawing engine will lock the font for us when // Usually, the drawing engine will lock the font for us when
// needed - unfortunately, it can't know we need it here // needed - unfortunately, it can't know we need it here
fFont.Lock(); fFont.Lock();
_UpdateFont(); _UpdateFont();
fFont.Unlock(); fFont.Unlock();
#if USE_OUTLINE_RASTERIZER #if ALIASED_DRAWING
_UpdateLineWidth(); fRasterizer.gamma(agg::gamma_threshold(0.5));
#endif #endif
} }
// destructor // destructor
Painter::~Painter() Painter::~Painter()
{ {
_MakeEmpty();
delete fPatternHandler;
} }
// #pragma mark - // #pragma mark -
@@ -126,49 +107,14 @@ Painter::AttachToBuffer(RenderingBuffer* buffer)
if (buffer && buffer->InitCheck() >= B_OK && if (buffer && buffer->InitCheck() >= B_OK &&
// TODO: implement drawing on B_RGB24, B_RGB15, B_RGB16, B_CMAP8 and B_GRAY8 :-[ // TODO: implement drawing on B_RGB24, B_RGB15, B_RGB16, B_CMAP8 and B_GRAY8 :-[
(buffer->ColorSpace() == B_RGBA32 || buffer->ColorSpace() == B_RGB32)) { (buffer->ColorSpace() == B_RGBA32 || buffer->ColorSpace() == B_RGB32)) {
// clean up previous stuff fBuffer.attach((uint8*)buffer->Bits(),
_MakeEmpty(); buffer->Width(), buffer->Height(), buffer->BytesPerRow());
fBuffer = new agg::rendering_buffer();
fBuffer->attach((uint8*)buffer->Bits(),
buffer->Width(),
buffer->Height(),
buffer->BytesPerRow());
fPixelFormat = new pixfmt(*fBuffer, fPatternHandler);
fPixelFormat->SetDrawingMode(fDrawingMode, fAlphaSrcMode, fAlphaFncMode, false);
fBaseRenderer = new renderer_base(*fPixelFormat);
// These are the AGG renderes and rasterizes which // These are the AGG renderes and rasterizes which
// will be used for stroking paths // will be used for stroking paths
#if USE_OUTLINE_RASTERIZER
#if ALIASED_DRAWING
fOutlineRenderer = new outline_renderer_type(*fBaseRenderer);
fOutlineRasterizer = new outline_rasterizer_type(*fOutlineRenderer);
#else
fOutlineRenderer = new outline_renderer_type(*fBaseRenderer, fLineProfile);
fOutlineRasterizer = new outline_rasterizer_type(*fOutlineRenderer);
// attach our line profile to the renderer, it keeps a pointer _SetRendererColor(fPatternHandler.HighColor().GetColor32());
fOutlineRenderer->profile(fLineProfile);
#endif // ALIASED_DRAWING
#endif // USE_OUTLINE_RASTERIZER
// the renderer used for filling paths
fRenderer = new renderer_type(*fBaseRenderer);
fRasterizer = new rasterizer_type();
fUnpackedScanline = new scanline_unpacked_type();
fPackedScanline = new scanline_packed_type();
#if ALIASED_DRAWING
fRasterizer->gamma(agg::gamma_threshold(0.5));
#endif
// possibly needed for drawing text (if the font is
// a one bit bitmap font, which is currently not supported yet)
fRendererBin = new renderer_bin_type(*fBaseRenderer);
_SetRendererColor(fPatternHandler->HighColor().GetColor32());
} }
} }
@@ -176,7 +122,6 @@ Painter::AttachToBuffer(RenderingBuffer* buffer)
void void
Painter::DetachFromBuffer() Painter::DetachFromBuffer()
{ {
_MakeEmpty();
} }
// #pragma mark - // #pragma mark -
@@ -203,7 +148,7 @@ Painter::SetDrawState(const DrawState* data, bool updateFont,
// any of these conditions means we need to use a different drawing // any of these conditions means we need to use a different drawing
// mode instance // mode instance
bool updateDrawingMode = !(data->GetPattern() == fPatternHandler->GetPattern()) || bool updateDrawingMode = !(data->GetPattern() == fPatternHandler.GetPattern()) ||
data->GetDrawingMode() != fDrawingMode || data->GetDrawingMode() != fDrawingMode ||
(data->GetDrawingMode() == B_OP_ALPHA && (data->AlphaSrcMode() != fAlphaSrcMode || (data->GetDrawingMode() == B_OP_ALPHA && (data->AlphaSrcMode() != fAlphaSrcMode ||
data->AlphaFncMode() != fAlphaFncMode)); data->AlphaFncMode() != fAlphaFncMode));
@@ -211,8 +156,8 @@ Painter::SetDrawState(const DrawState* data, bool updateFont,
fDrawingMode = data->GetDrawingMode(); fDrawingMode = data->GetDrawingMode();
fAlphaSrcMode = data->AlphaSrcMode(); fAlphaSrcMode = data->AlphaSrcMode();
fAlphaFncMode = data->AlphaFncMode(); fAlphaFncMode = data->AlphaFncMode();
fPatternHandler->SetPattern(data->GetPattern()); fPatternHandler.SetPattern(data->GetPattern());
fPatternHandler->SetOffsets(xOffset, yOffset); fPatternHandler.SetOffsets(xOffset, yOffset);
fLineCapMode = data->LineCapMode(); fLineCapMode = data->LineCapMode();
fLineJoinMode = data->LineJoinMode(); fLineJoinMode = data->LineJoinMode();
fMiterLimit = data->MiterLimit(); fMiterLimit = data->MiterLimit();
@@ -222,7 +167,7 @@ Painter::SetDrawState(const DrawState* data, bool updateFont,
SetHighColor(data->HighColor().GetColor32()); SetHighColor(data->HighColor().GetColor32());
SetLowColor(data->LowColor().GetColor32()); SetLowColor(data->LowColor().GetColor32());
if (updateDrawingMode || fPixelFormat->UsesOpCopyForText()) if (updateDrawingMode || fPixelFormat.UsesOpCopyForText())
_UpdateDrawingMode(); _UpdateDrawingMode();
} }
@@ -233,12 +178,12 @@ void
Painter::ConstrainClipping(const BRegion* region) Painter::ConstrainClipping(const BRegion* region)
{ {
fClippingRegion = region; fClippingRegion = region;
fBaseRenderer->set_clipping_region(const_cast<BRegion*>(region)); fBaseRenderer.set_clipping_region(const_cast<BRegion*>(region));
fValidClipping = region->Frame().IsValid(); fValidClipping = region->Frame().IsValid();
if (fValidClipping) { if (fValidClipping) {
clipping_rect cb = fClippingRegion->FrameInt(); clipping_rect cb = fClippingRegion->FrameInt();
fRasterizer->clip_box(cb.left, cb.top, cb.right + 1, cb.bottom + 1); fRasterizer.clip_box(cb.left, cb.top, cb.right + 1, cb.bottom + 1);
} }
} }
@@ -246,10 +191,10 @@ Painter::ConstrainClipping(const BRegion* region)
void void
Painter::SetHighColor(const rgb_color& color) Painter::SetHighColor(const rgb_color& color)
{ {
if (fPatternHandler->HighColor().GetColor32() == color) if (fPatternHandler.HighColor().GetColor32() == color)
return; return;
fPatternHandler->SetHighColor(color); fPatternHandler.SetHighColor(color);
if (*(fPatternHandler->GetR5Pattern()) == B_SOLID_HIGH) if (*(fPatternHandler.GetR5Pattern()) == B_SOLID_HIGH)
_SetRendererColor(color); _SetRendererColor(color);
} }
@@ -257,8 +202,8 @@ Painter::SetHighColor(const rgb_color& color)
void void
Painter::SetLowColor(const rgb_color& color) Painter::SetLowColor(const rgb_color& color)
{ {
fPatternHandler->SetLowColor(color); fPatternHandler.SetLowColor(color);
if (*(fPatternHandler->GetR5Pattern()) == B_SOLID_LOW) if (*(fPatternHandler.GetR5Pattern()) == B_SOLID_LOW)
_SetRendererColor(color); _SetRendererColor(color);
} }
@@ -278,11 +223,6 @@ Painter::SetPenSize(float size)
{ {
if (fPenSize != size) { if (fPenSize != size) {
fPenSize = size; fPenSize = size;
#if USE_OUTLINE_RASTERIZER
// NOTE: _UpdateLineWidth() updates the line profile which is quite a heavy resource!
// fortunately, we don't need it when using the general purpose rasterizer
_UpdateLineWidth();
#endif
} }
} }
@@ -290,18 +230,18 @@ Painter::SetPenSize(float size)
void void
Painter::SetPattern(const pattern& p, bool drawingText) Painter::SetPattern(const pattern& p, bool drawingText)
{ {
if (!(p == *fPatternHandler->GetR5Pattern()) || drawingText != fDrawingText) { if (!(p == *fPatternHandler.GetR5Pattern()) || drawingText != fDrawingText) {
fPatternHandler->SetPattern(p); fPatternHandler.SetPattern(p);
fDrawingText = drawingText; fDrawingText = drawingText;
_UpdateDrawingMode(fDrawingText); _UpdateDrawingMode(fDrawingText);
// update renderer color if necessary // update renderer color if necessary
if (fPatternHandler->IsSolidHigh()) { if (fPatternHandler.IsSolidHigh()) {
// pattern was not solid high before // pattern was not solid high before
_SetRendererColor(fPatternHandler->HighColor().GetColor32()); _SetRendererColor(fPatternHandler.HighColor().GetColor32());
} else if (fPatternHandler->IsSolidLow()) { } else if (fPatternHandler.IsSolidLow()) {
// pattern was not solid low before // pattern was not solid low before
_SetRendererColor(fPatternHandler->LowColor().GetColor32()); _SetRendererColor(fPatternHandler.LowColor().GetColor32());
} }
} }
} }
@@ -351,12 +291,12 @@ Painter::StrokeLine(BPoint a, BPoint b)
// first, try an optimized version // first, try an optimized version
if (fPenSize == 1.0 && if (fPenSize == 1.0 &&
(fDrawingMode == B_OP_COPY || fDrawingMode == B_OP_OVER)) { (fDrawingMode == B_OP_COPY || fDrawingMode == B_OP_OVER)) {
pattern pat = *fPatternHandler->GetR5Pattern(); pattern pat = *fPatternHandler.GetR5Pattern();
if (pat == B_SOLID_HIGH && if (pat == B_SOLID_HIGH &&
StraightLine(a, b, fPatternHandler->HighColor().GetColor32())) { StraightLine(a, b, fPatternHandler.HighColor().GetColor32())) {
return _Clipped(touched); return _Clipped(touched);
} else if (pat == B_SOLID_LOW && } else if (pat == B_SOLID_LOW &&
StraightLine(a, b, fPatternHandler->LowColor().GetColor32())) { StraightLine(a, b, fPatternHandler.LowColor().GetColor32())) {
return _Clipped(touched); return _Clipped(touched);
} }
} }
@@ -393,64 +333,65 @@ Painter::StrokeLine(BPoint a, BPoint b)
bool bool
Painter::StraightLine(BPoint a, BPoint b, const rgb_color& c) const Painter::StraightLine(BPoint a, BPoint b, const rgb_color& c) const
{ {
if (fBuffer && fValidClipping) { if (!fValidClipping)
if (a.x == b.x) { return false;
// vertical
uint8* dst = fBuffer->row_ptr(0); if (a.x == b.x) {
uint32 bpr = fBuffer->stride(); // vertical
int32 x = (int32)a.x; uint8* dst = fBuffer.row_ptr(0);
dst += x * 4; uint32 bpr = fBuffer.stride();
int32 y1 = (int32)min_c(a.y, b.y); int32 x = (int32)a.x;
int32 y2 = (int32)max_c(a.y, b.y); dst += x * 4;
pixel32 color; int32 y1 = (int32)min_c(a.y, b.y);
color.data8[0] = c.blue; int32 y2 = (int32)max_c(a.y, b.y);
color.data8[1] = c.green; pixel32 color;
color.data8[2] = c.red; color.data8[0] = c.blue;
color.data8[3] = 255; color.data8[1] = c.green;
// draw a line, iterate over clipping boxes color.data8[2] = c.red;
fBaseRenderer->first_clip_box(); color.data8[3] = 255;
do { // draw a line, iterate over clipping boxes
if (fBaseRenderer->xmin() <= x && fBaseRenderer.first_clip_box();
fBaseRenderer->xmax() >= x) { do {
int32 i = max_c(fBaseRenderer->ymin(), y1); if (fBaseRenderer.xmin() <= x &&
int32 end = min_c(fBaseRenderer->ymax(), y2); fBaseRenderer.xmax() >= x) {
uint8* handle = dst + i * bpr; int32 i = max_c(fBaseRenderer.ymin(), y1);
for (; i <= end; i++) { int32 end = min_c(fBaseRenderer.ymax(), y2);
*(uint32*)handle = color.data32; uint8* handle = dst + i * bpr;
handle += bpr; for (; i <= end; i++) {
} *(uint32*)handle = color.data32;
handle += bpr;
} }
} while (fBaseRenderer->next_clip_box()); }
} while (fBaseRenderer.next_clip_box());
return true;
return true;
} else if (a.y == b.y) {
// horizontal } else if (a.y == b.y) {
int32 y = (int32)a.y; // horizontal
uint8* dst = fBuffer->row_ptr(y); int32 y = (int32)a.y;
int32 x1 = (int32)min_c(a.x, b.x); uint8* dst = fBuffer.row_ptr(y);
int32 x2 = (int32)max_c(a.x, b.x); int32 x1 = (int32)min_c(a.x, b.x);
pixel32 color; int32 x2 = (int32)max_c(a.x, b.x);
color.data8[0] = c.blue; pixel32 color;
color.data8[1] = c.green; color.data8[0] = c.blue;
color.data8[2] = c.red; color.data8[1] = c.green;
color.data8[3] = 255; color.data8[2] = c.red;
// draw a line, iterate over clipping boxes color.data8[3] = 255;
fBaseRenderer->first_clip_box(); // draw a line, iterate over clipping boxes
do { fBaseRenderer.first_clip_box();
if (fBaseRenderer->ymin() <= y && do {
fBaseRenderer->ymax() >= y) { if (fBaseRenderer.ymin() <= y &&
int32 i = max_c(fBaseRenderer->xmin(), x1); fBaseRenderer.ymax() >= y) {
int32 end = min_c(fBaseRenderer->xmax(), x2); int32 i = max_c(fBaseRenderer.xmin(), x1);
uint32* handle = (uint32*)(dst + i * 4); int32 end = min_c(fBaseRenderer.xmax(), x2);
for (; i <= end; i++) { uint32* handle = (uint32*)(dst + i * 4);
*handle++ = color.data32; for (; i <= end; i++) {
} *handle++ = color.data32;
} }
} while (fBaseRenderer->next_clip_box()); }
} while (fBaseRenderer.next_clip_box());
return true;
} return true;
} }
return false; return false;
} }
@@ -594,16 +535,16 @@ Painter::StrokeRect(const BRect& r) const
// first, try an optimized version // first, try an optimized version
if (fPenSize == 1.0 && if (fPenSize == 1.0 &&
(fDrawingMode == B_OP_COPY || fDrawingMode == B_OP_OVER)) { (fDrawingMode == B_OP_COPY || fDrawingMode == B_OP_OVER)) {
pattern p = *fPatternHandler->GetR5Pattern(); pattern p = *fPatternHandler.GetR5Pattern();
if (p == B_SOLID_HIGH) { if (p == B_SOLID_HIGH) {
BRect rect(a, b); BRect rect(a, b);
StrokeRect(rect, StrokeRect(rect,
fPatternHandler->HighColor().GetColor32()); fPatternHandler.HighColor().GetColor32());
return _Clipped(rect); return _Clipped(rect);
} else if (p == B_SOLID_LOW) { } else if (p == B_SOLID_LOW) {
BRect rect(a, b); BRect rect(a, b);
StrokeRect(rect, StrokeRect(rect,
fPatternHandler->LowColor().GetColor32()); fPatternHandler.LowColor().GetColor32());
return _Clipped(rect); return _Clipped(rect);
} }
} }
@@ -659,27 +600,27 @@ Painter::FillRect(const BRect& r) const
// first, try an optimized version // first, try an optimized version
if (fDrawingMode == B_OP_COPY || fDrawingMode == B_OP_OVER) { if (fDrawingMode == B_OP_COPY || fDrawingMode == B_OP_OVER) {
pattern p = *fPatternHandler->GetR5Pattern(); pattern p = *fPatternHandler.GetR5Pattern();
if (p == B_SOLID_HIGH) { if (p == B_SOLID_HIGH) {
BRect rect(a, b); BRect rect(a, b);
FillRect(rect, fPatternHandler->HighColor().GetColor32()); FillRect(rect, fPatternHandler.HighColor().GetColor32());
return _Clipped(rect); return _Clipped(rect);
} else if (p == B_SOLID_LOW) { } else if (p == B_SOLID_LOW) {
BRect rect(a, b); BRect rect(a, b);
FillRect(rect, fPatternHandler->LowColor().GetColor32()); FillRect(rect, fPatternHandler.LowColor().GetColor32());
return _Clipped(rect); return _Clipped(rect);
} }
} }
if (fDrawingMode == B_OP_ALPHA && fAlphaFncMode == B_ALPHA_OVERLAY) { if (fDrawingMode == B_OP_ALPHA && fAlphaFncMode == B_ALPHA_OVERLAY) {
pattern p = *fPatternHandler->GetR5Pattern(); pattern p = *fPatternHandler.GetR5Pattern();
if (p == B_SOLID_HIGH) { if (p == B_SOLID_HIGH) {
BRect rect(a, b); BRect rect(a, b);
_BlendRect32(rect, fPatternHandler->HighColor().GetColor32()); _BlendRect32(rect, fPatternHandler.HighColor().GetColor32());
return _Clipped(rect); return _Clipped(rect);
} else if (p == B_SOLID_LOW) { } else if (p == B_SOLID_LOW) {
rgb_color c = fPatternHandler->LowColor().GetColor32(); rgb_color c = fPatternHandler.LowColor().GetColor32();
if (fAlphaSrcMode == B_CONSTANT_ALPHA) if (fAlphaSrcMode == B_CONSTANT_ALPHA)
c.alpha = fPatternHandler->HighColor().GetColor32().alpha; c.alpha = fPatternHandler.HighColor().GetColor32().alpha;
BRect rect(a, b); BRect rect(a, b);
_BlendRect32(rect, c); _BlendRect32(rect, c);
return _Clipped(rect); return _Clipped(rect);
@@ -707,70 +648,69 @@ Painter::FillRect(const BRect& r) const
void void
Painter::FillRect(const BRect& r, const rgb_color& c) const Painter::FillRect(const BRect& r, const rgb_color& c) const
{ {
if (fBuffer && fValidClipping) { if (!fValidClipping)
uint8* dst = fBuffer->row_ptr(0); return;
uint32 bpr = fBuffer->stride();
int32 left = (int32)r.left; uint8* dst = fBuffer.row_ptr(0);
int32 top = (int32)r.top; uint32 bpr = fBuffer.stride();
int32 right = (int32)r.right; int32 left = (int32)r.left;
int32 bottom = (int32)r.bottom; int32 top = (int32)r.top;
// get a 32 bit pixel ready with the color int32 right = (int32)r.right;
pixel32 color; int32 bottom = (int32)r.bottom;
color.data8[0] = c.blue; // get a 32 bit pixel ready with the color
color.data8[1] = c.green; pixel32 color;
color.data8[2] = c.red; color.data8[0] = c.blue;
color.data8[3] = c.alpha; color.data8[1] = c.green;
// fill rects, iterate over clipping boxes color.data8[2] = c.red;
fBaseRenderer->first_clip_box(); color.data8[3] = c.alpha;
do { // fill rects, iterate over clipping boxes
int32 x1 = max_c(fBaseRenderer->xmin(), left); fBaseRenderer.first_clip_box();
int32 x2 = min_c(fBaseRenderer->xmax(), right); do {
if (x1 <= x2) { int32 x1 = max_c(fBaseRenderer.xmin(), left);
int32 y1 = max_c(fBaseRenderer->ymin(), top); int32 x2 = min_c(fBaseRenderer.xmax(), right);
int32 y2 = min_c(fBaseRenderer->ymax(), bottom); if (x1 <= x2) {
uint8* offset = dst + x1 * 4; int32 y1 = max_c(fBaseRenderer.ymin(), top);
for (; y1 <= y2; y1++) { int32 y2 = min_c(fBaseRenderer.ymax(), bottom);
uint8* offset = dst + x1 * 4;
for (; y1 <= y2; y1++) {
// uint32* handle = (uint32*)(offset + y1 * bpr); // uint32* handle = (uint32*)(offset + y1 * bpr);
// for (int32 x = x1; x <= x2; x++) { // for (int32 x = x1; x <= x2; x++) {
// *handle++ = color.data32; // *handle++ = color.data32;
// } // }
gfxset32(offset + y1 * bpr, color.data32, (x2 - x1 + 1) * 4); gfxset32(offset + y1 * bpr, color.data32, (x2 - x1 + 1) * 4);
}
} }
} while (fBaseRenderer->next_clip_box()); }
} } while (fBaseRenderer.next_clip_box());
} }
// FillRectNoClipping // FillRectNoClipping
void void
Painter::FillRectNoClipping(const BRect& r, const rgb_color& c) const Painter::FillRectNoClipping(const BRect& r, const rgb_color& c) const
{ {
if (fBuffer) { int32 left = (int32)r.left;
int32 left = (int32)r.left; int32 y = (int32)r.top;
int32 y = (int32)r.top; int32 right = (int32)r.right;
int32 right = (int32)r.right; int32 bottom = (int32)r.bottom;
int32 bottom = (int32)r.bottom;
uint8* dst = fBuffer->row_ptr(y); uint8* dst = fBuffer.row_ptr(y);
uint32 bpr = fBuffer->stride(); uint32 bpr = fBuffer.stride();
// get a 32 bit pixel ready with the color // get a 32 bit pixel ready with the color
pixel32 color; pixel32 color;
color.data8[0] = c.blue; color.data8[0] = c.blue;
color.data8[1] = c.green; color.data8[1] = c.green;
color.data8[2] = c.red; color.data8[2] = c.red;
color.data8[3] = c.alpha; color.data8[3] = c.alpha;
dst += left * 4; dst += left * 4;
for (; y <= bottom; y++) { for (; y <= bottom; y++) {
// uint32* handle = (uint32*)dst; // uint32* handle = (uint32*)dst;
// for (int32 x = left; x <= right; x++) { // for (int32 x = left; x <= right; x++) {
// *handle++ = color.data32; // *handle++ = color.data32;
// } // }
gfxset32(dst, color.data32, (right - left + 1) * 4); gfxset32(dst, color.data32, (right - left + 1) * 4);
dst += bpr; dst += bpr;
}
} }
} }
@@ -809,8 +749,8 @@ Painter::StrokeRoundRect(const BRect& r, float xRadius, float yRadius) const
outer.rect(lt.x, lt.y, rb.x, rb.y); outer.rect(lt.x, lt.y, rb.x, rb.y);
outer.radius(xRadius, yRadius); outer.radius(xRadius, yRadius);
fRasterizer->reset(); fRasterizer.reset();
fRasterizer->add_path(outer); fRasterizer.add_path(outer);
// don't add an inner hole if the "size is negative", this avoids some // don't add an inner hole if the "size is negative", this avoids some
// defects that can be observed on R5 and could be regarded as a bug. // defects that can be observed on R5 and could be regarded as a bug.
@@ -819,19 +759,19 @@ Painter::StrokeRoundRect(const BRect& r, float xRadius, float yRadius) const
inner.rect(lt.x + fPenSize, lt.y + fPenSize, rb.x - fPenSize, rb.y - fPenSize); inner.rect(lt.x + fPenSize, lt.y + fPenSize, rb.x - fPenSize, rb.y - fPenSize);
inner.radius(max_c(0.0, xRadius - fPenSize), max_c(0.0, yRadius - fPenSize)); inner.radius(max_c(0.0, xRadius - fPenSize), max_c(0.0, yRadius - fPenSize));
fRasterizer->add_path(inner); fRasterizer.add_path(inner);
} }
// make the inner rect work as a hole // make the inner rect work as a hole
fRasterizer->filling_rule(agg::fill_even_odd); fRasterizer.filling_rule(agg::fill_even_odd);
if (fPenSize > 2) if (fPenSize > 2)
agg::render_scanlines(*fRasterizer, *fPackedScanline, *fRenderer); agg::render_scanlines(fRasterizer, fPackedScanline, fRenderer);
else else
agg::render_scanlines(*fRasterizer, *fUnpackedScanline, *fRenderer); agg::render_scanlines(fRasterizer, fUnpackedScanline, fRenderer);
// reset to default // reset to default
fRasterizer->filling_rule(agg::fill_non_zero); fRasterizer.filling_rule(agg::fill_non_zero);
return _Clipped(_BoundingBox(outer)); return _Clipped(_BoundingBox(outer));
} }
@@ -915,20 +855,20 @@ Painter::DrawEllipse(BRect r, bool fill) const
yRadius + inset, yRadius + inset,
divisions); divisions);
fRasterizer->reset(); fRasterizer.reset();
fRasterizer->add_path(outer); fRasterizer.add_path(outer);
fRasterizer->add_path(inner); fRasterizer.add_path(inner);
// make the inner ellipse work as a hole // make the inner ellipse work as a hole
fRasterizer->filling_rule(agg::fill_even_odd); fRasterizer.filling_rule(agg::fill_even_odd);
if (fPenSize > 4) if (fPenSize > 4)
agg::render_scanlines(*fRasterizer, *fPackedScanline, *fRenderer); agg::render_scanlines(fRasterizer, fPackedScanline, fRenderer);
else else
agg::render_scanlines(*fRasterizer, *fUnpackedScanline, *fRenderer); agg::render_scanlines(fRasterizer, fUnpackedScanline, fRenderer);
// reset to default // reset to default
fRasterizer->filling_rule(agg::fill_non_zero); fRasterizer.filling_rule(agg::fill_non_zero);
return _Clipped(_BoundingBox(outer)); return _Clipped(_BoundingBox(outer));
} }
@@ -1008,17 +948,16 @@ Painter::DrawString(const char* utf8String, uint32 length,
SetPattern(B_SOLID_HIGH, true); SetPattern(B_SOLID_HIGH, true);
if (fBuffer) { bounds = fTextRenderer->RenderString(utf8String,
bounds = fTextRenderer->RenderString(utf8String, length,
length, &fRenderer,
fRenderer, &fRendererBin,
fRendererBin, baseLine,
baseLine, fClippingRegion->Frame(),
fClippingRegion->Frame(), false,
false, &fPenLocation,
&fPenLocation, delta);
delta);
}
return _Clipped(bounds); return _Clipped(bounds);
} }
@@ -1036,8 +975,8 @@ Painter::BoundingBox(const char* utf8String, uint32 length,
static BRect dummy; static BRect dummy;
return fTextRenderer->RenderString(utf8String, return fTextRenderer->RenderString(utf8String,
length, length,
fRenderer, &fRenderer,
fRendererBin, &fRendererBin,
baseLine, dummy, true, penLocation, baseLine, dummy, true, penLocation,
delta); delta);
} }
@@ -1113,42 +1052,6 @@ Painter::InvertRect(const BRect& r) const
// #pragma mark - private // #pragma mark - private
// _MakeEmpty
void
Painter::_MakeEmpty()
{
delete fBuffer;
fBuffer = NULL;
delete fPixelFormat;
fPixelFormat = NULL;
delete fBaseRenderer;
fBaseRenderer = NULL;
#if USE_OUTLINE_RASTERIZER
delete fOutlineRenderer;
fOutlineRenderer = NULL;
delete fOutlineRasterizer;
fOutlineRasterizer = NULL;
#endif
delete fUnpackedScanline;
fUnpackedScanline = NULL;
delete fPackedScanline;
fPackedScanline = NULL;
delete fRasterizer;
fRasterizer = NULL;
delete fRenderer;
fRenderer = NULL;
delete fRendererBin;
fRendererBin = NULL;
}
// _Transform // _Transform
void void
Painter::_Transform(BPoint* point, bool centerOffset) const Painter::_Transform(BPoint* point, bool centerOffset) const
@@ -1194,13 +1097,6 @@ Painter::_UpdateFont()
fTextRenderer->SetFont(fFont); fTextRenderer->SetFont(fFont);
} }
// _UpdateLineWidth
void
Painter::_UpdateLineWidth()
{
fLineProfile.width(fPenSize);
}
// _UpdateDrawingMode // _UpdateDrawingMode
void void
Painter::_UpdateDrawingMode(bool drawingText) Painter::_UpdateDrawingMode(bool drawingText)
@@ -1223,39 +1119,23 @@ Painter::_UpdateDrawingMode(bool drawingText)
// When a solid pattern is used, _SetRendererColor() // When a solid pattern is used, _SetRendererColor()
// has to be called so that all internal colors in the renderes // has to be called so that all internal colors in the renderes
// are up to date for use by the solid drawing mode version. // are up to date for use by the solid drawing mode version.
fPixelFormat->SetDrawingMode(fDrawingMode, fAlphaSrcMode, fPixelFormat.SetDrawingMode(fDrawingMode, fAlphaSrcMode,
fAlphaFncMode, drawingText); fAlphaFncMode, drawingText);
} }
// _SetRendererColor // _SetRendererColor
void void
Painter::_SetRendererColor(const rgb_color& color) const Painter::_SetRendererColor(const rgb_color& color) const
{ {
#if USE_OUTLINE_RASTERIZER fRenderer.color(agg::rgba(color.red / 255.0,
if (fOutlineRenderer) color.green / 255.0,
#if ALIASED_DRAWING color.blue / 255.0,
fOutlineRenderer->line_color(agg::rgba(color.red / 255.0, color.alpha / 255.0));
color.green / 255.0,
color.blue / 255.0,
color.alpha / 255.0));
#else
fOutlineRenderer->color(agg::rgba(color.red / 255.0,
color.green / 255.0,
color.blue / 255.0,
color.alpha / 255.0));
#endif // ALIASED_DRAWING
#endif // USE_OUTLINE_RASTERIZER
if (fRenderer)
fRenderer->color(agg::rgba(color.red / 255.0,
color.green / 255.0,
color.blue / 255.0,
color.alpha / 255.0));
// TODO: bitmap fonts not yet correctly setup in AGGTextRenderer // TODO: bitmap fonts not yet correctly setup in AGGTextRenderer
// if (fRendererBin) // fRendererBin.color(agg::rgba(color.red / 255.0,
// fRendererBin->color(agg::rgba(color.red / 255.0, // color.green / 255.0,
// color.green / 255.0, // color.blue / 255.0,
// color.blue / 255.0, // color.alpha / 255.0));
// color.alpha / 255.0));
} }
// #pragma mark - // #pragma mark -
@@ -1351,7 +1231,7 @@ Painter::_DrawBitmap(agg::rendering_buffer& srcBuffer, color_space format,
BRect actualBitmapRect, BRect bitmapRect, BRect actualBitmapRect, BRect bitmapRect,
BRect viewRect) const BRect viewRect) const
{ {
if (!fBuffer || !fValidClipping if (!fValidClipping
|| !bitmapRect.IsValid() || !bitmapRect.Intersects(actualBitmapRect) || !bitmapRect.IsValid() || !bitmapRect.Intersects(actualBitmapRect)
|| !viewRect.IsValid()) { || !viewRect.IsValid()) {
return; return;
@@ -1474,8 +1354,8 @@ Painter::_DrawBitmapNoScale32(F copyRowFunction, uint32 bytesPerSourcePixel,
{ {
// NOTE: this would crash if viewRect was large enough to read outside the // NOTE: this would crash if viewRect was large enough to read outside the
// bitmap, so make sure this is not the case before calling this function! // bitmap, so make sure this is not the case before calling this function!
uint8* dst = fBuffer->row_ptr(0); uint8* dst = fBuffer.row_ptr(0);
uint32 dstBPR = fBuffer->stride(); uint32 dstBPR = fBuffer.stride();
const uint8* src = srcBuffer.row_ptr(0); const uint8* src = srcBuffer.row_ptr(0);
uint32 srcBPR = srcBuffer.stride(); uint32 srcBPR = srcBuffer.stride();
@@ -1503,13 +1383,13 @@ if (left - xOffset < 0 || left - xOffset >= (int32)srcBuffer.width() ||
const rgb_color* colorMap = SystemPalette(); const rgb_color* colorMap = SystemPalette();
// copy rects, iterate over clipping boxes // copy rects, iterate over clipping boxes
fBaseRenderer->first_clip_box(); fBaseRenderer.first_clip_box();
do { do {
int32 x1 = max_c(fBaseRenderer->xmin(), left); int32 x1 = max_c(fBaseRenderer.xmin(), left);
int32 x2 = min_c(fBaseRenderer->xmax(), right); int32 x2 = min_c(fBaseRenderer.xmax(), right);
if (x1 <= x2) { if (x1 <= x2) {
int32 y1 = max_c(fBaseRenderer->ymin(), top); int32 y1 = max_c(fBaseRenderer.ymin(), top);
int32 y2 = min_c(fBaseRenderer->ymax(), bottom); int32 y2 = min_c(fBaseRenderer.ymax(), bottom);
if (y1 <= y2) { if (y1 <= y2) {
uint8* dstHandle = dst + y1 * dstBPR + x1 * 4; uint8* dstHandle = dst + y1 * dstBPR + x1 * 4;
const uint8* srcHandle = src + (y1 - yOffset) * srcBPR const uint8* srcHandle = src + (y1 - yOffset) * srcBPR
@@ -1524,7 +1404,7 @@ if (left - xOffset < 0 || left - xOffset >= (int32)srcBuffer.width() ||
} }
} }
} }
} while (fBaseRenderer->next_clip_box()); } while (fBaseRenderer.next_clip_box());
} }
// _DrawBitmapGeneric32 // _DrawBitmapGeneric32
@@ -1582,13 +1462,13 @@ Painter::_DrawBitmapGeneric32(agg::rendering_buffer& srcBuffer,
fPath.close_polygon(); fPath.close_polygon();
agg::conv_transform<agg::path_storage> transformedPath(fPath, srcMatrix); agg::conv_transform<agg::path_storage> transformedPath(fPath, srcMatrix);
fRasterizer->reset(); fRasterizer.reset();
fRasterizer->add_path(transformedPath); fRasterizer.add_path(transformedPath);
// render the path with the bitmap as scanline fill // render the path with the bitmap as scanline fill
agg::render_scanlines_aa(*fRasterizer, agg::render_scanlines_aa(fRasterizer,
*fUnpackedScanline, fUnpackedScanline,
*fBaseRenderer, fBaseRenderer,
spanAllocator, spanAllocator,
spanGenerator); spanGenerator);
} }
@@ -1597,17 +1477,15 @@ Painter::_DrawBitmapGeneric32(agg::rendering_buffer& srcBuffer,
void void
Painter::_InvertRect32(BRect r) const Painter::_InvertRect32(BRect r) const
{ {
if (fBuffer) { int32 width = r.IntegerWidth() + 1;
int32 width = r.IntegerWidth() + 1; for (int32 y = (int32)r.top; y <= (int32)r.bottom; y++) {
for (int32 y = (int32)r.top; y <= (int32)r.bottom; y++) { uint8* dst = fBuffer.row_ptr(y);
uint8* dst = fBuffer->row_ptr(y); dst += (int32)r.left * 4;
dst += (int32)r.left * 4; for (int32 i = 0; i < width; i++) {
for (int32 i = 0; i < width; i++) { dst[0] = 255 - dst[0];
dst[0] = 255 - dst[0]; dst[1] = 255 - dst[1];
dst[1] = 255 - dst[1]; dst[2] = 255 - dst[2];
dst[2] = 255 - dst[2]; dst += 4;
dst += 4;
}
} }
} }
} }
@@ -1616,32 +1494,33 @@ Painter::_InvertRect32(BRect r) const
void void
Painter::_BlendRect32(const BRect& r, const rgb_color& c) const Painter::_BlendRect32(const BRect& r, const rgb_color& c) const
{ {
if (fBuffer && fValidClipping) { if (!fValidClipping)
uint8* dst = fBuffer->row_ptr(0); return;
uint32 bpr = fBuffer->stride();
int32 left = (int32)r.left; uint8* dst = fBuffer.row_ptr(0);
int32 top = (int32)r.top; uint32 bpr = fBuffer.stride();
int32 right = (int32)r.right;
int32 bottom = (int32)r.bottom;
// fill rects, iterate over clipping boxes int32 left = (int32)r.left;
fBaseRenderer->first_clip_box(); int32 top = (int32)r.top;
do { int32 right = (int32)r.right;
int32 x1 = max_c(fBaseRenderer->xmin(), left); int32 bottom = (int32)r.bottom;
int32 x2 = min_c(fBaseRenderer->xmax(), right);
if (x1 <= x2) {
int32 y1 = max_c(fBaseRenderer->ymin(), top);
int32 y2 = min_c(fBaseRenderer->ymax(), bottom);
uint8* offset = dst + x1 * 4 + y1 * bpr; // fill rects, iterate over clipping boxes
for (; y1 <= y2; y1++) { fBaseRenderer.first_clip_box();
blend_line32(offset, x2 - x1 + 1, c.red, c.green, c.blue, c.alpha); do {
offset += bpr; int32 x1 = max_c(fBaseRenderer.xmin(), left);
} int32 x2 = min_c(fBaseRenderer.xmax(), right);
if (x1 <= x2) {
int32 y1 = max_c(fBaseRenderer.ymin(), top);
int32 y2 = min_c(fBaseRenderer.ymax(), bottom);
uint8* offset = dst + x1 * 4 + y1 * bpr;
for (; y1 <= y2; y1++) {
blend_line32(offset, x2 - x1 + 1, c.red, c.green, c.blue, c.alpha);
offset += bpr;
} }
} while (fBaseRenderer->next_clip_box()); }
} } while (fBaseRenderer.next_clip_box());
} }
// #pragma mark - // #pragma mark -
@@ -1697,34 +1576,24 @@ template<class VertexSource>
BRect BRect
Painter::_StrokePath(VertexSource& path) const Painter::_StrokePath(VertexSource& path) const
{ {
#if USE_OUTLINE_RASTERIZER agg::conv_stroke<VertexSource> stroke(path);
fOutlineRasterizer->add_path(path); stroke.width(fPenSize);
#else
// if (fPenSize > 1.0) {
agg::conv_stroke<VertexSource> stroke(path);
stroke.width(fPenSize);
// special case line width = 1 with square caps // special case line width = 1 with square caps
// this has a couple of advantages and it looks // this has a couple of advantages and it looks
// like this is also the R5 behaviour. // like this is also the R5 behaviour.
if (fPenSize == 1.0 && fLineCapMode == B_BUTT_CAP) { if (fPenSize == 1.0 && fLineCapMode == B_BUTT_CAP) {
stroke.line_cap(agg::square_cap); stroke.line_cap(agg::square_cap);
} else { } else {
stroke.line_cap(agg_line_cap_mode_for(fLineCapMode)); stroke.line_cap(agg_line_cap_mode_for(fLineCapMode));
} }
stroke.line_join(agg_line_join_mode_for(fLineJoinMode)); stroke.line_join(agg_line_join_mode_for(fLineJoinMode));
stroke.miter_limit(fMiterLimit); stroke.miter_limit(fMiterLimit);
fRasterizer->reset(); fRasterizer.reset();
fRasterizer->add_path(stroke); fRasterizer.add_path(stroke);
agg::render_scanlines(*fRasterizer, *fPackedScanline, *fRenderer); agg::render_scanlines(fRasterizer, fPackedScanline, fRenderer);
// } else {
// TODO: update to AGG 2.3 to get rid of the remaining problems:
// rects which are 2 or 1 pixel high/wide don't render at all.
// fOutlineRasterizer->add_path(path);
// }
#endif
BRect touched = _BoundingBox(path); BRect touched = _BoundingBox(path);
float penSize = ceilf(fPenSize / 2.0); float penSize = ceilf(fPenSize / 2.0);
@@ -1738,9 +1607,9 @@ template<class VertexSource>
BRect BRect
Painter::_FillPath(VertexSource& path) const Painter::_FillPath(VertexSource& path) const
{ {
fRasterizer->reset(); fRasterizer.reset();
fRasterizer->add_path(path); fRasterizer.add_path(path);
agg::render_scanlines(*fRasterizer, *fPackedScanline, *fRenderer); agg::render_scanlines(fRasterizer, fPackedScanline, fRenderer);
return _Clipped(_BoundingBox(path)); return _Clipped(_BoundingBox(path));
} }
+10 -34
View File
@@ -32,24 +32,6 @@ class ServerBitmap;
class ServerFont; class ServerFont;
class Transformable; class Transformable;
// TODO: API transition:
// * most all functions should take a DrawState* context parameter instead
// of the current pattern argument, that way, each function can
// decide for itself, which pieces of information in DrawState it
// needs -> well I'm not so sure about this, there could also
// be a DrawState member in Painter fGraphicsState or something...
// * Painter itself should be made thread safe. Because no
// ServerWindow is supposed to draw outside of its clipping region,
// there is actually no reason to lock the DisplayDriver. Multiple
// threads drawing in the frame buffer at the same time is actually
// only bad if their drawing could overlap, but this is already
// prevented by the clipping regions (access to those needs to be
// locked).
// Making Painter thread safe could introduce some overhead, since
// some of the current members of Painter would need to be created
// on the stack... I'll have to see about that... On multiple CPU
// machines though, there would be quite an improvement. In two
// years from now, most systems will be at least dual CPU
class Painter { class Painter {
public: public:
@@ -75,7 +57,7 @@ class Painter {
inline void SetHighColor(const RGBColor& color) inline void SetHighColor(const RGBColor& color)
{ SetHighColor(color.GetColor32()); } { SetHighColor(color.GetColor32()); }
inline rgb_color HighColor() const inline rgb_color HighColor() const
{ return fPatternHandler-> { return fPatternHandler.
HighColor().GetColor32(); } HighColor().GetColor32(); }
void SetLowColor(const rgb_color& color); void SetLowColor(const rgb_color& color);
@@ -209,8 +191,6 @@ class Painter {
{ return _Clipped(rect); } { return _Clipped(rect); }
private: private:
void _MakeEmpty();
void _Transform(BPoint* point, void _Transform(BPoint* point,
bool centerOffset = true) const; bool centerOffset = true) const;
BPoint _Transform(const BPoint& point, BPoint _Transform(const BPoint& point,
@@ -259,22 +239,18 @@ class Painter {
template<class VertexSource> template<class VertexSource>
BRect _FillPath(VertexSource& path) const; BRect _FillPath(VertexSource& path) const;
agg::rendering_buffer* fBuffer; mutable agg::rendering_buffer fBuffer;
// AGG rendering and rasterization classes // AGG rendering and rasterization classes
pixfmt* fPixelFormat; pixfmt fPixelFormat;
renderer_base* fBaseRenderer; mutable renderer_base fBaseRenderer;
outline_renderer_type* fOutlineRenderer; mutable scanline_unpacked_type fUnpackedScanline;
outline_rasterizer_type* fOutlineRasterizer; mutable scanline_packed_type fPackedScanline;
mutable rasterizer_type fRasterizer;
mutable renderer_type fRenderer;
mutable renderer_bin_type fRendererBin;
scanline_unpacked_type* fUnpackedScanline;
scanline_packed_type* fPackedScanline;
rasterizer_type* fRasterizer;
renderer_type* fRenderer;
renderer_bin_type* fRendererBin;
agg::line_profile_aa fLineProfile;
mutable agg::path_storage fPath; mutable agg::path_storage fPath;
mutable agg::conv_curve<agg::path_storage> fCurve; mutable agg::conv_curve<agg::path_storage> fCurve;
@@ -293,7 +269,7 @@ mutable agg::conv_curve<agg::path_storage> fCurve;
join_mode fLineJoinMode; join_mode fLineJoinMode;
float fMiterLimit; float fMiterLimit;
PatternHandler* fPatternHandler; PatternHandler fPatternHandler;
ServerFont fFont; ServerFont fFont;
// a class handling rendering and caching of glyphs // a class handling rendering and caching of glyphs