Many efficiency improvements to text rendering. Moved stuff from Painter into AGGTextRenderer which didn't belong in Painter. AGGTextRenderer now has an embedded transformation, which expresses the font rotation and (in future) shear settings. Removed direct support for BBitmaps from Painter (supposed to draw ServerBitmaps). Tested drawing of bitmaps other than B_RGB32. (only B_CMAP8 and B_GRAY8 so far, but they work). Right now, these colorspaces are supported by on the fly conversion. So every colorspace supported by BBitmap::ImportBits() should work, which are a lot more than the R5 app_server can display.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@12815 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -193,11 +193,7 @@ class Painter {
|
|||||||
const escapement_delta* delta = NULL);
|
const escapement_delta* delta = NULL);
|
||||||
|
|
||||||
// bitmaps
|
// bitmaps
|
||||||
void DrawBitmap( const BBitmap* bitmap,
|
BRect DrawBitmap( const ServerBitmap* bitmap,
|
||||||
BRect bitmapRect,
|
|
||||||
BRect viewRect) const;
|
|
||||||
|
|
||||||
void DrawBitmap( const ServerBitmap* bitmap,
|
|
||||||
BRect bitmapRect,
|
BRect bitmapRect,
|
||||||
BRect viewRect) const;
|
BRect viewRect) const;
|
||||||
|
|
||||||
@@ -306,9 +302,6 @@ class Painter {
|
|||||||
// font file, it uses the FontManager to locate a file
|
// font file, it uses the FontManager to locate a file
|
||||||
// by Family and Style
|
// by Family and Style
|
||||||
AGGTextRenderer* fTextRenderer;
|
AGGTextRenderer* fTextRenderer;
|
||||||
uint32 fLastFamilyAndStyle;
|
|
||||||
float fLastRotation;
|
|
||||||
float fLastShear;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// SetHighColor
|
// SetHighColor
|
||||||
|
|||||||
@@ -104,6 +104,8 @@ Desktop::AddDriver(DisplayDriver *driver)
|
|||||||
if (driver->Initialize()) {
|
if (driver->Initialize()) {
|
||||||
// TODO: be careful of screen initialization - monitor may not support 640x480
|
// TODO: be careful of screen initialization - monitor may not support 640x480
|
||||||
Screen *sc = new Screen(driver, BPoint(640, 480), B_RGB32, fScreenList.CountItems()+1);
|
Screen *sc = new Screen(driver, BPoint(640, 480), B_RGB32, fScreenList.CountItems()+1);
|
||||||
|
|
||||||
|
// Screen *sc = new Screen(driver, BPoint(1400, 1050), B_RGB32, fScreenList.CountItems()+1);
|
||||||
// Screen *sc = new Screen(driver, BPoint(640, 480), B_CMAP8, fScreenList.CountItems()+1);
|
// Screen *sc = new Screen(driver, BPoint(640, 480), B_CMAP8, fScreenList.CountItems()+1);
|
||||||
// Screen *sc = new Screen(driver, BPoint(640, 480), B_GRAY8, fScreenList.CountItems()+1);
|
// Screen *sc = new Screen(driver, BPoint(640, 480), B_GRAY8, fScreenList.CountItems()+1);
|
||||||
// Screen *sc = new Screen(driver, BPoint(640, 480), B_RGB15, fScreenList.CountItems()+1);
|
// Screen *sc = new Screen(driver, BPoint(640, 480), B_RGB15, fScreenList.CountItems()+1);
|
||||||
|
|||||||
@@ -2020,7 +2020,6 @@ void ServerWindow::DispatchGraphicsMessage(int32 code, LinkMsgReader &link)
|
|||||||
case AS_DRAW_STRING:
|
case AS_DRAW_STRING:
|
||||||
{
|
{
|
||||||
DTRACE(("ServerWindow %s: Message AS_DRAW_STRING\n",fName));
|
DTRACE(("ServerWindow %s: Message AS_DRAW_STRING\n",fName));
|
||||||
|
|
||||||
char *string;
|
char *string;
|
||||||
int32 length;
|
int32 length;
|
||||||
BPoint location;
|
BPoint location;
|
||||||
@@ -2031,9 +2030,10 @@ void ServerWindow::DispatchGraphicsMessage(int32 code, LinkMsgReader &link)
|
|||||||
link.Read<escapement_delta>(&delta);
|
link.Read<escapement_delta>(&delta);
|
||||||
link.ReadString(&string);
|
link.ReadString(&string);
|
||||||
|
|
||||||
if(cl && cl->fLayerData)
|
if (cl && cl->fLayerData)
|
||||||
desktop->GetDisplayDriver()->DrawString(string,length,cl->ConvertToTop(location),
|
desktop->GetDisplayDriver()->DrawString(string, length,
|
||||||
cl->fLayerData);
|
cl->ConvertToTop(location),
|
||||||
|
cl->fLayerData);
|
||||||
|
|
||||||
free(string);
|
free(string);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -387,9 +387,9 @@ DisplayDriverPainter::DrawBitmap(ServerBitmap *bitmap,
|
|||||||
fGraphicsCard->HideSoftwareCursor(clipped);
|
fGraphicsCard->HideSoftwareCursor(clipped);
|
||||||
|
|
||||||
fPainter->SetDrawData(d);
|
fPainter->SetDrawData(d);
|
||||||
fPainter->DrawBitmap(bitmap, source, dest);
|
BRect touched = fPainter->DrawBitmap(bitmap, source, dest);
|
||||||
|
|
||||||
fGraphicsCard->Invalidate(clipped);
|
fGraphicsCard->Invalidate(touched);
|
||||||
fGraphicsCard->ShowSoftwareCursor();
|
fGraphicsCard->ShowSoftwareCursor();
|
||||||
|
|
||||||
Unlock();
|
Unlock();
|
||||||
@@ -969,7 +969,8 @@ DisplayDriverPainter::DrawString(const char *string, const int32 &length,
|
|||||||
{
|
{
|
||||||
static DrawData d;
|
static DrawData d;
|
||||||
d.SetHighColor(color);
|
d.SetHighColor(color);
|
||||||
|
|
||||||
|
// TODO: Why is escapement_delta a part of the state stack?
|
||||||
if (delta)
|
if (delta)
|
||||||
d.SetEscapementDelta(*delta);
|
d.SetEscapementDelta(*delta);
|
||||||
|
|
||||||
@@ -985,21 +986,23 @@ DisplayDriverPainter::DrawString(const char *string, const int32 &length,
|
|||||||
fPainter->SetDrawData(d);
|
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 DrawString after it is actually faster!?!
|
||||||
// TODO: make the availability of the hardware cursor part of the
|
// TODO: make the availability of the hardware cursor part of the
|
||||||
// HW acceleration flags and skip all calculations for HideSoftwareCursor
|
// HW acceleration flags and skip all calculations for HideSoftwareCursor
|
||||||
// in case we don't need one.
|
// in case we don't have one.
|
||||||
BRect b = fPainter->BoundingBox(string, length, pt);
|
BRect b = fPainter->BoundingBox(string, length, pt);
|
||||||
|
// stop here if we're supposed to render outside of the clipping
|
||||||
|
if (fPainter->ClippingRegion()->Frame().Intersects(b)) {
|
||||||
//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);
|
||||||
|
|
||||||
//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);
|
||||||
|
|
||||||
fGraphicsCard->Invalidate(touched);
|
fGraphicsCard->Invalidate(touched);
|
||||||
fGraphicsCard->ShowSoftwareCursor();
|
fGraphicsCard->ShowSoftwareCursor();
|
||||||
|
}
|
||||||
Unlock();
|
Unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,10 +80,7 @@ Painter::Painter()
|
|||||||
fPenLocation(0.0, 0.0),
|
fPenLocation(0.0, 0.0),
|
||||||
fDrawingModeFactory(new DrawingModeFactory()),
|
fDrawingModeFactory(new DrawingModeFactory()),
|
||||||
fPatternHandler(new PatternHandler()),
|
fPatternHandler(new PatternHandler()),
|
||||||
fTextRenderer(new AGGTextRenderer()),
|
fTextRenderer(new AGGTextRenderer())
|
||||||
fLastFamilyAndStyle(0),
|
|
||||||
fLastRotation(0.0),
|
|
||||||
fLastShear(90.0)
|
|
||||||
{
|
{
|
||||||
if (fontserver && fontserver->GetSystemPlain())
|
if (fontserver && fontserver->GetSystemPlain())
|
||||||
fFont = *fontserver->GetSystemPlain();
|
fFont = *fontserver->GetSystemPlain();
|
||||||
@@ -883,25 +880,14 @@ Painter::DrawString(const char* utf8String, uint32 length,
|
|||||||
|
|
||||||
if (fBuffer) {
|
if (fBuffer) {
|
||||||
|
|
||||||
Transformable transform;
|
|
||||||
// TODO: convert BFont::Shear(), which is in degrees 45°...135° to whatever AGG is using
|
|
||||||
// transform.ShearBy(B_ORIGIN, fFont.Shear(), 0.0);
|
|
||||||
transform.RotateBy(B_ORIGIN, -fFont.Rotation());
|
|
||||||
transform.TranslateBy(baseLine);
|
|
||||||
|
|
||||||
BRect clippingFrame;
|
|
||||||
if (fClippingRegion)
|
|
||||||
clippingFrame = fClippingRegion->Frame();
|
|
||||||
|
|
||||||
bounds = fTextRenderer->RenderString(utf8String,
|
bounds = fTextRenderer->RenderString(utf8String,
|
||||||
length,
|
length,
|
||||||
fFontRendererSolid,
|
fFontRendererSolid,
|
||||||
fFontRendererBin,
|
fFontRendererBin,
|
||||||
transform,
|
baseLine,
|
||||||
clippingFrame,
|
fClippingRegion->Frame(),
|
||||||
false,
|
false,
|
||||||
&fPenLocation);
|
&fPenLocation);
|
||||||
transform.Transform(&fPenLocation);
|
|
||||||
}
|
}
|
||||||
return _Clipped(bounds);
|
return _Clipped(bounds);
|
||||||
}
|
}
|
||||||
@@ -926,31 +912,15 @@ Painter::DrawString(const char* utf8String, BPoint baseLine,
|
|||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
// DrawBitmap
|
// DrawBitmap
|
||||||
void
|
BRect
|
||||||
Painter::DrawBitmap(const BBitmap* bitmap,
|
|
||||||
BRect bitmapRect, BRect viewRect) const
|
|
||||||
{
|
|
||||||
if (bitmap && bitmap->IsValid()) {
|
|
||||||
// the native bitmap coordinate system
|
|
||||||
// (can have left top corner offset)
|
|
||||||
BRect actualBitmapRect(bitmap->Bounds());
|
|
||||||
|
|
||||||
agg::rendering_buffer srcBuffer;
|
|
||||||
srcBuffer.attach((uint8*)bitmap->Bits(),
|
|
||||||
(uint32)actualBitmapRect.IntegerWidth() + 1,
|
|
||||||
(uint32)actualBitmapRect.IntegerHeight() + 1,
|
|
||||||
bitmap->BytesPerRow());
|
|
||||||
|
|
||||||
_DrawBitmap(srcBuffer, bitmap->ColorSpace(), actualBitmapRect, bitmapRect, viewRect);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DrawBitmap
|
|
||||||
void
|
|
||||||
Painter::DrawBitmap(const ServerBitmap* bitmap,
|
Painter::DrawBitmap(const ServerBitmap* bitmap,
|
||||||
BRect bitmapRect, BRect viewRect) const
|
BRect bitmapRect, BRect viewRect) const
|
||||||
{
|
{
|
||||||
if (bitmap && bitmap->InitCheck()) {
|
CHECK_CLIPPING
|
||||||
|
|
||||||
|
BRect touched = _Clipped(viewRect);
|
||||||
|
|
||||||
|
if (bitmap && bitmap->InitCheck() && touched.IsValid()) {
|
||||||
// the native bitmap coordinate system
|
// the native bitmap coordinate system
|
||||||
BRect actualBitmapRect(bitmap->Bounds());
|
BRect actualBitmapRect(bitmap->Bounds());
|
||||||
|
|
||||||
@@ -962,6 +932,7 @@ Painter::DrawBitmap(const ServerBitmap* bitmap,
|
|||||||
|
|
||||||
_DrawBitmap(srcBuffer, bitmap->ColorSpace(), actualBitmapRect, bitmapRect, viewRect);
|
_DrawBitmap(srcBuffer, bitmap->ColorSpace(), actualBitmapRect, bitmapRect, viewRect);
|
||||||
}
|
}
|
||||||
|
return touched;
|
||||||
}
|
}
|
||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
@@ -1004,15 +975,12 @@ BRect
|
|||||||
Painter::BoundingBox(const char* utf8String, uint32 length,
|
Painter::BoundingBox(const char* utf8String, uint32 length,
|
||||||
const BPoint& baseLine) const
|
const BPoint& baseLine) const
|
||||||
{
|
{
|
||||||
Transformable transform;
|
|
||||||
transform.TranslateBy(baseLine);
|
|
||||||
|
|
||||||
static BRect dummy;
|
static BRect dummy;
|
||||||
return fTextRenderer->RenderString(utf8String,
|
return fTextRenderer->RenderString(utf8String,
|
||||||
length,
|
length,
|
||||||
fFontRendererSolid,
|
fFontRendererSolid,
|
||||||
fFontRendererBin,
|
fFontRendererBin,
|
||||||
transform, dummy, true);
|
baseLine, dummy, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// StringWidth
|
// StringWidth
|
||||||
@@ -1106,20 +1074,7 @@ Painter::_UpdateFont()
|
|||||||
if (fFont.InitCheck() < B_OK)
|
if (fFont.InitCheck() < B_OK)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (fLastFamilyAndStyle != fFont.GetFamilyAndStyle()
|
fTextRenderer->SetFont(fFont);
|
||||||
|| fFont.Rotation() != fLastRotation || fFont.Shear() != fLastShear) {
|
|
||||||
|
|
||||||
if (fTextRenderer->SetFont(fFont)) {
|
|
||||||
fLastFamilyAndStyle = fFont.GetFamilyAndStyle();
|
|
||||||
fLastRotation = fFont.Rotation();
|
|
||||||
fLastShear = fFont.Shear();
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "unable to set font\n");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// just update the size
|
|
||||||
fTextRenderer->SetPointSize(fFont.Size());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// _UpdateLineWidth
|
// _UpdateLineWidth
|
||||||
@@ -1176,7 +1131,6 @@ Painter::_UpdateDrawingMode()
|
|||||||
void
|
void
|
||||||
Painter::_SetRendererColor(const rgb_color& color) const
|
Painter::_SetRendererColor(const rgb_color& color) const
|
||||||
{
|
{
|
||||||
|
|
||||||
if (fOutlineRenderer)
|
if (fOutlineRenderer)
|
||||||
#if ALIASED_DRAWING
|
#if ALIASED_DRAWING
|
||||||
fOutlineRenderer->line_color(agg::rgba(color.red / 255.0,
|
fOutlineRenderer->line_color(agg::rgba(color.red / 255.0,
|
||||||
@@ -1340,14 +1294,13 @@ Painter::_DrawBitmap(const agg::rendering_buffer& srcBuffer, color_space format,
|
|||||||
_DrawBitmap32(srcBuffer, actualBitmapRect, bitmapRect, viewRect);
|
_DrawBitmap32(srcBuffer, actualBitmapRect, bitmapRect, viewRect);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "Painter::_DrawBitmap() - non-native colorspace: %d\n", format);
|
//printf("Painter::_DrawBitmap() - non-native colorspace: %d\n", format);
|
||||||
#ifdef __HAIKU__
|
|
||||||
// TODO: this is only a temporary implementation,
|
// TODO: this is only a temporary implementation,
|
||||||
// to really handle other colorspaces, one would
|
// to really handle other colorspaces, one would
|
||||||
// rather do the conversion with much less overhead,
|
// rather do the conversion with much less overhead,
|
||||||
// for example in the nn filter (hm), or in the
|
// for example in the nn filter (hm), or in the
|
||||||
// scanline generator
|
// scanline generator (better)
|
||||||
BBitmap temp(actualBitmapRect, 0, B_RGB32);
|
BBitmap temp(actualBitmapRect, B_BITMAP_NO_SERVER_LINK, B_RGB32);
|
||||||
status_t err = temp.ImportBits(srcBuffer.buf(),
|
status_t err = temp.ImportBits(srcBuffer.buf(),
|
||||||
srcBuffer.height() * srcBuffer.stride(),
|
srcBuffer.height() * srcBuffer.stride(),
|
||||||
srcBuffer.stride(),
|
srcBuffer.stride(),
|
||||||
@@ -1360,9 +1313,8 @@ fprintf(stderr, "Painter::_DrawBitmap() - non-native colorspace: %d\n", format);
|
|||||||
temp.BytesPerRow());
|
temp.BytesPerRow());
|
||||||
_DrawBitmap32(convertedBuffer, actualBitmapRect, bitmapRect, viewRect);
|
_DrawBitmap32(convertedBuffer, actualBitmapRect, bitmapRect, viewRect);
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Painter::_DrawBitmap() - colorspace conversion failed: %s\n", strerror(err));
|
printf("Painter::_DrawBitmap() - colorspace conversion failed: %s\n", strerror(err));
|
||||||
}
|
}
|
||||||
#endif // __HAIKU__
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1373,10 +1325,17 @@ Painter::_DrawBitmap32(const agg::rendering_buffer& srcBuffer,
|
|||||||
BRect actualBitmapRect, BRect bitmapRect, BRect viewRect) const
|
BRect actualBitmapRect, BRect bitmapRect, BRect viewRect) const
|
||||||
{
|
{
|
||||||
typedef agg::span_allocator<agg::rgba8> span_alloc_type;
|
typedef agg::span_allocator<agg::rgba8> span_alloc_type;
|
||||||
|
|
||||||
|
// pipeline for non-scaled bitmaps
|
||||||
|
//typedef agg::span_generator<agg::rgba8, span_alloc_type> span_gen_type;
|
||||||
|
//typedef agg::renderer_scanline_aa<renderer_base, span_gen_type> image_renderer_type;
|
||||||
|
|
||||||
|
// pipeline for scaled bitmaps
|
||||||
typedef agg::span_interpolator_linear<> interpolator_type;
|
typedef agg::span_interpolator_linear<> interpolator_type;
|
||||||
typedef agg::span_image_filter_rgba32_nn<agg::order_bgra32,
|
typedef agg::span_image_filter_rgba32_nn<agg::order_bgra32,
|
||||||
interpolator_type> span_gen_type;
|
interpolator_type> scaled_span_gen_type;
|
||||||
typedef agg::renderer_scanline_aa<renderer_base, span_gen_type> image_renderer_type;
|
typedef agg::renderer_scanline_aa<renderer_base, scaled_span_gen_type> scaled_image_renderer_type;
|
||||||
|
|
||||||
|
|
||||||
if (bitmapRect.IsValid() && bitmapRect.Intersects(actualBitmapRect)
|
if (bitmapRect.IsValid() && bitmapRect.Intersects(actualBitmapRect)
|
||||||
&& viewRect.IsValid()) {
|
&& viewRect.IsValid()) {
|
||||||
@@ -1429,10 +1388,6 @@ typedef agg::renderer_scanline_aa<renderer_base, span_gen_type> image_renderer_t
|
|||||||
span_alloc_type sa;
|
span_alloc_type sa;
|
||||||
interpolator_type interpolator(imgMatrix);
|
interpolator_type interpolator(imgMatrix);
|
||||||
|
|
||||||
span_gen_type sg(sa, srcBuffer, agg::rgba(0, 0, 0, 0), interpolator);
|
|
||||||
|
|
||||||
image_renderer_type ri(*fBaseRenderer, sg);
|
|
||||||
|
|
||||||
agg::rasterizer_scanline_aa<> pf;
|
agg::rasterizer_scanline_aa<> pf;
|
||||||
agg::scanline_u8 sl;
|
agg::scanline_u8 sl;
|
||||||
|
|
||||||
@@ -1447,7 +1402,22 @@ typedef agg::renderer_scanline_aa<renderer_base, span_gen_type> image_renderer_t
|
|||||||
agg::conv_transform<agg::path_storage> tr(path, srcMatrix);
|
agg::conv_transform<agg::path_storage> tr(path, srcMatrix);
|
||||||
|
|
||||||
pf.add_path(tr);
|
pf.add_path(tr);
|
||||||
agg::render_scanlines(pf, sl, ri);
|
|
||||||
|
// if (xScale != 1.0 || yScale != 1.0) {
|
||||||
|
//printf("scaled\n");
|
||||||
|
scaled_span_gen_type sg(sa, srcBuffer, agg::rgba(0, 0, 0, 0), interpolator);
|
||||||
|
scaled_image_renderer_type ri(*fBaseRenderer, sg);
|
||||||
|
|
||||||
|
agg::render_scanlines(pf, sl, ri);
|
||||||
|
/* } else {
|
||||||
|
// TODO: Does not even compile, find out how to construct a pipeline without
|
||||||
|
// scaling
|
||||||
|
printf("non scaled scaled\n");
|
||||||
|
span_gen_type sg(sa);
|
||||||
|
image_renderer_type ri(*fBaseRenderer, sg);
|
||||||
|
|
||||||
|
agg::render_scanlines(pf, sl, ri);
|
||||||
|
}*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ namespace agg
|
|||||||
m_curr_cb = 0;
|
m_curr_cb = 0;
|
||||||
if(m_region && m_region->CountRects() > 0)
|
if(m_region && m_region->CountRects() > 0)
|
||||||
{
|
{
|
||||||
BRect cb = m_region->RectAt(0);
|
clipping_rect cb = m_region->RectAtInt(0);
|
||||||
m_ren.clip_box_naked(cb.left, cb.top, cb.right, cb.bottom);
|
m_ren.clip_box_naked(cb.left, cb.top, cb.right, cb.bottom);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -86,7 +86,7 @@ namespace agg
|
|||||||
{
|
{
|
||||||
if(m_region && (int)(++m_curr_cb) < m_region->CountRects())
|
if(m_region && (int)(++m_curr_cb) < m_region->CountRects())
|
||||||
{
|
{
|
||||||
BRect cb = m_region->RectAt(m_curr_cb);
|
clipping_rect cb = m_region->RectAtInt(m_curr_cb);
|
||||||
m_ren.clip_box_naked(cb.left, cb.top, cb.right, cb.bottom);
|
m_ren.clip_box_naked(cb.left, cb.top, cb.right, cb.bottom);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -107,16 +107,18 @@ namespace agg
|
|||||||
{
|
{
|
||||||
m_region = region;
|
m_region = region;
|
||||||
if (m_region) {
|
if (m_region) {
|
||||||
BRect r = m_region->Frame();
|
clipping_rect r = m_region->FrameInt();
|
||||||
if (r.IsValid()) {
|
if (r.left <= r.right && r.top <= r.bottom) {
|
||||||
r = r & BRect(0, 0, width() - 1, height() - 1);
|
// clip rect to frame buffer bounds
|
||||||
// a BRegion actually keeps integer clipping_rects
|
r.left = max_c(0, r.left);
|
||||||
// so just converting to int without rounding is
|
r.top = max_c(0, r.top);
|
||||||
// fine
|
r.right = min_c((int)width() - 1, r.right);
|
||||||
if(r.left < m_bounds.x1) m_bounds.x1 = (int)r.left;
|
r.bottom = min_c((int)height() - 1, r.bottom);
|
||||||
if(r.top < m_bounds.y1) m_bounds.y1 = (int)r.top;
|
|
||||||
if(r.right > m_bounds.x2) m_bounds.x2 = (int)r.right;
|
if(r.left < m_bounds.x1) m_bounds.x1 = r.left;
|
||||||
if(r.bottom > m_bounds.y2) m_bounds.y2 = (int)r.bottom;
|
if(r.top < m_bounds.y1) m_bounds.y1 = r.top;
|
||||||
|
if(r.right > m_bounds.x2) m_bounds.x2 = r.right;
|
||||||
|
if(r.bottom > m_bounds.y2) m_bounds.y2 = r.bottom;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,7 +56,12 @@ AGGTextRenderer::AGGTextRenderer()
|
|||||||
|
|
||||||
fHinted(true),
|
fHinted(true),
|
||||||
fAntialias(true),
|
fAntialias(true),
|
||||||
fKerning(true)
|
fKerning(true),
|
||||||
|
fEmbeddedTransformation(),
|
||||||
|
|
||||||
|
fLastFamilyAndStyle(0),
|
||||||
|
fLastPointSize(-1.0),
|
||||||
|
fLastHinted(false)
|
||||||
{
|
{
|
||||||
fCurves.approximation_scale(2.0);
|
fCurves.approximation_scale(2.0);
|
||||||
fContour.auto_detect_orientation(false);
|
fContour.auto_detect_orientation(false);
|
||||||
@@ -74,18 +79,30 @@ AGGTextRenderer::~AGGTextRenderer()
|
|||||||
bool
|
bool
|
||||||
AGGTextRenderer::SetFont(const ServerFont &font)
|
AGGTextRenderer::SetFont(const ServerFont &font)
|
||||||
{
|
{
|
||||||
bool success = false;
|
bool success = true;
|
||||||
if (font.Rotation() == 0.0 && font.Shear() == 90.0) {
|
// construct an embedded transformation (rotate & shear)
|
||||||
|
Transformable transform;
|
||||||
|
// TODO: convert BFont::Shear(), which is in degrees 45°...135° to whatever AGG is using
|
||||||
|
// transform.ShearBy(B_ORIGIN, fFont.Shear(), 0.0);
|
||||||
|
transform.RotateBy(B_ORIGIN, -font.Rotation());
|
||||||
|
|
||||||
|
bool load = font.GetFamilyAndStyle() != fLastFamilyAndStyle ||
|
||||||
|
transform != fEmbeddedTransformation;
|
||||||
|
|
||||||
|
if (load) {
|
||||||
|
if (transform.IsIdentity()) {
|
||||||
//printf("AGGTextRenderer::SetFont() - native\n");
|
//printf("AGGTextRenderer::SetFont() - native\n");
|
||||||
success = fFontEngine.load_font(font, agg::glyph_ren_native_gray8);
|
success = fFontEngine.load_font(font, agg::glyph_ren_native_gray8);
|
||||||
fFontEngine.hinting(fHinted);
|
} else {
|
||||||
} else {
|
|
||||||
//printf("AGGTextRenderer::SetFont() - outline\n");
|
//printf("AGGTextRenderer::SetFont() - outline\n");
|
||||||
success = fFontEngine.load_font(font, agg::glyph_ren_outline);
|
success = fFontEngine.load_font(font, agg::glyph_ren_outline);
|
||||||
fFontEngine.hinting(false);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SetPointSize(font.Size());
|
fLastFamilyAndStyle = font.GetFamilyAndStyle();
|
||||||
|
fEmbeddedTransformation = transform;
|
||||||
|
|
||||||
|
_UpdateSizeAndHinting(font.Size(), fEmbeddedTransformation.IsIdentity() && fHinted, load);
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
fprintf(stderr, "font could not be loaded\n");
|
fprintf(stderr, "font could not be loaded\n");
|
||||||
@@ -95,23 +112,13 @@ AGGTextRenderer::SetFont(const ServerFont &font)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetPointSize
|
|
||||||
void
|
|
||||||
AGGTextRenderer::SetPointSize(float size)
|
|
||||||
{
|
|
||||||
if (size != fFontEngine.height()) {
|
|
||||||
fFontEngine.height(size);
|
|
||||||
fFontEngine.width(size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetHinting
|
// SetHinting
|
||||||
void
|
void
|
||||||
AGGTextRenderer::SetHinting(bool hinting)
|
AGGTextRenderer::SetHinting(bool hinting)
|
||||||
{
|
{
|
||||||
if (fHinted != hinting) {
|
if (fHinted != hinting) {
|
||||||
fHinted = hinting;
|
fHinted = hinting;
|
||||||
fFontEngine.hinting(fHinted);
|
_UpdateSizeAndHinting(fLastPointSize, fEmbeddedTransformation.IsIdentity() && fHinted);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,26 +142,23 @@ AGGTextRenderer::RenderString(const char* string,
|
|||||||
uint32 length,
|
uint32 length,
|
||||||
font_renderer_solid_type* solidRenderer,
|
font_renderer_solid_type* solidRenderer,
|
||||||
font_renderer_bin_type* binRenderer,
|
font_renderer_bin_type* binRenderer,
|
||||||
const Transformable& transform,
|
const BPoint& baseLine,
|
||||||
BRect clippingFrame,
|
const BRect& clippingFrame,
|
||||||
bool dryRun,
|
bool dryRun,
|
||||||
BPoint* nextCharPos)
|
BPoint* nextCharPos)
|
||||||
{
|
{
|
||||||
//printf("RenderString(\"%s\", length: %ld, dry: %d)\n", string, length, dryRun);
|
//printf("RenderString(\"%s\", length: %ld, dry: %d)\n", string, length, dryRun);
|
||||||
|
|
||||||
// ToDo: this is a temporary fix for some drawing problems
|
|
||||||
// Please remove when the real cause has been found :-)
|
|
||||||
float size = fFontEngine.height();
|
|
||||||
fFontEngine.height(size);
|
|
||||||
fFontEngine.width(size);
|
|
||||||
fFontEngine.hinting(fHinted);
|
|
||||||
|
|
||||||
// "bounds" will track the bounding box arround all glyphs that are actually drawn
|
// "bounds" will track the bounding box arround all glyphs that are actually drawn
|
||||||
// it will be calculated in untransformed coordinates within the loop and then
|
// it will be calculated in untransformed coordinates within the loop and then
|
||||||
// it is transformed to the real location at the exit of the function.
|
// it is transformed to the real location at the exit of the function.
|
||||||
BRect bounds(0.0, 0.0, -1.0, -1.0);
|
BRect bounds(0.0, 0.0, -1.0, -1.0);
|
||||||
|
|
||||||
|
Transformable transform(fEmbeddedTransformation);
|
||||||
|
transform.TranslateBy(baseLine);
|
||||||
|
|
||||||
uint32 glyphCount;
|
uint32 glyphCount;
|
||||||
|
|
||||||
if (_PrepareUnicodeBuffer(string, length, &glyphCount) >= B_OK) {
|
if (_PrepareUnicodeBuffer(string, length, &glyphCount) >= B_OK) {
|
||||||
|
|
||||||
fCurves.approximation_scale(transform.scale());
|
fCurves.approximation_scale(transform.scale());
|
||||||
@@ -194,7 +198,6 @@ AGGTextRenderer::RenderString(const char* string,
|
|||||||
const agg::glyph_cache* glyph = fFontManager.glyph(*p);
|
const agg::glyph_cache* glyph = fFontManager.glyph(*p);
|
||||||
|
|
||||||
if (glyph) {
|
if (glyph) {
|
||||||
|
|
||||||
if (i > 0 && fKerning) {
|
if (i > 0 && fKerning) {
|
||||||
fFontManager.add_kerning(&advanceX, &advanceY);
|
fFontManager.add_kerning(&advanceX, &advanceY);
|
||||||
}
|
}
|
||||||
@@ -240,7 +243,7 @@ AGGTextRenderer::RenderString(const char* string,
|
|||||||
glyphBounds = transform.TransformBounds(glyphBounds);
|
glyphBounds = transform.TransformBounds(glyphBounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clippingFrame.Intersects(glyphBounds)) {
|
if (true /*clippingFrame.Intersects(glyphBounds)*/) {
|
||||||
switch (glyph->data_type) {
|
switch (glyph->data_type) {
|
||||||
case agg::glyph_data_mono:
|
case agg::glyph_data_mono:
|
||||||
agg::render_scanlines(fFontManager.mono_adaptor(),
|
agg::render_scanlines(fFontManager.mono_adaptor(),
|
||||||
@@ -297,6 +300,15 @@ AGGTextRenderer::RenderString(const char* string,
|
|||||||
// increment pen position
|
// increment pen position
|
||||||
advanceX = glyph->advance_x;
|
advanceX = glyph->advance_x;
|
||||||
advanceY = glyph->advance_y;
|
advanceY = glyph->advance_y;
|
||||||
|
} else {
|
||||||
|
if (*p < 128) {
|
||||||
|
char c[2];
|
||||||
|
c[0] = (uint8)*p;
|
||||||
|
c[1] = 0;
|
||||||
|
fprintf(stderr, "failed to load glyph for '%s'\n", c);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "failed to load glyph for %d\n", *p);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
@@ -305,6 +317,8 @@ AGGTextRenderer::RenderString(const char* string,
|
|||||||
if (nextCharPos) {
|
if (nextCharPos) {
|
||||||
nextCharPos->x = x + advanceX;
|
nextCharPos->x = x + advanceX;
|
||||||
nextCharPos->y = y + advanceY;
|
nextCharPos->y = y + advanceY;
|
||||||
|
|
||||||
|
transform.Transform(nextCharPos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -371,3 +385,19 @@ AGGTextRenderer::_PrepareUnicodeBuffer(const char* utf8String,
|
|||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// _UpdateSizeAndHinting
|
||||||
|
void
|
||||||
|
AGGTextRenderer::_UpdateSizeAndHinting(float size, bool hinted, bool force)
|
||||||
|
{
|
||||||
|
if (force || size != fLastPointSize || hinted != fLastHinted) {
|
||||||
|
//printf("AGGTextRenderer::_UpdateSizeAndHinting(%.1f, %d, %d)\n", size, hinted, force);
|
||||||
|
fLastPointSize = size;
|
||||||
|
fLastHinted = hinted;
|
||||||
|
|
||||||
|
fFontEngine.height(size);
|
||||||
|
fFontEngine.width(size);
|
||||||
|
fFontEngine.hinting(hinted);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,8 +22,6 @@ class AGGTextRenderer {
|
|||||||
bool SetFont(const ServerFont &font);
|
bool SetFont(const ServerFont &font);
|
||||||
void Unset();
|
void Unset();
|
||||||
|
|
||||||
void SetPointSize(float size);
|
|
||||||
|
|
||||||
void SetHinting(bool hinting);
|
void SetHinting(bool hinting);
|
||||||
bool Hinting() const
|
bool Hinting() const
|
||||||
{ return fHinted; }
|
{ return fHinted; }
|
||||||
@@ -32,12 +30,16 @@ class AGGTextRenderer {
|
|||||||
bool Antialiasing() const
|
bool Antialiasing() const
|
||||||
{ return fAntialias; }
|
{ return fAntialias; }
|
||||||
|
|
||||||
|
void SetKerning(bool kerning);
|
||||||
|
bool Kerning() const
|
||||||
|
{ return fKerning; }
|
||||||
|
|
||||||
BRect RenderString(const char* utf8String,
|
BRect RenderString(const char* utf8String,
|
||||||
uint32 length,
|
uint32 length,
|
||||||
font_renderer_solid_type* solidRenderer,
|
font_renderer_solid_type* solidRenderer,
|
||||||
font_renderer_bin_type* binRenderer,
|
font_renderer_bin_type* binRenderer,
|
||||||
const Transformable& transform,
|
const BPoint& baseLine,
|
||||||
BRect clippingFrame,
|
const BRect& clippingFrame,
|
||||||
bool dryRun = false,
|
bool dryRun = false,
|
||||||
BPoint* nextCharPos = NULL);
|
BPoint* nextCharPos = NULL);
|
||||||
|
|
||||||
@@ -48,6 +50,8 @@ class AGGTextRenderer {
|
|||||||
status_t _PrepareUnicodeBuffer(const char* utf8String,
|
status_t _PrepareUnicodeBuffer(const char* utf8String,
|
||||||
uint32 length,
|
uint32 length,
|
||||||
uint32* glyphCount);
|
uint32* glyphCount);
|
||||||
|
void _UpdateSizeAndHinting(float size, bool hinted,
|
||||||
|
bool force = false);
|
||||||
|
|
||||||
|
|
||||||
typedef agg::font_engine_freetype_int32 font_engine_type;
|
typedef agg::font_engine_freetype_int32 font_engine_type;
|
||||||
@@ -70,8 +74,14 @@ class AGGTextRenderer {
|
|||||||
int32 fUnicodeBufferSize;
|
int32 fUnicodeBufferSize;
|
||||||
|
|
||||||
bool fHinted; // is glyph hinting active?
|
bool fHinted; // is glyph hinting active?
|
||||||
bool fAntialias; // is anti-aliasing active?
|
bool fAntialias;
|
||||||
bool fKerning;
|
bool fKerning;
|
||||||
|
Transformable fEmbeddedTransformation; // rotated or sheared font?
|
||||||
|
|
||||||
|
// caching to avoid loading a font unnecessarily
|
||||||
|
uint32 fLastFamilyAndStyle;
|
||||||
|
float fLastPointSize;
|
||||||
|
bool fLastHinted;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // AGG_TEXT_RENDERER_H
|
#endif // AGG_TEXT_RENDERER_H
|
||||||
|
|||||||
Reference in New Issue
Block a user