diff options
-rw-r--r-- | include/vcl/outdev.hxx | 3 | ||||
-rw-r--r-- | vcl/source/outdev/outdev.cxx | 10 | ||||
-rw-r--r-- | vcl/source/window/paint.cxx | 162 |
3 files changed, 103 insertions, 72 deletions
diff --git a/include/vcl/outdev.hxx b/include/vcl/outdev.hxx index c2e334c5129d..f0057b3b54c0 100644 --- a/include/vcl/outdev.hxx +++ b/include/vcl/outdev.hxx @@ -318,7 +318,6 @@ namespace vcl { class VCL_DLLPUBLIC OutputDevice { - friend class PaintHelper; friend class Printer; friend class VirtualDevice; friend class vcl::Window; @@ -499,6 +498,8 @@ public: long GetOutputHeightPixel() const { return mnOutHeight; } long GetOutOffXPixel() const { return mnOutOffX; } long GetOutOffYPixel() const { return mnOutOffY; } + void SetOutOffXPixel(long nOutOffX); + void SetOutOffYPixel(long nOutOffY); Size GetOutputSize() const { return PixelToLogic( GetOutputSizePixel() ); } diff --git a/vcl/source/outdev/outdev.cxx b/vcl/source/outdev/outdev.cxx index 2ae452e70d63..0d9842de39dc 100644 --- a/vcl/source/outdev/outdev.cxx +++ b/vcl/source/outdev/outdev.cxx @@ -427,6 +427,16 @@ sal_uInt16 OutputDevice::GetBitCount() const return (sal_uInt16)mpGraphics->GetBitCount(); } +void OutputDevice::SetOutOffXPixel(long nOutOffX) +{ + mnOutOffX = nOutOffX; +} + +void OutputDevice::SetOutOffYPixel(long nOutOffY) +{ + mnOutOffY = nOutOffY; +} + sal_uLong OutputDevice::GetColorCount() const { diff --git a/vcl/source/window/paint.cxx b/vcl/source/window/paint.cxx index ee5d47a18caa..a02d60065b09 100644 --- a/vcl/source/window/paint.cxx +++ b/vcl/source/window/paint.cxx @@ -40,6 +40,88 @@ #define IMPL_PAINT_ERASE ((sal_uInt16)0x0010) #define IMPL_PAINT_CHECKRTL ((sal_uInt16)0x0020) +/// Sets up the buffer to have settings matching the window, and restore the original state in the dtor. +class PaintBufferGuard +{ + ImplFrameData* mpFrameData; + bool mbBackground; + Wallpaper maBackground; + AllSettings maSettings; + long mnOutOffX; + long mnOutOffY; +public: + PaintBufferGuard(ImplFrameData* pFrameData, vcl::Window* pWindow) + : mpFrameData(pFrameData), + mbBackground(false), + mnOutOffX(0), + mnOutOffY(0) + { + // transfer various settings + // FIXME: this must disappear as we move to RenderContext only, + // the painting must become state-less, so that no actual + // vcl::Window setting affects this + mbBackground = pFrameData->mpBuffer->IsBackground(); + if (pWindow->IsBackground()) + { + maBackground = pFrameData->mpBuffer->GetBackground(); + pFrameData->mpBuffer->SetBackground(pWindow->GetBackground()); + } + //else + //SAL_WARN("vcl.doublebuffering", "the root of the double-buffering hierarchy should not have a transparent background"); + + PushFlags nFlags = PushFlags::NONE; + nFlags |= PushFlags::CLIPREGION; + nFlags |= PushFlags::FILLCOLOR; + nFlags |= PushFlags::FONT; + nFlags |= PushFlags::LINECOLOR; + nFlags |= PushFlags::MAPMODE; + maSettings = pFrameData->mpBuffer->GetSettings(); + nFlags |= PushFlags::REFPOINT; + nFlags |= PushFlags::TEXTCOLOR; + nFlags |= PushFlags::TEXTLINECOLOR; + nFlags |= PushFlags::OVERLINECOLOR; + nFlags |= PushFlags::TEXTFILLCOLOR; + nFlags |= PushFlags::TEXTALIGN; + nFlags |= PushFlags::RASTEROP; + nFlags |= PushFlags::TEXTLAYOUTMODE; + nFlags |= PushFlags::TEXTLANGUAGE; + pFrameData->mpBuffer->Push(nFlags); + pFrameData->mpBuffer->SetClipRegion(pWindow->GetClipRegion()); + pFrameData->mpBuffer->SetFillColor(pWindow->GetFillColor()); + pFrameData->mpBuffer->SetFont(pWindow->GetFont()); + pFrameData->mpBuffer->SetLineColor(pWindow->GetLineColor()); + pFrameData->mpBuffer->SetMapMode(pWindow->GetMapMode()); + pFrameData->mpBuffer->SetRefPoint(pWindow->GetRefPoint()); + pFrameData->mpBuffer->SetSettings(pWindow->GetSettings()); + pFrameData->mpBuffer->SetTextColor(pWindow->GetTextColor()); + pFrameData->mpBuffer->SetTextLineColor(pWindow->GetTextLineColor()); + pFrameData->mpBuffer->SetOverlineColor(pWindow->GetOverlineColor()); + pFrameData->mpBuffer->SetTextFillColor(pWindow->GetTextFillColor()); + pFrameData->mpBuffer->SetTextAlign(pWindow->GetTextAlign()); + pFrameData->mpBuffer->SetRasterOp(pWindow->GetRasterOp()); + pFrameData->mpBuffer->SetLayoutMode(pWindow->GetLayoutMode()); + pFrameData->mpBuffer->SetDigitLanguage(pWindow->GetDigitLanguage()); + + mnOutOffX = pFrameData->mpBuffer->GetOutOffXPixel(); + mnOutOffY = pFrameData->mpBuffer->GetOutOffYPixel(); + pFrameData->mpBuffer->SetOutOffXPixel(pWindow->GetOutOffXPixel()); + pFrameData->mpBuffer->SetOutOffYPixel(pWindow->GetOutOffYPixel()); + } + ~PaintBufferGuard() + { + // Restore buffer state. + mpFrameData->mpBuffer->SetOutOffXPixel(mnOutOffX); + mpFrameData->mpBuffer->SetOutOffYPixel(mnOutOffY); + + mpFrameData->mpBuffer->Pop(); + mpFrameData->mpBuffer->SetSettings(maSettings); + if (mbBackground) + mpFrameData->mpBuffer->SetBackground(maBackground); + else + mpFrameData->mpBuffer->SetBackground(); + } +}; + class PaintHelper { private: @@ -47,7 +129,6 @@ private: vcl::Region* m_pChildRegion; Rectangle m_aSelectionRect; Rectangle m_aPaintRect; - MapMode m_aPaintRectMapMode; vcl::Region m_aPaintRegion; sal_uInt16 m_nPaintFlags; bool m_bPop : 1; @@ -88,9 +169,6 @@ public: /// Start buffered paint: set it up to have the same settings as m_pWindow. void StartBufferedPaint(); - /// Setup the buffer according to the settings of the current m_pWindow. - void SetupBuffer(); - /// Paint the content of the buffer to the current m_pWindow. void PaintBuffer(); @@ -116,53 +194,16 @@ void PaintHelper::StartBufferedPaint() // painting over, as VirtualDevice::ImplInitVirDev() would do. // The painted area is m_aPaintRect, or in case it's empty, then the whole window. pFrameData->mpBuffer->SetBackground(Wallpaper(Color(COL_WHITE))); - if (m_aPaintRect.IsEmpty()) - pFrameData->mpBuffer->Erase(Rectangle(Point(0, 0), m_pWindow->GetOutputSize())); - else - pFrameData->mpBuffer->Erase(m_aPaintRect); + { + PaintBufferGuard g(pFrameData, m_pWindow); + if (m_aPaintRect.IsEmpty()) + pFrameData->mpBuffer->Erase(Rectangle(Point(0, 0), m_pWindow->GetOutputSize())); + else + pFrameData->mpBuffer->Erase(m_aPaintRect); + } pFrameData->mbInBufferedPaint = true; m_bStartedBufferedPaint = true; - - // Remember what was the map mode of m_aPaintRect. - m_aPaintRectMapMode = m_pWindow->GetMapMode(); - - // we need to remember the mnOutOffX / mnOutOffY, but actually really - // set it just temporarily for the subwidgets - so we are setting it here - // only to remember the value & to be able to pass it to the descendants - // FIXME: once everything's double-buffered, this is (hopefully) not - // necessary as the buffer is always created for the main window. - pFrameData->mpBuffer->mnOutOffX = m_pWindow->GetOutOffXPixel(); - pFrameData->mpBuffer->mnOutOffY = m_pWindow->GetOutOffYPixel(); -} - -void PaintHelper::SetupBuffer() -{ - ImplFrameData* pFrameData = m_pWindow->mpWindowImpl->mpFrameData; - // transfer various settings - // FIXME: this must disappear as we move to RenderContext only, - // the painting must become state-less, so that no actual - // vcl::Window setting affects this - if (m_pWindow->IsBackground()) - pFrameData->mpBuffer->SetBackground(m_pWindow->GetBackground()); - else - SAL_WARN("vcl.doublebuffering", "the root of the double-buffering hierarchy should not have a transparent background"); - - pFrameData->mpBuffer->SetClipRegion(m_pWindow->GetClipRegion()); - pFrameData->mpBuffer->SetFillColor(m_pWindow->GetFillColor()); - pFrameData->mpBuffer->SetFont(m_pWindow->GetFont()); - pFrameData->mpBuffer->SetLineColor(m_pWindow->GetLineColor()); - pFrameData->mpBuffer->SetMapMode(m_pWindow->GetMapMode()); - pFrameData->mpBuffer->SetRefPoint(m_pWindow->GetRefPoint()); - pFrameData->mpBuffer->SetSettings(m_pWindow->GetSettings()); - pFrameData->mpBuffer->SetTextColor(m_pWindow->GetTextColor()); - pFrameData->mpBuffer->SetTextLineColor(m_pWindow->GetTextLineColor()); - pFrameData->mpBuffer->SetOverlineColor(m_pWindow->GetOverlineColor()); - pFrameData->mpBuffer->SetTextFillColor(m_pWindow->GetTextFillColor()); - pFrameData->mpBuffer->SetTextAlign(m_pWindow->GetTextAlign()); - pFrameData->mpBuffer->SetRasterOp(m_pWindow->GetRasterOp()); - pFrameData->mpBuffer->SetLayoutMode(m_pWindow->GetLayoutMode()); - pFrameData->mpBuffer->SetDigitLanguage(m_pWindow->GetDigitLanguage()); } void PaintHelper::PaintBuffer() @@ -171,9 +212,6 @@ void PaintHelper::PaintBuffer() assert(pFrameData->mbInBufferedPaint); assert(m_bStartedBufferedPaint); - pFrameData->mpBuffer->mnOutOffX = 0; - pFrameData->mpBuffer->mnOutOffY = 0; - // copy the buffer content to the actual window // export VCL_DOUBLEBUFFERING_AVOID_PAINT=1 to see where we are // painting directly instead of using Invalidate() @@ -181,12 +219,6 @@ void PaintHelper::PaintBuffer() // window either above or in eg. an event handler] if (!getenv("VCL_DOUBLEBUFFERING_AVOID_PAINT")) { - // The map mode of m_pWindow and/or the buffer may have changed since - // StartBufferedPaint(), set it back to what it was, otherwise unwanted - // scaling or translating may happen. - m_pWindow->SetMapMode(m_aPaintRectMapMode); - pFrameData->mpBuffer->SetMapMode(m_aPaintRectMapMode); - // Make sure that the +1 value GetSize() adds to the size is in pixels. Size aPaintRectSize; if (m_pWindow->GetMapMode().GetMapUnit() == MAP_PIXEL) @@ -199,6 +231,7 @@ void PaintHelper::PaintBuffer() aPaintRectSize = m_pWindow->PixelToLogic(aRectanglePixel.GetSize()); } + PaintBufferGuard g(pFrameData, m_pWindow); m_pWindow->DrawOutDev(m_aPaintRect.TopLeft(), aPaintRectSize, m_aPaintRect.TopLeft(), aPaintRectSize, *pFrameData->mpBuffer.get()); } } @@ -247,24 +280,11 @@ void PaintHelper::DoPaint(const vcl::Region* pRegion) if (pFrameData->mbInBufferedPaint && m_pWindow->SupportsDoubleBuffering()) { // double-buffering - SetupBuffer(); + PaintBufferGuard g(pFrameData, m_pWindow); m_pWindow->ApplySettings(*pFrameData->mpBuffer.get()); - // temporarily decrease the mnOutOffX/Y of the buffer for the - // subwidgets (because the buffer is our base here) - // FIXME: once everything's double-buffered, this is (hopefully) not - // necessary as the buffer is always created for the main window. - long nOutOffX = pFrameData->mpBuffer->mnOutOffX; - long nOutOffY = pFrameData->mpBuffer->mnOutOffY; - pFrameData->mpBuffer->mnOutOffX = m_pWindow->GetOutOffXPixel() - pFrameData->mpBuffer->mnOutOffX; - pFrameData->mpBuffer->mnOutOffY = m_pWindow->GetOutOffYPixel() - pFrameData->mpBuffer->mnOutOffY; - m_pWindow->PushPaintHelper(this, *pFrameData->mpBuffer.get()); m_pWindow->Paint(*pFrameData->mpBuffer.get(), m_aPaintRect); - - // restore the mnOutOffX/Y value - pFrameData->mpBuffer->mnOutOffX = nOutOffX; - pFrameData->mpBuffer->mnOutOffY = nOutOffY; } else { |