diff --git a/headers/private/servers/app/Painter.h b/headers/private/servers/app/Painter.h index 6fffbb66f2..b8435b609f 100644 --- a/headers/private/servers/app/Painter.h +++ b/headers/private/servers/app/Painter.h @@ -64,11 +64,11 @@ class Painter { // painting functions // lines - void StrokeLine( BPoint a, + BRect StrokeLine( BPoint a, BPoint b, const pattern& p = B_SOLID_HIGH); - void StrokeLine( BPoint b, + BRect StrokeLine( BPoint b, const pattern& p = B_SOLID_HIGH); // return true if the line was either vertical or horizontal @@ -115,14 +115,14 @@ class Painter { // rects - void StrokeRect( const BRect& r, + BRect StrokeRect( const BRect& r, const pattern& p = B_SOLID_HIGH) const; // strokes a one pixel wide solid rect, no blending void StrokeRect( const BRect& r, const rgb_color& c) const; - void FillRect( const BRect& r, + BRect FillRect( const BRect& r, const pattern& p = B_SOLID_HIGH) const; // fills a solid rect with color c, no blending @@ -207,6 +207,9 @@ class Painter { uint32 length, const BPoint& baseLine) const; + inline BRect ClipRect(const BRect& rect) const + { return _Clipped(rect); } + private: void _MakeEmpty(); @@ -218,6 +221,7 @@ class Painter { float _Transform(const float& width) const; void _Transform(BRect* rect) const; BRect _Transform(const BRect& rect) const; + BRect _Clipped(const BRect& rect) const; void _RebuildClipping(); @@ -258,10 +262,14 @@ class Painter { template - void _StrokePath(VertexSource& path, + BRect _BoundingBox(VertexSource& path) const; + + template + BRect _StrokePath(VertexSource& path, const pattern& p) const; template - void _FillPath(VertexSource& path, + BRect _FillPath(VertexSource& path, + const pattern& p) const; void _SetPattern(const pattern& p) const; diff --git a/src/servers/app/drawing/DisplayDriverPainter.cpp b/src/servers/app/drawing/DisplayDriverPainter.cpp index ced5daa4ed..27726ca206 100644 --- a/src/servers/app/drawing/DisplayDriverPainter.cpp +++ b/src/servers/app/drawing/DisplayDriverPainter.cpp @@ -460,7 +460,6 @@ printf("region: %ld, rect: %ld, offset(%ld, %ld)\n", i, j, xOffset, yOffset); if (void* rectCopy = rectList.ItemAt(i)) free(rectCopy); } -//printf("CopyRegionList(): %lld\n", system_time() - now); fGraphicsCard->Invalidate(updateRect); @@ -549,9 +548,9 @@ DisplayDriverPainter::FillRect(const BRect &r, const RGBColor &color) if (Lock()) { fPainter->SetHighColor(color); - fPainter->FillRect(r); + BRect touched = fPainter->FillRect(r); - fGraphicsCard->Invalidate(r); + fGraphicsCard->Invalidate(touched); Unlock(); } @@ -564,9 +563,9 @@ DisplayDriverPainter::FillRect(const BRect &r, const DrawData *d) if (Lock()) { fPainter->SetDrawData(d); - fPainter->FillRect(r); + BRect touched = fPainter->FillRect(r); - fGraphicsCard->Invalidate(r); + fGraphicsCard->Invalidate(touched); Unlock(); } @@ -706,10 +705,17 @@ DisplayDriverPainter::StrokeEllipse(const BRect &r, const DrawData *d) void DisplayDriverPainter::StrokeLine(const BPoint &start, const BPoint &end, const RGBColor &color) { - DrawData d; - d.highcolor = color; - d.draw_mode = B_OP_COPY; - StrokeLine(start, end, &d); + if (Lock()) { + if (!fPainter->StraightLine(start, end, color.GetColor32())) { + DrawData d; + d.highcolor = color; + d.draw_mode = B_OP_COPY; + StrokeLine(start, end, &d); + } else { + fGraphicsCard->Invalidate(fPainter->ClipRect(BRect(start, end))); + } + Unlock(); + } } // StrokeLine @@ -719,10 +725,9 @@ DisplayDriverPainter::StrokeLine(const BPoint &start, const BPoint &end, const D if (Lock()) { fPainter->SetDrawData(d); - fPainter->StrokeLine(start, end); + BRect touched = fPainter->StrokeLine(start, end); - BRect r(start, end); - fGraphicsCard->Invalidate(r); + fGraphicsCard->Invalidate(touched); Unlock(); } @@ -768,7 +773,6 @@ void DisplayDriverPainter::StrokeRect(const BRect &r, const RGBColor &color) { if (Lock()) { - fPainter->StrokeRect(r, color.GetColor32()); fGraphicsCard->Invalidate(BRect(r.left, r.top, r.right, r.top)); @@ -787,9 +791,9 @@ DisplayDriverPainter::StrokeRect(const BRect &r, const DrawData *d) if (Lock()) { fPainter->SetDrawData(d); - fPainter->StrokeRect(r); + BRect touched = fPainter->StrokeRect(r); - fGraphicsCard->Invalidate(r); + fGraphicsCard->Invalidate(touched); Unlock(); } @@ -803,13 +807,11 @@ DisplayDriverPainter::StrokeRegion(BRegion& r, const DrawData *d) fPainter->SetDrawData(d); - BRect invalid = r.RectAt(0); - fPainter->StrokeRect(invalid); + BRect invalid = fPainter->StrokeRect(r.RectAt(0)); int32 count = r.CountRects(); for (int32 i = 1; i < count; i++) { - fPainter->StrokeRect(r.RectAt(i)); - invalid = invalid | r.RectAt(i); + invalid = invalid | fPainter->StrokeRect(r.RectAt(i)); } fGraphicsCard->Invalidate(invalid); @@ -885,6 +887,7 @@ DisplayDriverPainter::DrawString(const char *string, const int32 &length, const BPoint &pt, DrawData *d) { if (Lock()) { + fPainter->SetDrawData(d); BRect boundingBox = fPainter->DrawString(string, length, pt); diff --git a/src/servers/app/drawing/Painter/Painter.cpp b/src/servers/app/drawing/Painter/Painter.cpp index d1e592e509..a223f02524 100644 --- a/src/servers/app/drawing/Painter/Painter.cpp +++ b/src/servers/app/drawing/Painter/Painter.cpp @@ -4,9 +4,11 @@ #include #include +#include #include #include +#include #include #include #include @@ -199,17 +201,21 @@ Painter::SetLowColor(const rgb_color& color) void Painter::SetScale(float scale) { - fScale = scale; - _RebuildClipping(); - _UpdateLineWidth(); + if (fScale != scale) { + fScale = scale; + _RebuildClipping(); + _UpdateLineWidth(); + } } // SetPenSize void Painter::SetPenSize(float size) { - fPenSize = size; - _UpdateLineWidth(); + if (fPenSize != size) { + fPenSize = size; + _UpdateLineWidth(); + } } // SetOrigin @@ -245,6 +251,8 @@ void Painter::SetBlendingMode(source_alpha alphaSrcMode, alpha_function alphaFncMode) { if (fAlphaSrcMode != alphaSrcMode || fAlphaFncMode != alphaFncMode) { + fAlphaSrcMode = alphaSrcMode; + fAlphaFncMode = alphaFncMode; if (fDrawingMode == B_OP_ALPHA && fPixelFormat) { fPixelFormat->set_drawing_mode(DrawingModeFactory::DrawingModeFor(fDrawingMode, fAlphaSrcMode, @@ -284,12 +292,14 @@ Painter::SetFont(const ServerFont& font) // #pragma mark - // StrokeLine -void +BRect Painter::StrokeLine(BPoint a, BPoint b, const pattern& p) { _Transform(&a); _Transform(&b); + BRect touched(a, b); + // first, try an optimized version float penSize = _Transform(fPenSize); if (penSize == 1.0 && @@ -298,30 +308,31 @@ Painter::StrokeLine(BPoint a, BPoint b, const pattern& p) if (pat == B_SOLID_HIGH && StraightLine(a, b, fPatternHandler->HighColor().GetColor32())) { SetPenLocation(b); - return; + return _Clipped(touched); } else if (pat == B_SOLID_LOW && StraightLine(a, b, fPatternHandler->LowColor().GetColor32())) { SetPenLocation(b); - return; + return _Clipped(touched); } } - agg::path_storage path; path.move_to(a.x, a.y); path.line_to(b.x, b.y); - _StrokePath(path, p); + touched = _StrokePath(path, p); SetPenLocation(b); + + return _Clipped(touched); } // StrokeLine -void +BRect Painter::StrokeLine(BPoint b, const pattern& p) { // TODO: move this function elsewhere - StrokeLine(fPenLocation, b); + return StrokeLine(fPenLocation, b); } // StraightLine @@ -486,7 +497,7 @@ Painter::FillShape(/*const */BShape* shape, const pattern& p) const } // StrokeRect -void +BRect Painter::StrokeRect(const BRect& r, const pattern& p) const { BPoint a(r.left, r.top); @@ -501,13 +512,15 @@ Painter::StrokeRect(const BRect& r, const pattern& p) const // TODO: fix me // pattern p = *fPatternHandler->GetR5Pattern(); if (p == B_SOLID_HIGH) { - StrokeRect(BRect(a, b), + BRect rect(a, b); + StrokeRect(rect, fPatternHandler->HighColor().GetColor32()); - return; + return _Clipped(rect); } else if (p == B_SOLID_LOW) { - StrokeRect(BRect(a, b), + BRect rect(a, b); + StrokeRect(rect, fPatternHandler->LowColor().GetColor32()); - return; + return _Clipped(rect); } } @@ -518,7 +531,7 @@ Painter::StrokeRect(const BRect& r, const pattern& p) const path.line_to(a.x, b.y); path.close_polygon(); - _StrokePath(path, p); + return _StrokePath(path, p); } // StrokeRect @@ -536,7 +549,7 @@ Painter::StrokeRect(const BRect& r, const rgb_color& c) const } // FillRect -void +BRect Painter::FillRect(const BRect& r, const pattern& p) const { BPoint a(r.left, r.top); @@ -548,11 +561,13 @@ Painter::FillRect(const BRect& r, const pattern& p) const if (fDrawingMode == B_OP_COPY || fDrawingMode == B_OP_OVER) { pattern pat = *fPatternHandler->GetR5Pattern(); if (pat == B_SOLID_HIGH) { - FillRect(BRect(a, b), fPatternHandler->HighColor().GetColor32()); - return; + BRect rect(a, b); + FillRect(rect, fPatternHandler->HighColor().GetColor32()); + return _Clipped(rect); } else if (pat == B_SOLID_LOW) { - FillRect(BRect(a, b), fPatternHandler->LowColor().GetColor32()); - return; + BRect rect(a, b); + FillRect(rect, fPatternHandler->LowColor().GetColor32()); + return _Clipped(rect); } } @@ -569,7 +584,7 @@ Painter::FillRect(const BRect& r, const pattern& p) const path.line_to(a.x, b.y); path.close_polygon(); - _FillPath(path, p); + return _FillPath(path, p); } // FillRect @@ -770,12 +785,18 @@ Painter::DrawString(const char* utf8String, uint32 length, transform.TranslateBy(baseLine); transform.ScaleBy(B_ORIGIN, fScale, fScale); transform.TranslateBy(fOrigin); - + + BRect clippingFrame; + if (fClippingRegion) + clippingFrame = _Transform(fClippingRegion->Frame()); + bounds = fTextRenderer->RenderString(utf8String, length, fFontRendererSolid, fFontRendererBin, - transform, false, + transform, + clippingFrame, + false, &fPenLocation); // pen location is not transformed in quite the same way, // or transformations would add up @@ -784,9 +805,7 @@ Painter::DrawString(const char* utf8String, uint32 length, transform.TranslateBy(baseLine); transform.Transform(&fPenLocation); } - if (bounds.IsValid() && fClippingRegion) - bounds = bounds & _Transform(fClippingRegion->Frame()); - return bounds; + return _Clipped(bounds); } // DrawString @@ -885,11 +904,12 @@ Painter::BoundingBox(const char* utf8String, uint32 length, Transformable transform; transform.TranslateBy(baseLine); + BRect dummy; return fTextRenderer->RenderString(utf8String, length, fFontRendererSolid, fFontRendererBin, - transform, true); + transform, dummy, true); } // #pragma mark - @@ -1008,6 +1028,17 @@ Painter::_Transform(const BRect& rect) const return ret; } +// _Clipped +BRect +Painter::_Clipped(const BRect& rect) const +{ + if (rect.IsValid() && fClippingRegion) + return rect & _Transform(fClippingRegion->Frame()); + return rect; +} + +// #pragma mark - + // _RebuildClipping void Painter::_RebuildClipping() @@ -1320,9 +1351,24 @@ Painter::_InvertRect32(BRect r) const // #pragma mark - +template +BRect +Painter::_BoundingBox(VertexSource& path) const +{ + double left = 0.0; + double top = 0.0; + double right = -1.0; + double bottom = -1.0; + uint32 pathID[1]; + pathID[0] = 0; + agg::bounding_rect(path, pathID, 0, 1, &left, &top, &right, &bottom); + return BRect(left, top, right, bottom); +} + + // _StrokePath template -void +BRect Painter::_StrokePath(VertexSource& path, const pattern& p) const { // We're now used by app_server and SetDrawData() was called prior to @@ -1345,11 +1391,13 @@ Painter::_StrokePath(VertexSource& path, const pattern& p) const #else fOutlineRasterizer->add_path(path); #endif + + return _Clipped(_BoundingBox(path)); } // _FillPath template -void +BRect Painter::_FillPath(VertexSource& path, const pattern& p) const { // We're now used by app_server and SetDrawData() was called prior to @@ -1359,24 +1407,25 @@ Painter::_FillPath(VertexSource& path, const pattern& p) const fRasterizer->add_path(path); agg::render_scanlines(*fRasterizer, *fScanline, *fRenderer); + + return _Clipped(_BoundingBox(path)); } // _SetPattern void Painter::_SetPattern(const pattern& p) const { - if (memcmp(&p, fPatternHandler->GetR5Pattern(), sizeof(pattern)) != 0) { -// if ((uint64)p != (uint64)*fPatternHandler->GetR5Pattern()) { + if (!(p == *fPatternHandler->GetR5Pattern())) { printf("Painter::_SetPattern()\n"); fPatternHandler->SetPattern(p); DrawingMode* mode = NULL; - if (memcmp(&p, &B_SOLID_HIGH, sizeof(pattern)) == 0) { + if (p == B_SOLID_HIGH) { _SetRendererColor(fPatternHandler->HighColor().GetColor32()); mode = DrawingModeFactory::DrawingModeFor(fDrawingMode, fAlphaSrcMode, fAlphaFncMode, true); - } else if (memcmp(&p, &B_SOLID_LOW, sizeof(pattern)) == 0) { + } else if (p == B_SOLID_LOW) { _SetRendererColor(fPatternHandler->LowColor().GetColor32()); mode = DrawingModeFactory::DrawingModeFor(fDrawingMode, fAlphaSrcMode, diff --git a/src/servers/app/drawing/Painter/font_support/AGGTextRenderer.cpp b/src/servers/app/drawing/Painter/font_support/AGGTextRenderer.cpp index 77b0c968de..7c7b3dc4d7 100644 --- a/src/servers/app/drawing/Painter/font_support/AGGTextRenderer.cpp +++ b/src/servers/app/drawing/Painter/font_support/AGGTextRenderer.cpp @@ -113,8 +113,8 @@ AGGTextRenderer::Archive(BMessage* into, bool deep) const bool AGGTextRenderer::SetFont(const ServerFont &font) { -// if (fFontEngine.load_font(font, agg::glyph_ren_native_gray8)) { - if (fFontEngine.load_font(font, agg::glyph_ren_outline)) { + if (fFontEngine.load_font(font, agg::glyph_ren_native_gray8)) { +// if (fFontEngine.load_font(font, agg::glyph_ren_outline)) { return TextRenderer::SetFont(font); } else { fprintf(stderr, "font could not be loaded\n"); @@ -189,10 +189,11 @@ AGGTextRenderer::RenderString(const char* string, font_renderer_solid_type* solidRenderer, font_renderer_bin_type* binRenderer, const Transformable& transform, + BRect clippingFrame, bool dryRun, BPoint* nextCharPos) { - fFontEngine.hinting(fHinted); + fFontEngine.hinting(false); fFontEngine.height((int32)(fPtSize)); fFontEngine.width((int32)(fPtSize)); @@ -237,6 +238,10 @@ AGGTextRenderer::RenderString(const char* string, double advanceX = 0.0; double advanceY = 0.0; + // for when we bypass the transformation pipeline + BPoint transformOffset(0.0, 0.0); + transform.Transform(&transformOffset); + for (int32 i = 0; i < dstLength / 2; i++) { // line break @@ -264,75 +269,68 @@ AGGTextRenderer::RenderString(const char* string, x += (fAdvanceScale - 1.0) * fFontEngine.height(); y += advanceY; - fFontManager.init_embedded_adaptors(glyph, x, y); + // calculate bounds + const agg::rect& r = glyph->bounds; + BRect glyphBounds(r.x1 + x, r.y1 + y, r.x2 + x, r.y2 + y); - double left = 0.0; - double top = 0.0; - double right = -1.0; - double bottom = -1.0; - uint32 pathID[1]; - pathID[0] = 0; + // init the fontmanager and transform glyph bounds + if (glyph->data_type != agg::glyph_data_outline) { + // we cannot use the transformation pipeline + double transformedX = x + transformOffset.x; + double transformedY = y + transformOffset.y; + fFontManager.init_embedded_adaptors(glyph, + transformedX, + transformedY); + glyphBounds.OffsetBy(transformOffset); + } else { + fFontManager.init_embedded_adaptors(glyph, x, y); + glyphBounds = transform.TransformBounds(glyphBounds); + } - const agg::rect& r = fFontEngine.bounds(); - - switch(glyph->data_type) { - case agg::glyph_data_mono: - left = r.x1 + x; - right = r.x2 + x; - top = r.y1 + y; - bottom = r.y2 + y; - if (!dryRun) { + // render glyph and update touched area + if (!dryRun && clippingFrame.Intersects(glyphBounds)) { + switch(glyph->data_type) { + case agg::glyph_data_mono: agg::render_scanlines(fFontManager.mono_adaptor(), fFontManager.mono_scanline(), *binRenderer); - } - break; - - case agg::glyph_data_gray8: - left = r.x1 + x; - right = r.x2 + x; - top = r.y1 + y; - bottom = r.y2 + y; - if (!dryRun) { + break; + + case agg::glyph_data_gray8: agg::render_scanlines(fFontManager.gray8_adaptor(), fFontManager.gray8_scanline(), *solidRenderer); - } - break; - - case agg::glyph_data_outline: - ras.reset(); - if(fabs(0.0) <= 0.01) { + break; + + case agg::glyph_data_outline: + ras.reset(); + // NOTE: this function can be easily extended to handle + // conversion to contours, to that's why there is a lot of + // commented out code, I leave here because I think it + // will be needed again. + + // if(fabs(0.0) <= 0.01) { // For the sake of efficiency skip the // contour converter if the weight is about zero. //----------------------- - agg::bounding_rect(ftrans, pathID, 0, 1, - &left, &top, &right, &bottom); - if (!dryRun) // ras.add_path(fCurves); ras.add_path(ftrans); - } else { - if (!dryRun) + /* } else { // ras.add_path(fContour); ras.add_path(ftrans); - agg::bounding_rect(ftrans, pathID, 0, 1, - &left, &top, &right, &bottom); - } - if (!dryRun) { + }*/ if (fAntialias) { agg::render_scanlines(ras, sl, *solidRenderer); } else { agg::render_scanlines(ras, sl, *binRenderer); } - } - break; - default: - break; + break; + default: + break; + } } - // calculate bounds - BRect t(left, top, right, bottom); - if (t.IsValid()) - bounds = bounds.IsValid() ? bounds | t : t; + if (glyphBounds.IsValid()) + bounds = bounds.IsValid() ? bounds | glyphBounds : glyphBounds; // increment pen position advanceX = fHinted ? floorf(glyph->advance_x + 0.5) : glyph->advance_x; diff --git a/src/servers/app/drawing/Painter/font_support/AGGTextRenderer.h b/src/servers/app/drawing/Painter/font_support/AGGTextRenderer.h index 98c3867c47..b7ca5cc3fe 100644 --- a/src/servers/app/drawing/Painter/font_support/AGGTextRenderer.h +++ b/src/servers/app/drawing/Painter/font_support/AGGTextRenderer.h @@ -36,6 +36,7 @@ class AGGTextRenderer : public TextRenderer { font_renderer_solid_type* solidRenderer, font_renderer_bin_type* binRenderer, const Transformable& transform, + BRect clippingFrame, bool dryRun = false, BPoint* nextCharPos = NULL);