* 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
This commit is contained in:
parent
94a48ae276
commit
c9d2046fe5
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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<FontCacheEntry::ContourConverter, Transformable>
|
||||
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());
|
||||
}
|
||||
|
@ -1,10 +1,11 @@
|
||||
/*
|
||||
* Copyright 2005-2006, Stephan Aßmus <superstippi@gmx.de>. All rights reserved.
|
||||
* Copyright 2005-2007, Stephan Aßmus <superstippi@gmx.de>. 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 <agg_scanline_u.h>
|
||||
|
||||
|
||||
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
|
||||
|
@ -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)
|
||||
|
@ -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<agg::path_storage> 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
|
||||
|
Loading…
Reference in New Issue
Block a user