From c9d2046fe5b12fee15b6c24960d29fd581a81cef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20A=C3=9Fmus?= Date: Sat, 4 Aug 2007 11:37:16 +0000 Subject: [PATCH] * after my last changes to font rendering, it was about 15% slower than before (although there should be much less lock contention) * with this change, there is quite a bit of cleanup, text drawing is now about 20% faster than before the original changes to font caching, mostly due to turning off the kerning feature, which at the moment gives absolutely no benefit. The correct way of doing it might be to use kerning depending on the provided glyph spacing mode * removed fPenLocation from Painter, the usage should be more correct now, since it is now consistently applied before the coordinate transformation from view to screen (also for DrawShape() now, before any view scaling and origin offset) * Painter no longer has it's own instance of a ServerFont, instead it uses its AGGTextRenderer instance, which was per Painter again after the last change, and not global anymore, made _UpdateFont() useless * When using GlyphLayoutEngine, it supports a second pass with the same FontCacheEntry through the introduction of a FontCacheReference. This speeds up DrawString a little, since it needs to calculate the bounding box for the string, and then draw the string in a second pass. This is now done with only one FontCacheEntry lookup * I also tried to optimize the on-the-fly conversion of UTF8->CharCode away, since it was done four times per DrawString, but surprisingly, it proofed to be a slight slowdown. * introduced a shortcut in DrawingEngine::DrawString() which avoids calculating the bounding box, we are now a tiny bit faster to figure out that we don't need to draw any string than Dano In the test environment (drawing to offscreen bitmap and blitting to screen eventually), text rendering is now about 3.7 times _faster_ than Dano text rendering (directly to screen), for untransformed text. Unfortunately I cannot test on the same machine in accelerant using version of the test environment. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21822 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/servers/app/FontCache.cpp | 5 +- src/servers/app/FontCacheEntry.cpp | 5 +- src/servers/app/GlyphLayoutEngine.h | 97 ++++++++++++++----- src/servers/app/ProfileMessageSupport.cpp | 1 + src/servers/app/drawing/DrawingEngine.cpp | 38 ++++---- .../app/drawing/Painter/AGGTextRenderer.cpp | 38 +++----- .../app/drawing/Painter/AGGTextRenderer.h | 24 +++-- src/servers/app/drawing/Painter/Painter.cpp | 70 +++++-------- src/servers/app/drawing/Painter/Painter.h | 15 ++- 9 files changed, 166 insertions(+), 127 deletions(-) diff --git a/src/servers/app/FontCache.cpp b/src/servers/app/FontCache.cpp index b4fda3b417..e810a9313c 100644 --- a/src/servers/app/FontCache.cpp +++ b/src/servers/app/FontCache.cpp @@ -48,7 +48,7 @@ FontCache::Default() return &sDefaultInstance; } -// SetFont +// FontCacheEntryFor FontCacheEntry* FontCache::FontCacheEntryFor(const ServerFont& font) { @@ -62,6 +62,7 @@ FontCache::FontCacheEntryFor(const ServerFont& font) if (entry) { // the entry was already there entry->AddReference(); +//printf("FontCacheEntryFor(%ld): %p\n", font.GetFamilyAndStyle(), entry); return entry; } @@ -91,6 +92,7 @@ FontCache::FontCacheEntryFor(const ServerFont& font) return NULL; } } +//printf("FontCacheEntryFor(%ld): %p (insert)\n", font.GetFamilyAndStyle(), entry); entry->AddReference(); return entry; @@ -100,6 +102,7 @@ FontCache::FontCacheEntryFor(const ServerFont& font) void FontCache::Recycle(FontCacheEntry* entry) { +//printf("Recycle(%p)\n", entry); entry->UpdateUsage(); entry->RemoveReference(); } diff --git a/src/servers/app/FontCacheEntry.cpp b/src/servers/app/FontCacheEntry.cpp index 785ba62d28..e2312b88a2 100644 --- a/src/servers/app/FontCacheEntry.cpp +++ b/src/servers/app/FontCacheEntry.cpp @@ -212,8 +212,11 @@ FontCacheEntry::GetKerning(uint16 glyphCode1, uint16 glyphCode2, FontCacheEntry::GenerateSignature(char* signature, const ServerFont& font) { glyph_rendering renderingType = glyph_ren_native_gray8; - if (font.Rotation() != 0.0 || font.Shear() != 90.0) + if (font.Rotation() != 0.0 || font.Shear() != 90.0 + || font.Flags() & B_DISABLE_ANTIALIASING + || font.Size() > 30) { renderingType = glyph_ren_outline; + } // TODO: read more of these from the font FT_Encoding charMap = FT_ENCODING_NONE; diff --git a/src/servers/app/GlyphLayoutEngine.h b/src/servers/app/GlyphLayoutEngine.h index 76c7343e64..36ddfe23e5 100644 --- a/src/servers/app/GlyphLayoutEngine.h +++ b/src/servers/app/GlyphLayoutEngine.h @@ -16,6 +16,42 @@ #include "ServerFont.h" +class FontCacheReference { + public: + FontCacheReference() + : fCacheEntry(NULL) + , fWriteLocked(false) + { + } + ~FontCacheReference() + { + if (fCacheEntry) { + if (fWriteLocked) + fCacheEntry->WriteUnlock(); + else + fCacheEntry->ReadUnlock(); + + FontCache::Default()->Recycle( + fCacheEntry); + } + } + void SetTo(FontCacheEntry* entry, + bool writeLocked) + { + fCacheEntry = entry; + fWriteLocked = writeLocked; + } + inline FontCacheEntry* Entry() const + { return fCacheEntry; } + inline bool WriteLocked() const + { return fWriteLocked; } + + private: + FontCacheEntry* fCacheEntry; + bool fWriteLocked; +}; + + class GlyphLayoutEngine { public: @@ -26,7 +62,8 @@ class GlyphLayoutEngine { int32 length, const escapement_delta* delta = NULL, bool kerning = true, - uint8 spacing = B_BITMAP_SPACING); + uint8 spacing = B_BITMAP_SPACING, + FontCacheReference* cacheReference = NULL); static bool IsWhiteSpace(uint32 glyphCode); @@ -62,27 +99,37 @@ inline bool GlyphLayoutEngine::LayoutGlyphs(GlyphConsumer& consumer, const ServerFont& font, const char* utf8String, int32 length, - const escapement_delta* delta, bool kerning, uint8 spacing) + const escapement_delta* delta, bool kerning, uint8 spacing, + FontCacheReference* cacheReference) { // TODO: implement spacing modes - FontCache* cache = FontCache::Default(); - FontCacheEntry* entry = cache->FontCacheEntryFor(font); - if (!entry || !entry->ReadLock()) { - cache->Recycle(entry); - return false; + FontCacheEntry* entry = NULL; + bool needsWriteLock = false; + if (cacheReference) { + entry = cacheReference->Entry(); + needsWriteLock = cacheReference->WriteLocked(); } - bool needsWriteLock - = !entry->HasGlyphs(utf8String, length); - - if (needsWriteLock) { - entry->ReadUnlock(); - if (!entry->WriteLock()) { + if (!entry) { + FontCache* cache = FontCache::Default(); + entry = cache->FontCacheEntryFor(font); + + if (!entry || !entry->ReadLock()) { cache->Recycle(entry); return false; } - } + + needsWriteLock = !entry->HasGlyphs(utf8String, length); + + if (needsWriteLock) { + entry->ReadUnlock(); + if (!entry->WriteLock()) { + cache->Recycle(entry); + return false; + } + } + } // else the entry was already used and is still locked consumer.Start(); @@ -107,8 +154,8 @@ GlyphLayoutEngine::LayoutGlyphs(GlyphConsumer& consumer, continue; } - if (kerning) - entry->GetKerning(lastCharCode, charCode, &advanceX, &advanceY); +// if (kerning) +// entry->GetKerning(lastCharCode, charCode, &advanceX, &advanceY); x += advanceX; y += advanceY; @@ -133,12 +180,18 @@ GlyphLayoutEngine::LayoutGlyphs(GlyphConsumer& consumer, y += advanceY; consumer.Finish(x, y); - if (needsWriteLock) - entry->WriteUnlock(); - else - entry->ReadUnlock(); - - cache->Recycle(entry); + if (!cacheReference) { + if (needsWriteLock) + entry->WriteUnlock(); + else + entry->ReadUnlock(); + + FontCache::Default()->Recycle(entry); + } else { + // the reference will take care of locking + if (!cacheReference->Entry()) + cacheReference->SetTo(entry, needsWriteLock); + } return true; } diff --git a/src/servers/app/ProfileMessageSupport.cpp b/src/servers/app/ProfileMessageSupport.cpp index 33f42f18cc..a18d7914df 100644 --- a/src/servers/app/ProfileMessageSupport.cpp +++ b/src/servers/app/ProfileMessageSupport.cpp @@ -201,6 +201,7 @@ string_for_message_code(uint32 code, BString& string) case AS_FILL_TRIANGLE: string = "AS_FILL_TRIANGLE"; break; case AS_DRAW_STRING: string = "AS_DRAW_STRING"; break; + case AS_DRAW_STRING_WITH_DELTA: string = "AS_DRAW_STRING_WITH_DELTA"; break; case AS_SYNC: string = "AS_SYNC"; break; diff --git a/src/servers/app/drawing/DrawingEngine.cpp b/src/servers/app/drawing/DrawingEngine.cpp index d8aa7c3b04..0de23a54ab 100644 --- a/src/servers/app/drawing/DrawingEngine.cpp +++ b/src/servers/app/drawing/DrawingEngine.cpp @@ -185,7 +185,7 @@ DrawingEngine::ConstrainClippingRegion(const BRegion* region) void DrawingEngine::SetDrawState(const DrawState* state, int32 xOffset, int32 yOffset) { - fPainter->SetDrawState(state, true, xOffset, yOffset); + fPainter->SetDrawState(state, xOffset, yOffset); } @@ -665,18 +665,12 @@ DrawingEngine::StrokeLine(const BPoint &start, const BPoint &end, bool cursorTouched = fGraphicsCard->HideSoftwareCursor(touched); if (!fPainter->StraightLine(start, end, color.GetColor32())) { - // TODO: all this is quite expensive, but it is currently - // used only for the "gradient" decorator tab buttons - rgb_color previousColor = fPainter->HighColor(); - drawing_mode previousMode = fPainter->DrawingMode(); fPainter->SetHighColor(color); fPainter->SetDrawingMode(B_OP_OVER); fPainter->StrokeLine(start, end); - fPainter->SetHighColor(previousColor); - fPainter->SetDrawingMode(previousMode); - } else { - fGraphicsCard->Invalidate(touched); } + + fGraphicsCard->Invalidate(touched); if (cursorTouched) fGraphicsCard->ShowSoftwareCursor(); } @@ -742,17 +736,12 @@ DrawingEngine::FillRegion(BRegion& r, const RGBColor& color) BRect frame = r.Frame(); bool cursorTouched = fGraphicsCard->HideSoftwareCursor(frame); - bool doInSoftware = true; // try hardware optimized version first if ((fAvailableHWAccleration & HW_ACC_FILL_REGION) != 0 && frame.Width() * frame.Height() > 100) { fGraphicsCard->FillRegion(r, color, fSuspendSyncLevel == 0 || cursorTouched); - doInSoftware = false; - } - - if (doInSoftware) { - + } else { int32 count = r.CountRects(); for (int32 i = 0; i < count; i++) { fPainter->FillRectNoClipping(r.RectAt(i), color.GetColor32()); @@ -1037,6 +1026,19 @@ DrawingEngine::DrawString(const char* string, int32 length, BPoint penLocation = pt; + // try a fast clipping path + float fontSize = fPainter->Font().Size(); + BRect clippingFrame = fPainter->ClippingRegion()->Frame(); + if (pt.x > clippingFrame.right || pt.y + fontSize < clippingFrame.top + || pt.y - fontSize > clippingFrame.bottom) { + penLocation.x += StringWidth(string, length, delta); + return penLocation; + } + + // use a FontCacheRefernece to speed up the second pass of + // drawing the string + FontCacheReference cacheReference; + //bigtime_t now = system_time(); // TODO: BoundingBox is quite slow!! Optimizing it will be beneficial. // Cursiously, the DrawString after it is actually faster!?! @@ -1045,7 +1047,8 @@ DrawingEngine::DrawString(const char* string, int32 length, // in case we don't have one. // TODO: Watch out about penLocation and use Painter::PenLocation() when // not using BoundindBox anymore. - BRect b = fPainter->BoundingBox(string, length, pt, &penLocation, delta); + BRect b = fPainter->BoundingBox(string, length, pt, &penLocation, delta, + &cacheReference); // stop here if we're supposed to render outside of the clipping b = fPainter->ClipRect(b); if (b.IsValid()) { @@ -1053,7 +1056,8 @@ DrawingEngine::DrawString(const char* string, int32 length, bool cursorTouched = fGraphicsCard->HideSoftwareCursor(b); //now = system_time(); - BRect touched = fPainter->DrawString(string, length, pt, delta); + BRect touched = fPainter->DrawString(string, length, pt, delta, + &cacheReference); //printf("drawing string: %lld µs\n", system_time() - now); fGraphicsCard->Invalidate(touched); diff --git a/src/servers/app/drawing/Painter/AGGTextRenderer.cpp b/src/servers/app/drawing/Painter/AGGTextRenderer.cpp index 45f8b1020c..ab082d5240 100644 --- a/src/servers/app/drawing/Painter/AGGTextRenderer.cpp +++ b/src/servers/app/drawing/Painter/AGGTextRenderer.cpp @@ -29,7 +29,8 @@ // constructor -AGGTextRenderer::AGGTextRenderer() +AGGTextRenderer::AGGTextRenderer(renderer_type& solidRenderer, + renderer_bin_type& binRenderer, scanline_unpacked_type& scanline) : fPathAdaptor() , fGray8Adaptor() , fGray8Scanline() @@ -39,6 +40,11 @@ AGGTextRenderer::AGGTextRenderer() , fCurves(fPathAdaptor) , fContour(fCurves) + , fSolidRenderer(solidRenderer) + , fBinRenderer(binRenderer) + , fScanline(scanline) + , fRasterizer() + , fHinted(true) , fAntialias(true) , fKerning(true) @@ -101,9 +107,6 @@ typedef agg::conv_transform class AGGTextRenderer::StringRenderer { public: StringRenderer(const IntRect& clippingFrame, bool dryRun, - renderer_type& solidRenderer, - renderer_bin_type& binRenderer, - scanline_unpacked_type& scanline, FontCacheEntry::TransformedOutline& transformedGlyph, FontCacheEntry::TransformedContourOutline& transformedContour, const Transformable& transform, @@ -119,10 +122,6 @@ class AGGTextRenderer::StringRenderer { , fNextCharPos(nextCharPos) , fVector(false) - , fSolidRenderer(solidRenderer) - , fBinRenderer(binRenderer) - , fScanline(scanline) - , fTransformedGlyph(transformedGlyph) , fTransformedContour(transformedContour) @@ -137,8 +136,8 @@ class AGGTextRenderer::StringRenderer { void Finish(double x, double y) { if (fVector) { - agg::render_scanlines(fRenderer.fRasterizer, fScanline, - fSolidRenderer); + agg::render_scanlines(fRenderer.fRasterizer, fRenderer.fScanline, + fRenderer.fSolidRenderer); } if (fNextCharPos) { @@ -157,7 +156,8 @@ class AGGTextRenderer::StringRenderer { { // "glyphBounds" is the bounds of the glyph transformed // by the x y location of the glyph along the base line, - // it is therefor yet "untransformed". + // it is therefor yet "untransformed" in case there is an + // embedded transformation. const agg::rect_i& r = glyph->bounds; IntRect glyphBounds(r.x1 + x, r.y1 + y - 1, r.x2 + x + 1, r.y2 + y + 1); @@ -211,12 +211,12 @@ class AGGTextRenderer::StringRenderer { switch (glyph->data_type) { case glyph_data_mono: agg::render_scanlines(fRenderer.fMonoAdaptor, - fRenderer.fMonoScanline, fBinRenderer); + fRenderer.fMonoScanline, fRenderer.fBinRenderer); break; case glyph_data_gray8: agg::render_scanlines(fRenderer.fGray8Adaptor, - fRenderer.fGray8Scanline, fSolidRenderer); + fRenderer.fGray8Scanline, fRenderer.fSolidRenderer); break; case glyph_data_outline: { @@ -262,9 +262,6 @@ class AGGTextRenderer::StringRenderer { BPoint* fNextCharPos; bool fVector; - renderer_type& fSolidRenderer; - renderer_bin_type& fBinRenderer; - scanline_unpacked_type& fScanline; FontCacheEntry::TransformedOutline& fTransformedGlyph; FontCacheEntry::TransformedContourOutline& fTransformedContour; AGGTextRenderer& fRenderer; @@ -274,14 +271,12 @@ class AGGTextRenderer::StringRenderer { BRect AGGTextRenderer::RenderString(const char* string, uint32 length, - renderer_type* solidRenderer, - renderer_bin_type* binRenderer, - scanline_unpacked_type& scanline, const BPoint& baseLine, const BRect& clippingFrame, bool dryRun, BPoint* nextCharPos, - const escapement_delta* delta) + const escapement_delta* delta, + FontCacheReference* cacheReference) { //printf("RenderString(\"%s\", length: %ld, dry: %d)\n", string, length, dryRun); @@ -303,12 +298,11 @@ AGGTextRenderer::RenderString(const char* string, transform.Transform(&transformOffset); StringRenderer renderer(clippingFrame, dryRun, - *solidRenderer, *binRenderer, scanline, transformedOutline, transformedContourOutline, transform, transformOffset, nextCharPos, *this); GlyphLayoutEngine::LayoutGlyphs(renderer, fFont, string, length, delta, - fKerning, B_BITMAP_SPACING); + fKerning, B_BITMAP_SPACING, cacheReference); return transform.TransformBounds(renderer.Bounds()); } diff --git a/src/servers/app/drawing/Painter/AGGTextRenderer.h b/src/servers/app/drawing/Painter/AGGTextRenderer.h index 0bcc8466c1..9726e4ff12 100644 --- a/src/servers/app/drawing/Painter/AGGTextRenderer.h +++ b/src/servers/app/drawing/Painter/AGGTextRenderer.h @@ -1,10 +1,11 @@ /* - * Copyright 2005-2006, Stephan Aßmus . All rights reserved. + * Copyright 2005-2007, Stephan Aßmus . All rights reserved. * Distributed under the terms of the MIT License. */ #ifndef AGG_TEXT_RENDERER_H #define AGG_TEXT_RENDERER_H + #include "defines.h" #include "FontCacheEntry.h" @@ -16,12 +17,18 @@ #include +class FontCacheReference; + class AGGTextRenderer { public: - AGGTextRenderer(); + AGGTextRenderer(renderer_type& solidRenderer, + renderer_bin_type& binRenderer, + scanline_unpacked_type& scanline); virtual ~AGGTextRenderer(); void SetFont(const ServerFont &font); + inline const ServerFont& Font() const + { return fFont; } void SetHinting(bool hinting); bool Hinting() const @@ -37,14 +44,12 @@ class AGGTextRenderer { BRect RenderString(const char* utf8String, uint32 length, - renderer_type* solidRenderer, - renderer_bin_type* binRenderer, - scanline_unpacked_type& scanline, const BPoint& baseLine, const BRect& clippingFrame, - bool dryRun = false, - BPoint* nextCharPos = NULL, - const escapement_delta* delta = NULL); + bool dryRun, + BPoint* nextCharPos, + const escapement_delta* delta, + FontCacheReference* cacheReference); private: @@ -61,6 +66,9 @@ class AGGTextRenderer { FontCacheEntry::CurveConverter fCurves; FontCacheEntry::ContourConverter fContour; + renderer_type& fSolidRenderer; + renderer_bin_type& fBinRenderer; + scanline_unpacked_type& fScanline; rasterizer_type fRasterizer; // NOTE: the object has it's own rasterizer object // since it might be using a different gamma setting diff --git a/src/servers/app/drawing/Painter/Painter.cpp b/src/servers/app/drawing/Painter/Painter.cpp index 6cece22e34..3cd41e3a6a 100644 --- a/src/servers/app/drawing/Painter/Painter.cpp +++ b/src/servers/app/drawing/Painter/Painter.cpp @@ -72,13 +72,12 @@ Painter::Painter() fDrawingText(false), fAlphaSrcMode(B_PIXEL_ALPHA), fAlphaFncMode(B_ALPHA_OVERLAY), - fPenLocation(0.0, 0.0), fLineCapMode(B_BUTT_CAP), fLineJoinMode(B_MITER_JOIN), fMiterLimit(B_DEFAULT_MITER_LIMIT), fPatternHandler(), - fTextRenderer() + fTextRenderer(fRenderer, fRendererBin, fUnpackedScanline) { fPixelFormat.SetDrawingMode(fDrawingMode, fAlphaSrcMode, fAlphaFncMode, false); @@ -122,21 +121,18 @@ Painter::DetachFromBuffer() // SetDrawState void -Painter::SetDrawState(const DrawState* data, bool updateFont, - int32 xOffset, int32 yOffset) +Painter::SetDrawState(const DrawState* data, int32 xOffset, int32 yOffset) { - // NOTE: The custom clipping in "data" is ignored, because it has already been - // taken into account elsewhere + // NOTE: The custom clipping in "data" is ignored, because it has already + // been taken into account elsewhere // TODO: optimize "context switch" for speed... // but for now... SetPenSize(data->PenSize()); - SetPenLocation(data->PenLocation()); - if (updateFont) - SetFont(data->Font()); - - fTextRenderer.SetAntialiasing(!(data->ForceFontAliasing() || data->Font().Flags() & B_DISABLE_ANTIALIASING)); + SetFont(data->Font()); + fTextRenderer.SetAntialiasing(!(data->ForceFontAliasing() + || data->Font().Flags() & B_DISABLE_ANTIALIASING)); fSubpixelPrecise = data->SubPixelPrecise(); @@ -259,18 +255,11 @@ Painter::SetPattern(const pattern& p, bool drawingText) } } -// SetPenLocation -void -Painter::SetPenLocation(const BPoint& location) -{ - fPenLocation = location; -} - // SetFont void Painter::SetFont(const ServerFont& font) { - fFont = font; + fTextRenderer.SetFont(font); } // #pragma mark - drawing @@ -524,14 +513,14 @@ Painter::DrawShape(const int32& opCount, const uint32* opList, for (int32 i = 0; i < opCount; i++) { uint32 op = opList[i] & 0xFF000000; if (op & OP_MOVETO) { - fPath.move_to(points->x + fPenLocation.x, points->y + fPenLocation.y); + fPath.move_to(points->x, points->y); points++; } if (op & OP_LINETO) { int32 count = opList[i] & 0x00FFFFFF; while (count--) { - fPath.line_to(points->x + fPenLocation.x, points->y + fPenLocation.y); + fPath.line_to(points->x, points->y); points++; } } @@ -539,9 +528,9 @@ Painter::DrawShape(const int32& opCount, const uint32* opList, if (op & OP_BEZIERTO) { int32 count = opList[i] & 0x00FFFFFF; while (count) { - fPath.curve4(points[0].x + fPenLocation.x, points[0].y + fPenLocation.y, - points[1].x + fPenLocation.x, points[1].y + fPenLocation.y, - points[2].x + fPenLocation.x, points[2].y + fPenLocation.y); + fPath.curve4(points[0].x, points[0].y, + points[1].x, points[1].y, + points[2].x, points[2].y); points += 3; count -= 3; } @@ -972,7 +961,8 @@ Painter::FillArc(BPoint center, float xRadius, float yRadius, // DrawString BRect Painter::DrawString(const char* utf8String, uint32 length, - BPoint baseLine, const escapement_delta* delta) + BPoint baseLine, const escapement_delta* delta, + FontCacheReference* cacheReference) { CHECK_CLIPPING @@ -987,14 +977,10 @@ Painter::DrawString(const char* utf8String, uint32 length, // make sure that the previous pattern is restored pattern oldPattern = *fPatternHandler.GetR5Pattern(); SetPattern(B_SOLID_HIGH, true); - // make sure the text renderer is using our font (the global - // instance of the text renderer is used by everyone) - _UpdateFont(); bounds = fTextRenderer.RenderString(utf8String, length, - &fRenderer, &fRendererBin, fUnpackedScanline, - baseLine, fClippingRegion->Frame(), false, - &fPenLocation, delta); + baseLine, fClippingRegion->Frame(), false, NULL, delta, + cacheReference); SetPattern(oldPattern); @@ -1005,21 +991,17 @@ Painter::DrawString(const char* utf8String, uint32 length, BRect Painter::BoundingBox(const char* utf8String, uint32 length, BPoint baseLine, BPoint* penLocation, - const escapement_delta* delta) const + const escapement_delta* delta, + FontCacheReference* cacheReference) const { if (!fSubpixelPrecise) { baseLine.x = roundf(baseLine.x); baseLine.y = roundf(baseLine.y); } - // make sure the text renderer is using our font (the global - // instance of the text renderer is used by everyone) - _UpdateFont(); - static BRect dummy; return fTextRenderer.RenderString(utf8String, length, - &fRenderer, &fRendererBin, fUnpackedScanline, - baseLine, dummy, true, penLocation, delta); + baseLine, dummy, true, penLocation, delta, cacheReference); } // StringWidth @@ -1027,7 +1009,7 @@ float Painter::StringWidth(const char* utf8String, uint32 length, const escapement_delta* delta) { - return fFont.StringWidth(utf8String, length, delta); + return Font().StringWidth(utf8String, length, delta); } // #pragma mark - @@ -1051,7 +1033,8 @@ Painter::DrawBitmap(const ServerBitmap* bitmap, bitmap->Height(), bitmap->BytesPerRow()); - _DrawBitmap(srcBuffer, bitmap->ColorSpace(), actualBitmapRect, bitmapRect, viewRect); + _DrawBitmap(srcBuffer, bitmap->ColorSpace(), actualBitmapRect, + bitmapRect, viewRect); } return touched; } @@ -1131,13 +1114,6 @@ Painter::_Clipped(const BRect& rect) const return BRect(rect); } -// _UpdateFont -void -Painter::_UpdateFont() const -{ - fTextRenderer.SetFont(fFont); -} - // _UpdateDrawingMode void Painter::_UpdateDrawingMode(bool drawingText) diff --git a/src/servers/app/drawing/Painter/Painter.h b/src/servers/app/drawing/Painter/Painter.h index fd69012e43..198cc2e8aa 100644 --- a/src/servers/app/drawing/Painter/Painter.h +++ b/src/servers/app/drawing/Painter/Painter.h @@ -27,6 +27,7 @@ class BBitmap; class BRegion; class DrawState; +class FontCacheReference; class RenderingBuffer; class ServerBitmap; class ServerFont; @@ -47,7 +48,6 @@ class Painter { { return fClippingRegion; } void SetDrawState(const DrawState* data, - bool updateFont = false, int32 xOffset = 0, int32 yOffset = 0); @@ -84,12 +84,9 @@ class Painter { void SetBlendingMode(source_alpha srcAlpha, alpha_function alphaFunc); - void SetPenLocation(const BPoint& location); - inline BPoint PenLocation() const - { return fPenLocation; } void SetFont(const ServerFont& font); inline const ServerFont& Font() const - { return fFont; } + { return fTextRenderer.Font(); } // painting functions @@ -178,13 +175,15 @@ class Painter { BRect DrawString( const char* utf8String, uint32 length, BPoint baseLine, - const escapement_delta* delta = NULL); + const escapement_delta* delta, + FontCacheReference* cacheReference = NULL); BRect BoundingBox( const char* utf8String, uint32 length, BPoint baseLine, BPoint* penLocation, - const escapement_delta* delta = NULL) const; + const escapement_delta* delta, + FontCacheReference* cacheReference = NULL) const; float StringWidth( const char* utf8String, uint32 length, @@ -278,14 +277,12 @@ mutable agg::conv_curve fCurve; bool fDrawingText; source_alpha fAlphaSrcMode; alpha_function fAlphaFncMode; - BPoint fPenLocation; cap_mode fLineCapMode; join_mode fLineJoinMode; float fMiterLimit; PatternHandler fPatternHandler; - ServerFont fFont; // a class handling rendering and caching of glyphs // it is setup to load from a specific Freetype supported // font file which it gets from ServerFont