From 0118ad76e16ce6ffa705ff3db93f48ed0c3cf260 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20A=C3=9Fmus?= Date: Mon, 7 Nov 2005 01:23:40 +0000 Subject: [PATCH] * 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 --- headers/private/servers/app/DrawingEngine.h | 2 +- src/servers/app/drawing/DrawingEngine.cpp | 15 +- src/servers/app/drawing/Painter/Painter.cpp | 171 +++++++++++++++----- src/servers/app/drawing/Painter/Painter.h | 15 +- 4 files changed, 150 insertions(+), 53 deletions(-) diff --git a/headers/private/servers/app/DrawingEngine.h b/headers/private/servers/app/DrawingEngine.h index 3988332270..acb9b05690 100644 --- a/headers/private/servers/app/DrawingEngine.h +++ b/headers/private/servers/app/DrawingEngine.h @@ -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, diff --git a/src/servers/app/drawing/DrawingEngine.cpp b/src/servers/app/drawing/DrawingEngine.cpp index 9995bea9e9..7afe367b5c 100644 --- a/src/servers/app/drawing/DrawingEngine.cpp +++ b/src/servers/app/drawing/DrawingEngine.cpp @@ -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(); } diff --git a/src/servers/app/drawing/Painter/Painter.cpp b/src/servers/app/drawing/Painter/Painter.cpp index f56f221f95..7606050bcd 100644 --- a/src/servers/app/drawing/Painter/Painter.cpp +++ b/src/servers/app/drawing/Painter/Painter.cpp @@ -13,9 +13,11 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -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 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 @@ -1474,20 +1556,23 @@ Painter::_StrokePath(VertexSource& path) const #else // if (fPenSize > 1.0) { agg::conv_stroke 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 > 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 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)); } diff --git a/src/servers/app/drawing/Painter/Painter.h b/src/servers/app/drawing/Painter/Painter.h index 1430885044..480fc1d00c 100644 --- a/src/servers/app/drawing/Painter/Painter.h +++ b/src/servers/app/drawing/Painter/Painter.h @@ -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;