* Painter uses the line_cap and join_mode settings of DrawState

* Painter implements DrawShape for stroking and filling BShape data
* Painter uses clipping to avoid problems with huge coordinates, the R5 app_server can be crashed by this.
  -> this should be added to more places as well like text rendering
* DrawingEngine uses the Painter to draw BShape data


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@14735 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus 2005-11-07 01:23:40 +00:00
parent b5f439b668
commit 0118ad76e1
4 changed files with 150 additions and 53 deletions

View File

@ -133,7 +133,7 @@ public:
void DrawShape( const BRect &bounds,
const int32 &opcount,
const int32 *oplist,
const uint32 *oplist,
const int32 &ptcount,
const BPoint *ptlist,
const DrawState *d,

View File

@ -808,14 +808,21 @@ DrawingEngine::DrawRoundRect(BRect r, const float &xrad,
// DrawShape
void
DrawingEngine::DrawShape(const BRect &bounds, const int32 &opcount,
const int32 *oplist, const int32 &ptcount,
const BPoint *ptlist, const DrawState *d,
DrawingEngine::DrawShape(const BRect& bounds, const int32& opCount,
const uint32* opList, const int32& ptCount,
const BPoint* ptList, const DrawState* d,
bool filled)
{
if (Lock()) {
fGraphicsCard->HideSoftwareCursor();
printf("DrawingEngine::DrawShape() - what is this stuff that gets passed here?\n");
fPainter->SetDrawState(d);
BRect touched = fPainter->DrawShape(opCount, opList,
ptCount, ptList,
filled);
fGraphicsCard->Invalidate(touched);
fGraphicsCard->ShowSoftwareCursor();
Unlock();
}

View File

@ -13,9 +13,11 @@
#include <Bitmap.h>
#include <GraphicsDefs.h>
#include <Region.h>
#include <String.h>
#include <agg_bezier_arc.h>
#include <agg_bounding_rect.h>
#include <agg_conv_clip_polygon.h>
#include <agg_conv_curve.h>
#include <agg_conv_stroke.h>
#include <agg_ellipse.h>
@ -31,7 +33,6 @@
#include "DrawingModeFactory.h"
#include "PatternHandler.h"
#include "RenderingBuffer.h"
#include "ShapeConverter.h"
#include "ServerBitmap.h"
#include "ServerFont.h"
@ -77,6 +78,7 @@ Painter::Painter()
fFontRendererBin(NULL),
fLineProfile(),
fSubpixelPrecise(false),
fPenSize(1.0),
fClippingRegion(new BRegion()),
fValidClipping(false),
@ -85,6 +87,10 @@ Painter::Painter()
// fAlphaSrcMode(B_CONSTANT_ALPHA),
fAlphaFncMode(B_ALPHA_OVERLAY),
fPenLocation(0.0, 0.0),
fLineCapMode(B_BUTT_CAP),
fLineJoinMode(B_MITER_JOIN),
fMiterLimit(B_DEFAULT_MITER_LIMIT),
fDrawingModeFactory(new DrawingModeFactory()),
fPatternHandler(new PatternHandler()),
fTextRenderer(new AGGTextRenderer())
@ -191,10 +197,13 @@ Painter::SetDrawState(const DrawState* data)
(data->GetDrawingMode() == B_OP_ALPHA && (data->AlphaSrcMode() != fAlphaSrcMode ||
data->AlphaFncMode() != fAlphaFncMode));
fDrawingMode = data->GetDrawingMode();
fAlphaSrcMode = data->AlphaSrcMode();
fAlphaFncMode = data->AlphaFncMode();
fDrawingMode = data->GetDrawingMode();
fAlphaSrcMode = data->AlphaSrcMode();
fAlphaFncMode = data->AlphaFncMode();
fPatternHandler->SetPattern(data->GetPattern());
fLineCapMode = data->LineCapMode();
fLineJoinMode = data->LineJoinMode();
fMiterLimit = data->MiterLimit();
if (updateDrawingMode)
_UpdateDrawingMode();
@ -533,18 +542,81 @@ Painter::FillBezier(const BPoint* controlPoints) const
return _FillPath(path);
}
// StrokeShape
BRect
Painter::StrokeShape(/*const */BShape* shape) const
{
return _DrawShape(shape, false);
}
// this comes from Shape.cpp
// code duplication ahead...
#define OP_LINETO 0x10000000
#define OP_BEZIERTO 0x20000000
#define OP_CLOSE 0x40000000
#define OP_MOVETO 0x80000000
// FillShape
// DrawShape
BRect
Painter::FillShape(/*const */BShape* shape) const
Painter::DrawShape(const int32& opCount, const uint32* opList,
const int32& ptCount, const BPoint* points,
bool filled) const
{
return _DrawShape(shape, true);
CHECK_CLIPPING
agg::path_storage path;
for (int32 i = 0; i < opCount; i++) {
switch (opList[i] & 0xFF000000) {
case OP_LINETO: {
int32 count = opList[i] & 0x00FFFFFF;
while (count--) {
path.line_to(points->x, points->y);
points++;
}
break;
}
case (OP_MOVETO | OP_LINETO): {
int32 count = opList[i] & 0x00FFFFFF;
path.move_to(points->x, points->y);
points++;
// execute "line to(s)"
while (count--) {
path.line_to(points->x, points->y);
points++;
}
break;
}
case OP_BEZIERTO: {
int32 count = opList[i] & 0x00FFFFFF;
while (count) {
path.curve4(points[0].x, points[0].y,
points[1].x, points[1].y,
points[2].x, points[2].y);
points += 3;
count -= 3;
}
break;
}
case (OP_MOVETO | OP_BEZIERTO): {
int32 count = opList[i] & 0x00FFFFFF;
// execute "move to"
path.move_to(points->x, points->y);
points++;
// execute "bezier to(s)"
while (count) {
path.curve4(points[0].x, points[0].y,
points[1].x, points[1].y,
points[2].x, points[2].y);
points += 3;
count -= 3;
}
break;
}
case OP_CLOSE:
case OP_CLOSE | OP_LINETO | OP_BEZIERTO: {
path.close_polygon();
break;
}
}
}
agg::conv_curve<agg::path_storage> curve(path);
if (filled)
return _FillPath(curve);
else
return _StrokePath(curve);
}
// StrokeRect
@ -1239,27 +1311,6 @@ Painter::_DrawEllipse(BPoint center, float xRadius, float yRadius,
}
}
// _DrawShape
inline BRect
Painter::_DrawShape(/*const */BShape* shape, bool fill) const
{
CHECK_CLIPPING
// TODO: untested
agg::path_storage path;
ShapeConverter converter(&path);
// offset locations to center of pixels
converter.TranslateBy(BPoint(0.5, 0.5));
converter.Iterate(shape);
if (fill)
return _FillPath(path);
else
return _StrokePath(path);
}
// _DrawPolygon
inline BRect
Painter::_DrawPolygon(const BPoint* ptArray, int32 numPts,
@ -1463,6 +1514,37 @@ Painter::_BoundingBox(VertexSource& path) const
return BRect(left, top, right, bottom);
}
// agg_line_cap_mode_for
inline agg::line_cap_e
agg_line_cap_mode_for(cap_mode mode)
{
switch (mode) {
case B_BUTT_CAP:
return agg::butt_cap;
case B_SQUARE_CAP:
return agg::square_cap;
case B_ROUND_CAP:
return agg::round_cap;
}
return agg::butt_cap;
}
// agg_line_join_mode_for
inline agg::line_join_e
agg_line_join_mode_for(join_mode mode)
{
switch (mode) {
case B_MITER_JOIN:
return agg::miter_join;
case B_ROUND_JOIN:
return agg::round_join;
case B_BEVEL_JOIN:
case B_BUTT_JOIN: // ??
case B_SQUARE_JOIN: // ??
return agg::bevel_join;
}
return agg::miter_join;
}
// _StrokePath
template<class VertexSource>
@ -1474,20 +1556,23 @@ Painter::_StrokePath(VertexSource& path) const
#else
// if (fPenSize > 1.0) {
agg::conv_stroke<VertexSource> stroke(path);
// TODO: Investigate this for shapes. Maybe we are supposed to
// use the settings from DrawState! Would make some sense!
// stroke.line_join(agg::round_join);
// stroke.line_cap(agg::butt_cap);
stroke.width(fPenSize);
// special case line width = 1 with square caps
// this has a couple of advantages and it looks
// like this is also the R5 behaviour.
if (fPenSize == 1.0)
if (fPenSize == 1.0 && fLineCapMode == B_BUTT_CAP) {
stroke.line_cap(agg::square_cap);
} else {
stroke.line_cap(agg_line_cap_mode_for(fLineCapMode));
}
stroke.line_join(agg_line_join_mode_for(fLineJoinMode));
stroke.miter_limit(fMiterLimit);
fRasterizer->reset();
fRasterizer->add_path(stroke);
agg::conv_clip_polygon<agg::conv_stroke<VertexSource> > clippedPath(stroke);
clippedPath.clip_box(-500, -500, fBuffer->width() + 500, fBuffer->height() + 500);
fRasterizer->add_path(clippedPath);
agg::render_scanlines(*fRasterizer, *fScanline, *fRenderer);
// } else {
// TODO: update to AGG 2.3 to get rid of the remaining problems:
@ -1509,9 +1594,11 @@ BRect
Painter::_FillPath(VertexSource& path) const
{
fRasterizer->reset();
fRasterizer->add_path(path);
agg::conv_clip_polygon<VertexSource> clippedPath(path);
clippedPath.clip_box(-500, -500, fBuffer->width() + 500, fBuffer->height() + 500);
fRasterizer->add_path(clippedPath);
agg::render_scanlines(*fRasterizer, *fScanline, *fRenderer);
return _Clipped(_BoundingBox(path));
return _Clipped(_BoundingBox(clippedPath));
}

View File

@ -29,6 +29,7 @@ class PatternHandler;
class RenderingBuffer;
class ServerBitmap;
class ServerFont;
class Transformable;
// TODO: API transition:
// * most all functions should take a DrawState* context parameter instead
@ -123,10 +124,11 @@ class Painter {
BRect FillBezier( const BPoint* controlPoints) const;
// shapes
BRect StrokeShape( /*const */BShape* shape) const;
BRect FillShape( /*const */BShape* shape) const;
BRect DrawShape( const int32& opCount,
const uint32* opList,
const int32& ptCount,
const BPoint* ptList,
bool filled) const;
// rects
BRect StrokeRect( const BRect& r) const;
@ -236,8 +238,6 @@ class Painter {
float xRadius,
float yRadius,
bool fill) const;
BRect _DrawShape( /*const */BShape* shape,
bool fill) const;
BRect _DrawPolygon( const BPoint* ptArray,
int32 numPts,
bool closed,
@ -292,6 +292,9 @@ class Painter {
source_alpha fAlphaSrcMode;
alpha_function fAlphaFncMode;
BPoint fPenLocation;
cap_mode fLineCapMode;
join_mode fLineJoinMode;
float fMiterLimit;
DrawingModeFactory* fDrawingModeFactory;
PatternHandler* fPatternHandler;