Various fixes and efficiency improvements to the drawing backend. Among other stuff, stroked lines with a width greater than 1 have anti-aliased butts now. There are some bugs left regarding text rendering.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@12761 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -838,14 +838,14 @@ void
|
|||||||
DisplayDriverPainter::StrokeRect(const BRect &r, const RGBColor &color)
|
DisplayDriverPainter::StrokeRect(const BRect &r, const RGBColor &color)
|
||||||
{
|
{
|
||||||
if (Lock()) {
|
if (Lock()) {
|
||||||
fGraphicsCard->HideSoftwareCursor();
|
|
||||||
|
|
||||||
// support invalid rects
|
// support invalid rects
|
||||||
BRect vr(min_c(r.left, r.right),
|
BRect vr(min_c(r.left, r.right),
|
||||||
min_c(r.top, r.bottom),
|
min_c(r.top, r.bottom),
|
||||||
max_c(r.left, r.right),
|
max_c(r.left, r.right),
|
||||||
max_c(r.top, r.bottom));
|
max_c(r.top, r.bottom));
|
||||||
|
|
||||||
|
fGraphicsCard->HideSoftwareCursor(vr);
|
||||||
|
|
||||||
fPainter->StrokeRect(vr, color.GetColor32());
|
fPainter->StrokeRect(vr, color.GetColor32());
|
||||||
|
|
||||||
/* fGraphicsCard->Invalidate(fPainter->ClipRect(BRect(vr.left, vr.top,
|
/* fGraphicsCard->Invalidate(fPainter->ClipRect(BRect(vr.left, vr.top,
|
||||||
@@ -868,7 +868,15 @@ void
|
|||||||
DisplayDriverPainter::StrokeRect(const BRect &r, const DrawData *d)
|
DisplayDriverPainter::StrokeRect(const BRect &r, const DrawData *d)
|
||||||
{
|
{
|
||||||
if (Lock()) {
|
if (Lock()) {
|
||||||
fGraphicsCard->HideSoftwareCursor();
|
// support invalid rects
|
||||||
|
BRect vr(min_c(r.left, r.right),
|
||||||
|
min_c(r.top, r.bottom),
|
||||||
|
max_c(r.left, r.right),
|
||||||
|
max_c(r.top, r.bottom));
|
||||||
|
float extend = -ceilf(d->PenSize() / 2.0);
|
||||||
|
vr.InsetBy(extend, extend);
|
||||||
|
|
||||||
|
fGraphicsCard->HideSoftwareCursor(vr);
|
||||||
|
|
||||||
fPainter->SetDrawData(d);
|
fPainter->SetDrawData(d);
|
||||||
BRect touched = fPainter->StrokeRect(r);
|
BRect touched = fPainter->StrokeRect(r);
|
||||||
@@ -974,6 +982,7 @@ DisplayDriverPainter::DrawString(const char *string, const int32 &length,
|
|||||||
const BPoint &pt, DrawData *d)
|
const BPoint &pt, DrawData *d)
|
||||||
{
|
{
|
||||||
if (Lock()) {
|
if (Lock()) {
|
||||||
|
fPainter->SetDrawData(d);
|
||||||
//bigtime_t now = system_time();
|
//bigtime_t now = system_time();
|
||||||
// TODO: BoundingBox is quite slow!! Optimizing it will be beneficial.
|
// TODO: BoundingBox is quite slow!! Optimizing it will be beneficial.
|
||||||
// Cursiously, the actual DrawString after it is actually faster!?!
|
// Cursiously, the actual DrawString after it is actually faster!?!
|
||||||
@@ -984,8 +993,6 @@ DisplayDriverPainter::DrawString(const char *string, const int32 &length,
|
|||||||
//printf("bounding box '%s': %lld µs\n", string, system_time() - now);
|
//printf("bounding box '%s': %lld µs\n", string, system_time() - now);
|
||||||
fGraphicsCard->HideSoftwareCursor(b);
|
fGraphicsCard->HideSoftwareCursor(b);
|
||||||
|
|
||||||
fPainter->SetDrawData(d);
|
|
||||||
|
|
||||||
//now = system_time();
|
//now = system_time();
|
||||||
BRect touched = fPainter->DrawString(string, length, pt);
|
BRect touched = fPainter->DrawString(string, length, pt);
|
||||||
//printf("drawing string: %lld µs\n", system_time() - now);
|
//printf("drawing string: %lld µs\n", system_time() - now);
|
||||||
|
|||||||
@@ -30,6 +30,21 @@
|
|||||||
|
|
||||||
#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
|
||||||
|
|
||||||
int
|
int
|
||||||
roundf(float v)
|
roundf(float v)
|
||||||
{
|
{
|
||||||
@@ -216,7 +231,11 @@ 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();
|
_UpdateLineWidth();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -531,9 +550,8 @@ Painter::StrokeRect(const BRect& r) const
|
|||||||
// support invalid rects
|
// support invalid rects
|
||||||
BPoint a(min_c(r.left, r.right), min_c(r.top, r.bottom));
|
BPoint a(min_c(r.left, r.right), min_c(r.top, r.bottom));
|
||||||
BPoint b(max_c(r.left, r.right), max_c(r.top, r.bottom));
|
BPoint b(max_c(r.left, r.right), max_c(r.top, r.bottom));
|
||||||
bool centerOffset = fPenSize == 1.0;
|
_Transform(&a, false);
|
||||||
_Transform(&a, centerOffset);
|
_Transform(&b, false);
|
||||||
_Transform(&b, centerOffset);
|
|
||||||
|
|
||||||
// first, try an optimized version
|
// first, try an optimized version
|
||||||
if (fPenSize == 1.0 &&
|
if (fPenSize == 1.0 &&
|
||||||
@@ -552,11 +570,24 @@ Painter::StrokeRect(const BRect& r) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fmodf(fPenSize, 2.0) != 0.0) {
|
||||||
|
// shift coords to center of pixels
|
||||||
|
a.x += 0.5;
|
||||||
|
a.y += 0.5;
|
||||||
|
b.x += 0.5;
|
||||||
|
b.y += 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
agg::path_storage path;
|
agg::path_storage path;
|
||||||
path.move_to(a.x, a.y);
|
path.move_to(a.x, a.y);
|
||||||
path.line_to(b.x, a.y);
|
if (a.x == b.x || a.y == b.y) {
|
||||||
path.line_to(b.x, b.y);
|
// special case rects with one pixel height or width
|
||||||
path.line_to(a.x, b.y);
|
path.line_to(b.x, b.y);
|
||||||
|
} else {
|
||||||
|
path.line_to(b.x, a.y);
|
||||||
|
path.line_to(b.x, b.y);
|
||||||
|
path.line_to(a.x, b.y);
|
||||||
|
}
|
||||||
path.close_polygon();
|
path.close_polygon();
|
||||||
|
|
||||||
return _StrokePath(path);
|
return _StrokePath(path);
|
||||||
@@ -664,6 +695,8 @@ Painter::StrokeRoundRect(const BRect& r, float xRadius, float yRadius) const
|
|||||||
BPoint lt(r.left, r.top);
|
BPoint lt(r.left, r.top);
|
||||||
BPoint rb(r.right, r.bottom);
|
BPoint rb(r.right, r.bottom);
|
||||||
bool centerOffset = fPenSize == 1.0;
|
bool centerOffset = fPenSize == 1.0;
|
||||||
|
// TODO: use this when using _StrokePath()
|
||||||
|
// bool centerOffset = fmodf(fPenSize, 2.0) != 0.0;
|
||||||
_Transform(<, centerOffset);
|
_Transform(<, centerOffset);
|
||||||
_Transform(&rb, centerOffset);
|
_Transform(&rb, centerOffset);
|
||||||
|
|
||||||
@@ -687,6 +720,8 @@ Painter::StrokeRoundRect(const BRect& r, float xRadius, float yRadius) const
|
|||||||
agg::rounded_rect outer;
|
agg::rounded_rect outer;
|
||||||
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->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
|
||||||
@@ -1227,6 +1262,7 @@ Painter::_DrawEllipse(BPoint center, float xRadius, float yRadius,
|
|||||||
yRadius + inset,
|
yRadius + inset,
|
||||||
divisions);
|
divisions);
|
||||||
|
|
||||||
|
fRasterizer->reset();
|
||||||
fRasterizer->add_path(outer);
|
fRasterizer->add_path(outer);
|
||||||
fRasterizer->add_path(inner);
|
fRasterizer->add_path(inner);
|
||||||
|
|
||||||
@@ -1456,19 +1492,25 @@ template<class VertexSource>
|
|||||||
BRect
|
BRect
|
||||||
Painter::_StrokePath(VertexSource& path) const
|
Painter::_StrokePath(VertexSource& path) const
|
||||||
{
|
{
|
||||||
#if ALIASED_DRAWING
|
#if USE_OUTLINE_RASTERIZER
|
||||||
if (fPenSize > 1.0) {
|
fOutlineRasterizer->add_path(path);
|
||||||
|
#else
|
||||||
|
// if (fPenSize > 1.0) {
|
||||||
agg::conv_stroke<VertexSource> stroke(path);
|
agg::conv_stroke<VertexSource> stroke(path);
|
||||||
stroke.line_join(agg::round_join);
|
// TODO: Investigate this for shapes. Maybe we are supposed to
|
||||||
|
// use the settings from DrawData! Would make some sense!
|
||||||
|
// stroke.line_join(agg::round_join);
|
||||||
|
// stroke.line_cap(agg::butt_cap);
|
||||||
stroke.width(fPenSize);
|
stroke.width(fPenSize);
|
||||||
|
|
||||||
|
fRasterizer->reset();
|
||||||
fRasterizer->add_path(stroke);
|
fRasterizer->add_path(stroke);
|
||||||
agg::render_scanlines(*fRasterizer, *fScanline, *fRenderer);
|
agg::render_scanlines(*fRasterizer, *fScanline, *fRenderer);
|
||||||
} else {
|
// } else {
|
||||||
fOutlineRasterizer->add_path(path);
|
// 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.
|
||||||
#else
|
// fOutlineRasterizer->add_path(path);
|
||||||
fOutlineRasterizer->add_path(path);
|
// }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
BRect touched = _BoundingBox(path);
|
BRect touched = _BoundingBox(path);
|
||||||
@@ -1483,6 +1525,7 @@ template<class VertexSource>
|
|||||||
BRect
|
BRect
|
||||||
Painter::_FillPath(VertexSource& path) const
|
Painter::_FillPath(VertexSource& path) const
|
||||||
{
|
{
|
||||||
|
fRasterizer->reset();
|
||||||
fRasterizer->add_path(path);
|
fRasterizer->add_path(path);
|
||||||
agg::render_scanlines(*fRasterizer, *fScanline, *fRenderer);
|
agg::render_scanlines(*fRasterizer, *fScanline, *fRenderer);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user