diff --git a/headers/private/servers/app/Painter.h b/headers/private/servers/app/Painter.h index 4c3aa21987..1961833b19 100644 --- a/headers/private/servers/app/Painter.h +++ b/headers/private/servers/app/Painter.h @@ -193,11 +193,7 @@ class Painter { const escapement_delta* delta = NULL); // bitmaps - void DrawBitmap( const BBitmap* bitmap, - BRect bitmapRect, - BRect viewRect) const; - - void DrawBitmap( const ServerBitmap* bitmap, + BRect DrawBitmap( const ServerBitmap* bitmap, BRect bitmapRect, BRect viewRect) const; @@ -306,9 +302,6 @@ class Painter { // font file, it uses the FontManager to locate a file // by Family and Style AGGTextRenderer* fTextRenderer; - uint32 fLastFamilyAndStyle; - float fLastRotation; - float fLastShear; }; // SetHighColor diff --git a/src/servers/app/Desktop.cpp b/src/servers/app/Desktop.cpp index 8290a0874b..174497ff02 100644 --- a/src/servers/app/Desktop.cpp +++ b/src/servers/app/Desktop.cpp @@ -104,6 +104,8 @@ Desktop::AddDriver(DisplayDriver *driver) if (driver->Initialize()) { // 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(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_GRAY8, fScreenList.CountItems()+1); // Screen *sc = new Screen(driver, BPoint(640, 480), B_RGB15, fScreenList.CountItems()+1); diff --git a/src/servers/app/ServerWindow.cpp b/src/servers/app/ServerWindow.cpp index c76262e76e..068b5fe206 100644 --- a/src/servers/app/ServerWindow.cpp +++ b/src/servers/app/ServerWindow.cpp @@ -2020,7 +2020,6 @@ void ServerWindow::DispatchGraphicsMessage(int32 code, LinkMsgReader &link) case AS_DRAW_STRING: { DTRACE(("ServerWindow %s: Message AS_DRAW_STRING\n",fName)); - char *string; int32 length; BPoint location; @@ -2031,9 +2030,10 @@ void ServerWindow::DispatchGraphicsMessage(int32 code, LinkMsgReader &link) link.Read(&delta); link.ReadString(&string); - if(cl && cl->fLayerData) - desktop->GetDisplayDriver()->DrawString(string,length,cl->ConvertToTop(location), - cl->fLayerData); + if (cl && cl->fLayerData) + desktop->GetDisplayDriver()->DrawString(string, length, + cl->ConvertToTop(location), + cl->fLayerData); free(string); break; diff --git a/src/servers/app/drawing/DisplayDriverPainter.cpp b/src/servers/app/drawing/DisplayDriverPainter.cpp index a7698e7e65..47a1e863dc 100644 --- a/src/servers/app/drawing/DisplayDriverPainter.cpp +++ b/src/servers/app/drawing/DisplayDriverPainter.cpp @@ -387,9 +387,9 @@ DisplayDriverPainter::DrawBitmap(ServerBitmap *bitmap, fGraphicsCard->HideSoftwareCursor(clipped); fPainter->SetDrawData(d); - fPainter->DrawBitmap(bitmap, source, dest); + BRect touched = fPainter->DrawBitmap(bitmap, source, dest); - fGraphicsCard->Invalidate(clipped); + fGraphicsCard->Invalidate(touched); fGraphicsCard->ShowSoftwareCursor(); Unlock(); @@ -969,7 +969,8 @@ DisplayDriverPainter::DrawString(const char *string, const int32 &length, { static DrawData d; d.SetHighColor(color); - + + // TODO: Why is escapement_delta a part of the state stack? if (delta) d.SetEscapementDelta(*delta); @@ -985,21 +986,23 @@ DisplayDriverPainter::DrawString(const char *string, const int32 &length, fPainter->SetDrawData(d); //bigtime_t now = system_time(); // 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 // 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); + // 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); - fGraphicsCard->HideSoftwareCursor(b); - + fGraphicsCard->HideSoftwareCursor(b); + //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); - - fGraphicsCard->Invalidate(touched); - fGraphicsCard->ShowSoftwareCursor(); - + + fGraphicsCard->Invalidate(touched); + fGraphicsCard->ShowSoftwareCursor(); + } Unlock(); } } diff --git a/src/servers/app/drawing/Painter/Painter.cpp b/src/servers/app/drawing/Painter/Painter.cpp index 36d1d5363e..f0088c9572 100644 --- a/src/servers/app/drawing/Painter/Painter.cpp +++ b/src/servers/app/drawing/Painter/Painter.cpp @@ -80,10 +80,7 @@ Painter::Painter() fPenLocation(0.0, 0.0), fDrawingModeFactory(new DrawingModeFactory()), fPatternHandler(new PatternHandler()), - fTextRenderer(new AGGTextRenderer()), - fLastFamilyAndStyle(0), - fLastRotation(0.0), - fLastShear(90.0) + fTextRenderer(new AGGTextRenderer()) { if (fontserver && fontserver->GetSystemPlain()) fFont = *fontserver->GetSystemPlain(); @@ -883,25 +880,14 @@ Painter::DrawString(const char* utf8String, uint32 length, 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, length, fFontRendererSolid, fFontRendererBin, - transform, - clippingFrame, + baseLine, + fClippingRegion->Frame(), false, &fPenLocation); - transform.Transform(&fPenLocation); } return _Clipped(bounds); } @@ -926,31 +912,15 @@ Painter::DrawString(const char* utf8String, BPoint baseLine, // #pragma mark - // DrawBitmap -void -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 +BRect Painter::DrawBitmap(const ServerBitmap* bitmap, 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 BRect actualBitmapRect(bitmap->Bounds()); @@ -962,6 +932,7 @@ Painter::DrawBitmap(const ServerBitmap* bitmap, _DrawBitmap(srcBuffer, bitmap->ColorSpace(), actualBitmapRect, bitmapRect, viewRect); } + return touched; } // #pragma mark - @@ -1004,15 +975,12 @@ BRect Painter::BoundingBox(const char* utf8String, uint32 length, const BPoint& baseLine) const { - Transformable transform; - transform.TranslateBy(baseLine); - static BRect dummy; return fTextRenderer->RenderString(utf8String, length, fFontRendererSolid, fFontRendererBin, - transform, dummy, true); + baseLine, dummy, true); } // StringWidth @@ -1106,20 +1074,7 @@ Painter::_UpdateFont() if (fFont.InitCheck() < B_OK) return; - if (fLastFamilyAndStyle != fFont.GetFamilyAndStyle() - || 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()); - } + fTextRenderer->SetFont(fFont); } // _UpdateLineWidth @@ -1176,7 +1131,6 @@ Painter::_UpdateDrawingMode() void Painter::_SetRendererColor(const rgb_color& color) const { - if (fOutlineRenderer) #if ALIASED_DRAWING 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); break; default: -fprintf(stderr, "Painter::_DrawBitmap() - non-native colorspace: %d\n", format); -#ifdef __HAIKU__ +//printf("Painter::_DrawBitmap() - non-native colorspace: %d\n", format); // TODO: this is only a temporary implementation, // to really handle other colorspaces, one would // rather do the conversion with much less overhead, // for example in the nn filter (hm), or in the - // scanline generator - BBitmap temp(actualBitmapRect, 0, B_RGB32); + // scanline generator (better) + BBitmap temp(actualBitmapRect, B_BITMAP_NO_SERVER_LINK, B_RGB32); status_t err = temp.ImportBits(srcBuffer.buf(), srcBuffer.height() * srcBuffer.stride(), srcBuffer.stride(), @@ -1360,9 +1313,8 @@ fprintf(stderr, "Painter::_DrawBitmap() - non-native colorspace: %d\n", format); temp.BytesPerRow()); _DrawBitmap32(convertedBuffer, actualBitmapRect, bitmapRect, viewRect); } 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; } } @@ -1373,10 +1325,17 @@ Painter::_DrawBitmap32(const agg::rendering_buffer& srcBuffer, BRect actualBitmapRect, BRect bitmapRect, BRect viewRect) const { typedef agg::span_allocator span_alloc_type; + +// pipeline for non-scaled bitmaps +//typedef agg::span_generator span_gen_type; +//typedef agg::renderer_scanline_aa image_renderer_type; + +// pipeline for scaled bitmaps typedef agg::span_interpolator_linear<> interpolator_type; typedef agg::span_image_filter_rgba32_nn span_gen_type; -typedef agg::renderer_scanline_aa image_renderer_type; + interpolator_type> scaled_span_gen_type; +typedef agg::renderer_scanline_aa scaled_image_renderer_type; + if (bitmapRect.IsValid() && bitmapRect.Intersects(actualBitmapRect) && viewRect.IsValid()) { @@ -1429,10 +1388,6 @@ typedef agg::renderer_scanline_aa image_renderer_t span_alloc_type sa; 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::scanline_u8 sl; @@ -1447,7 +1402,22 @@ typedef agg::renderer_scanline_aa image_renderer_t agg::conv_transform tr(path, srcMatrix); 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); + }*/ } } diff --git a/src/servers/app/drawing/Painter/agg_renderer_region.h b/src/servers/app/drawing/Painter/agg_renderer_region.h index 205a013636..e398448de3 100644 --- a/src/servers/app/drawing/Painter/agg_renderer_region.h +++ b/src/servers/app/drawing/Painter/agg_renderer_region.h @@ -74,7 +74,7 @@ namespace agg m_curr_cb = 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); } else @@ -86,7 +86,7 @@ namespace agg { 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); return true; } @@ -107,16 +107,18 @@ namespace agg { m_region = region; if (m_region) { - BRect r = m_region->Frame(); - if (r.IsValid()) { - r = r & BRect(0, 0, width() - 1, height() - 1); - // a BRegion actually keeps integer clipping_rects - // so just converting to int without rounding is - // fine - if(r.left < m_bounds.x1) m_bounds.x1 = (int)r.left; - 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.bottom > m_bounds.y2) m_bounds.y2 = (int)r.bottom; + clipping_rect r = m_region->FrameInt(); + if (r.left <= r.right && r.top <= r.bottom) { + // clip rect to frame buffer bounds + r.left = max_c(0, r.left); + r.top = max_c(0, r.top); + r.right = min_c((int)width() - 1, r.right); + r.bottom = min_c((int)height() - 1, r.bottom); + + if(r.left < m_bounds.x1) m_bounds.x1 = r.left; + 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; } } } diff --git a/src/servers/app/drawing/Painter/font_support/AGGTextRenderer.cpp b/src/servers/app/drawing/Painter/font_support/AGGTextRenderer.cpp index ea933fbc08..12c72703f8 100644 --- a/src/servers/app/drawing/Painter/font_support/AGGTextRenderer.cpp +++ b/src/servers/app/drawing/Painter/font_support/AGGTextRenderer.cpp @@ -56,7 +56,12 @@ AGGTextRenderer::AGGTextRenderer() fHinted(true), fAntialias(true), - fKerning(true) + fKerning(true), + fEmbeddedTransformation(), + + fLastFamilyAndStyle(0), + fLastPointSize(-1.0), + fLastHinted(false) { fCurves.approximation_scale(2.0); fContour.auto_detect_orientation(false); @@ -74,18 +79,30 @@ AGGTextRenderer::~AGGTextRenderer() bool AGGTextRenderer::SetFont(const ServerFont &font) { - bool success = false; - if (font.Rotation() == 0.0 && font.Shear() == 90.0) { + bool success = true; + // 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"); - success = fFontEngine.load_font(font, agg::glyph_ren_native_gray8); - fFontEngine.hinting(fHinted); - } else { + success = fFontEngine.load_font(font, agg::glyph_ren_native_gray8); + } else { //printf("AGGTextRenderer::SetFont() - outline\n"); - success = fFontEngine.load_font(font, agg::glyph_ren_outline); - fFontEngine.hinting(false); + success = fFontEngine.load_font(font, agg::glyph_ren_outline); + } } - SetPointSize(font.Size()); + fLastFamilyAndStyle = font.GetFamilyAndStyle(); + fEmbeddedTransformation = transform; + + _UpdateSizeAndHinting(font.Size(), fEmbeddedTransformation.IsIdentity() && fHinted, load); if (!success) { fprintf(stderr, "font could not be loaded\n"); @@ -95,23 +112,13 @@ AGGTextRenderer::SetFont(const ServerFont &font) return true; } -// SetPointSize -void -AGGTextRenderer::SetPointSize(float size) -{ - if (size != fFontEngine.height()) { - fFontEngine.height(size); - fFontEngine.width(size); - } -} - // SetHinting void AGGTextRenderer::SetHinting(bool hinting) { if (fHinted != hinting) { fHinted = hinting; - fFontEngine.hinting(fHinted); + _UpdateSizeAndHinting(fLastPointSize, fEmbeddedTransformation.IsIdentity() && fHinted); } } @@ -135,26 +142,23 @@ AGGTextRenderer::RenderString(const char* string, uint32 length, font_renderer_solid_type* solidRenderer, font_renderer_bin_type* binRenderer, - const Transformable& transform, - BRect clippingFrame, + const BPoint& baseLine, + const BRect& clippingFrame, bool dryRun, BPoint* nextCharPos) { //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 // 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. BRect bounds(0.0, 0.0, -1.0, -1.0); + Transformable transform(fEmbeddedTransformation); + transform.TranslateBy(baseLine); + uint32 glyphCount; + if (_PrepareUnicodeBuffer(string, length, &glyphCount) >= B_OK) { fCurves.approximation_scale(transform.scale()); @@ -194,7 +198,6 @@ AGGTextRenderer::RenderString(const char* string, const agg::glyph_cache* glyph = fFontManager.glyph(*p); if (glyph) { - if (i > 0 && fKerning) { fFontManager.add_kerning(&advanceX, &advanceY); } @@ -240,7 +243,7 @@ AGGTextRenderer::RenderString(const char* string, glyphBounds = transform.TransformBounds(glyphBounds); } - if (clippingFrame.Intersects(glyphBounds)) { + if (true /*clippingFrame.Intersects(glyphBounds)*/) { switch (glyph->data_type) { case agg::glyph_data_mono: agg::render_scanlines(fFontManager.mono_adaptor(), @@ -297,6 +300,15 @@ AGGTextRenderer::RenderString(const char* string, // increment pen position advanceX = glyph->advance_x; 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; } @@ -305,6 +317,8 @@ AGGTextRenderer::RenderString(const char* string, if (nextCharPos) { nextCharPos->x = x + advanceX; nextCharPos->y = y + advanceY; + + transform.Transform(nextCharPos); } } @@ -371,3 +385,19 @@ AGGTextRenderer::_PrepareUnicodeBuffer(const char* utf8String, 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); + } +} + diff --git a/src/servers/app/drawing/Painter/font_support/AGGTextRenderer.h b/src/servers/app/drawing/Painter/font_support/AGGTextRenderer.h index c11b959908..7357a8720c 100644 --- a/src/servers/app/drawing/Painter/font_support/AGGTextRenderer.h +++ b/src/servers/app/drawing/Painter/font_support/AGGTextRenderer.h @@ -22,8 +22,6 @@ class AGGTextRenderer { bool SetFont(const ServerFont &font); void Unset(); - void SetPointSize(float size); - void SetHinting(bool hinting); bool Hinting() const { return fHinted; } @@ -32,12 +30,16 @@ class AGGTextRenderer { bool Antialiasing() const { return fAntialias; } + void SetKerning(bool kerning); + bool Kerning() const + { return fKerning; } + BRect RenderString(const char* utf8String, uint32 length, font_renderer_solid_type* solidRenderer, font_renderer_bin_type* binRenderer, - const Transformable& transform, - BRect clippingFrame, + const BPoint& baseLine, + const BRect& clippingFrame, bool dryRun = false, BPoint* nextCharPos = NULL); @@ -48,6 +50,8 @@ class AGGTextRenderer { status_t _PrepareUnicodeBuffer(const char* utf8String, uint32 length, uint32* glyphCount); + void _UpdateSizeAndHinting(float size, bool hinted, + bool force = false); typedef agg::font_engine_freetype_int32 font_engine_type; @@ -70,8 +74,14 @@ class AGGTextRenderer { int32 fUnicodeBufferSize; bool fHinted; // is glyph hinting active? - bool fAntialias; // is anti-aliasing active? + bool fAntialias; 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