diff options
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/Library_vclplug_win.mk | 1 | ||||
-rw-r--r-- | vcl/inc/opengl/RenderList.hxx | 2 | ||||
-rw-r--r-- | vcl/inc/opengl/gdiimpl.hxx | 1 | ||||
-rw-r--r-- | vcl/inc/opengl/win/gdiimpl.hxx | 37 | ||||
-rw-r--r-- | vcl/inc/opengl/win/winlayout.hxx | 46 | ||||
-rw-r--r-- | vcl/inc/opengl/x11/gdiimpl.hxx | 2 | ||||
-rw-r--r-- | vcl/inc/skia/win/gdiimpl.hxx | 10 | ||||
-rw-r--r-- | vcl/inc/win/saldata.hxx | 4 | ||||
-rw-r--r-- | vcl/inc/win/salgdi.h | 40 | ||||
-rw-r--r-- | vcl/inc/win/wingdiimpl.hxx | 44 | ||||
-rw-r--r-- | vcl/inc/win/winlayout.hxx | 83 | ||||
-rw-r--r-- | vcl/opengl/gdiimpl.cxx | 6 | ||||
-rw-r--r-- | vcl/opengl/win/gdiimpl.cxx | 67 | ||||
-rw-r--r-- | vcl/opengl/win/winlayout.cxx | 56 | ||||
-rw-r--r-- | vcl/skia/win/gdiimpl.cxx | 5 | ||||
-rw-r--r-- | vcl/unx/generic/gdi/gdiimpl.hxx | 2 | ||||
-rw-r--r-- | vcl/win/gdi/gdiimpl.cxx | 4 | ||||
-rw-r--r-- | vcl/win/gdi/gdiimpl.hxx | 10 | ||||
-rw-r--r-- | vcl/win/gdi/salgdi.cxx | 36 | ||||
-rw-r--r-- | vcl/win/gdi/winlayout.cxx | 99 |
20 files changed, 371 insertions, 184 deletions
diff --git a/vcl/Library_vclplug_win.mk b/vcl/Library_vclplug_win.mk index 1b73c2458629..f0dc4ac17fc6 100644 --- a/vcl/Library_vclplug_win.mk +++ b/vcl/Library_vclplug_win.mk @@ -62,6 +62,7 @@ $(eval $(call gb_Library_use_externals,vclplug_win,\ $(eval $(call gb_Library_add_exception_objects,vclplug_win,\ vcl/opengl/win/gdiimpl \ + vcl/opengl/win/winlayout \ vcl/win/app/saldata \ vcl/win/app/salinfo \ vcl/win/app/salinst \ diff --git a/vcl/inc/opengl/RenderList.hxx b/vcl/inc/opengl/RenderList.hxx index e4df834755d6..06dd03b4d7d1 100644 --- a/vcl/inc/opengl/RenderList.hxx +++ b/vcl/inc/opengl/RenderList.hxx @@ -150,7 +150,7 @@ public: return maRenderEntries; } - void addDrawTextureWithMaskColor(OpenGLTexture const & rTexture, Color nColor, const SalTwoRect& r2Rect); + VCL_DLLPUBLIC void addDrawTextureWithMaskColor(OpenGLTexture const & rTexture, Color nColor, const SalTwoRect& r2Rect); void addDrawPixel(long nX, long nY, Color nColor); diff --git a/vcl/inc/opengl/gdiimpl.hxx b/vcl/inc/opengl/gdiimpl.hxx index e90e55458d12..b0b1de88b185 100644 --- a/vcl/inc/opengl/gdiimpl.hxx +++ b/vcl/inc/opengl/gdiimpl.hxx @@ -141,7 +141,6 @@ public: void DrawLinearGradient( const Gradient& rGradient, const tools::Rectangle& rRect ); void DrawAxialGradient( const Gradient& rGradient, const tools::Rectangle& rRect ); void DrawRadialGradient( const Gradient& rGradient, const tools::Rectangle& rRect ); - void DeferredTextDraw(OpenGLTexture const & rTexture, const Color nMaskColor, const SalTwoRect& rPosAry); void FlushDeferredDrawing(); void FlushLinesOrTriangles(DrawShaderType eType, RenderParameters const & rParameters); diff --git a/vcl/inc/opengl/win/gdiimpl.hxx b/vcl/inc/opengl/win/gdiimpl.hxx index 3af0ccbcd344..f7d3865ceec7 100644 --- a/vcl/inc/opengl/win/gdiimpl.hxx +++ b/vcl/inc/opengl/win/gdiimpl.hxx @@ -16,11 +16,34 @@ #include <opengl/gdiimpl.hxx> #include <svdata.hxx> #include <win/salgdi.h> +#include <win/wingdiimpl.hxx> #include <o3tl/lru_map.hxx> #include <vcl/opengl/OpenGLContext.hxx> #include <ControlCacheKey.hxx> -class WinOpenGLSalGraphicsImpl : public OpenGLSalGraphicsImpl +class OpenGLCompatibleDC : public CompatibleDC +{ +public: + OpenGLCompatibleDC(SalGraphics &rGraphics, int x, int y, int width, int height); + + virtual std::unique_ptr<Texture> getTexture() override; + // overload, caller must delete + OpenGLTexture* getOpenGLTexture(); + + virtual bool copyToTexture(Texture& aTexture) override; + + struct Texture; +}; + +struct OpenGLCompatibleDC::Texture : public CompatibleDC::Texture +{ + OpenGLTexture texture; + virtual bool isValid() const { return !!texture; } + virtual int GetWidth() const { return texture.GetWidth(); } + virtual int GetHeight() const { return texture.GetHeight(); } +}; + +class WinOpenGLSalGraphicsImpl : public OpenGLSalGraphicsImpl, public WinSalGraphicsImplBase { friend class WinLayout; private: @@ -42,11 +65,17 @@ public: virtual void Init() override; virtual void copyBits( const SalTwoRect& rPosAry, SalGraphics* pSrcGraphics ) override; + virtual bool UseTextDraw() const override { return true; } + virtual void PreDrawText() override; + virtual void PostDrawText() override; + virtual void DrawMask( CompatibleDC::Texture* rTexture, Color nMaskColor, const SalTwoRect& rPosAry ) override; + using OpenGLSalGraphicsImpl::DrawMask; + virtual void DeferredTextDraw(const CompatibleDC::Texture* pTexture, Color nMaskColor, const SalTwoRect& rPosAry) override; - bool TryRenderCachedNativeControl(ControlCacheKey const & rControlCacheKey, int nX, int nY); + virtual bool TryRenderCachedNativeControl(ControlCacheKey const & rControlCacheKey, int nX, int nY) override; - bool RenderAndCacheNativeControl(OpenGLCompatibleDC& rWhite, OpenGLCompatibleDC& rBlack, - int nX, int nY , ControlCacheKey& aControlCacheKey); + virtual bool RenderAndCacheNativeControl(CompatibleDC& rWhite, CompatibleDC& rBlack, + int nX, int nY , ControlCacheKey& aControlCacheKey) override; }; diff --git a/vcl/inc/opengl/win/winlayout.hxx b/vcl/inc/opengl/win/winlayout.hxx new file mode 100644 index 000000000000..c6ce77bdad4e --- /dev/null +++ b/vcl/inc/opengl/win/winlayout.hxx @@ -0,0 +1,46 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_INC_OPENGL_WIN_WINLAYOUT_HXX +#define INCLUDED_VCL_INC_OPENGL_WIN_WINLAYOUT_HXX + +#include <win/winlayout.hxx> +#include <opengl/PackedTextureAtlas.hxx> + +struct OpenGLGlobalWinGlyphCache : public GlobalWinGlyphCache +{ + OpenGLGlobalWinGlyphCache() + : maPackedTextureAtlas(2048, 2048) + { + } + + PackedTextureAtlasManager maPackedTextureAtlas; + + virtual bool AllocateTexture(WinGlyphDrawElement& rElement, int nWidth, int nHeight) override; +}; + +class OpenGLWinGlyphCache : public WinGlyphCache +{ +public: + void RemoveTextures(std::vector<GLuint>& rTextureIDs); +}; + +#endif // INCLUDED_VCL_INC_OPENGL_WIN_WINLAYOUT_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/opengl/x11/gdiimpl.hxx b/vcl/inc/opengl/x11/gdiimpl.hxx index d0c0c3caf352..d86af9223c54 100644 --- a/vcl/inc/opengl/x11/gdiimpl.hxx +++ b/vcl/inc/opengl/x11/gdiimpl.hxx @@ -32,8 +32,6 @@ protected: virtual rtl::Reference<OpenGLContext> CreateWinContext() override; public: - // implementation of X11GraphicsImpl - virtual void copyBits( const SalTwoRect& rPosAry, SalGraphics* pSrcGraphics ) override; virtual void Init() override; diff --git a/vcl/inc/skia/win/gdiimpl.hxx b/vcl/inc/skia/win/gdiimpl.hxx index 621d8d4b4a78..4c47f02baa95 100644 --- a/vcl/inc/skia/win/gdiimpl.hxx +++ b/vcl/inc/skia/win/gdiimpl.hxx @@ -15,6 +15,7 @@ #include <skia/gdiimpl.hxx> #include <win/salgdi.h> +#include <win/wingdiimpl.hxx> class ControlCacheKey; namespace sk_app @@ -22,7 +23,7 @@ namespace sk_app class WindowContext; } -class WinSkiaSalGraphicsImpl : public SkiaSalGraphicsImpl +class WinSkiaSalGraphicsImpl : public SkiaSalGraphicsImpl, public WinSalGraphicsImplBase { private: WinSalGraphics& mWinParent; @@ -36,10 +37,11 @@ public: virtual void freeResources() override; - bool TryRenderCachedNativeControl(ControlCacheKey const& rControlCacheKey, int nX, int nY); + virtual bool TryRenderCachedNativeControl(ControlCacheKey const& rControlCacheKey, int nX, + int nY) override; - bool RenderAndCacheNativeControl(OpenGLCompatibleDC& rWhite, OpenGLCompatibleDC& rBlack, int nX, - int nY, ControlCacheKey& aControlCacheKey); + virtual bool RenderAndCacheNativeControl(CompatibleDC& rWhite, CompatibleDC& rBlack, int nX, + int nY, ControlCacheKey& aControlCacheKey) override; protected: virtual void createSurface() override; diff --git a/vcl/inc/win/saldata.hxx b/vcl/inc/win/saldata.hxx index dd08b7553734..e9889e6653d1 100644 --- a/vcl/inc/win/saldata.hxx +++ b/vcl/inc/win/saldata.hxx @@ -38,7 +38,7 @@ class WinSalFrame; class WinSalVirtualDevice; class WinSalPrinter; namespace vcl { class Font; } -struct GlobalOpenGLGlyphCache; +struct GlobalWinGlyphCache; struct HDCCache; struct TempFontItem; class TextOutRenderer; @@ -122,7 +122,7 @@ public: std::unique_ptr<TextOutRenderer> m_pD2DWriteTextOutRenderer; // tdf#107205 need 2 instances because D2DWrite can't rotate text std::unique_ptr<TextOutRenderer> m_pExTextOutRenderer; - std::unique_ptr<GlobalOpenGLGlyphCache> m_pGlobalOpenGLGlyphCache; + std::unique_ptr<GlobalWinGlyphCache> m_pGlobalWinGlyphCache; std::unique_ptr<TheTextureCache> m_pTextureCache; }; diff --git a/vcl/inc/win/salgdi.h b/vcl/inc/win/salgdi.h index d6d8dea14c24..f7fb206624b5 100644 --- a/vcl/inc/win/salgdi.h +++ b/vcl/inc/win/salgdi.h @@ -45,10 +45,9 @@ class FontSelectPattern; class WinFontInstance; class ImplFontAttrCache; -class OpenGLTexture; class PhysicalFontCollection; class SalGraphicsImpl; -class WinOpenGLSalGraphicsImpl; +class WinSalGraphicsImplBase; class ImplFontMetricData; #define RGB_TO_PALRGB(nRGB) ((nRGB)|0x02000000) @@ -95,11 +94,12 @@ private: /** Class that creates (and destroys) a compatible Device Context. -This is to be used for GDI drawing into a DIB that we later use as a texture for OpenGL drawing. +This is to be used for GDI drawing into a DIB that we later use for a different +drawing method, such as a texture for OpenGL drawing or surface for Skia drawing. */ -class OpenGLCompatibleDC +class CompatibleDC { -private: +protected: /// The compatible DC that we create for our purposes. HDC mhCompatibleDC; @@ -115,12 +115,16 @@ private: /// Mapping between the GDI position and OpenGL, to use for OpenGL drawing. SalTwoRect maRects; - /// The OpenGL-based SalGraphicsImpl where we will draw. If null, we ignore the drawing, it means it happened directly to the DC... - WinOpenGLSalGraphicsImpl *mpImpl; + /// The SalGraphicsImpl where we will draw. If null, we ignore the drawing, it means it happened directly to the DC... + WinSalGraphicsImplBase *mpImpl; + + // If 'disable' is true, this class is a simple wrapper for drawing directly. Subclasses should use true. + CompatibleDC(SalGraphics &rGraphics, int x, int y, int width, int height, bool disable=true); public: - OpenGLCompatibleDC(SalGraphics &rGraphics, int x, int y, int width, int height); - ~OpenGLCompatibleDC(); + static std::unique_ptr< CompatibleDC > create(SalGraphics &rGraphics, int x, int y, int width, int height); + + virtual ~CompatibleDC(); HDC getCompatibleHDC() { return mhCompatibleDC; } @@ -131,11 +135,22 @@ public: /// Reset the DC with the defined color. void fill(sal_uInt32 color); - /// Obtain the texture; the caller must delete it after use. - OpenGLTexture* getTexture(); + /// Base texture class (OpenGL and Skia will provide their implementations). + struct Texture; + + /// Obtain the texture. + virtual std::unique_ptr<Texture> getTexture() { abort(); }; /// Copy bitmap data to the texture. Texture must be initialized and the correct size to hold the bitmap. - bool copyToTexture(OpenGLTexture& aTexture); + virtual bool copyToTexture(Texture& /*aTexture*/) { abort(); }; +}; + +struct CompatibleDC::Texture +{ + virtual ~Texture() = 0 {}; + virtual bool isValid() const = 0; + virtual int GetWidth() const = 0; + virtual int GetHeight() const = 0; }; class WinSalGraphics : public SalGraphics @@ -143,7 +158,6 @@ class WinSalGraphics : public SalGraphics friend class WinSalGraphicsImpl; friend class WinOpenGLSalGraphicsImpl; friend class ScopedFont; - friend class OpenGLCompatibleDC; protected: std::unique_ptr<SalGraphicsImpl> mpImpl; diff --git a/vcl/inc/win/wingdiimpl.hxx b/vcl/inc/win/wingdiimpl.hxx new file mode 100644 index 000000000000..d283f4c2bb5c --- /dev/null +++ b/vcl/inc/win/wingdiimpl.hxx @@ -0,0 +1,44 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_VCL_INC_WIN_WINGDIIMPL_HXX +#define INCLUDED_VCL_INC_WIN_WINGDIIMPL_HXX + +#include <win/salgdi.h> +#include <ControlCacheKey.hxx> + +class ControlCacheKey; + +// Base class for some functionality that OpenGL/Skia/GDI backends must each implement. +class WinSalGraphicsImplBase +{ +public: + virtual ~WinSalGraphicsImplBase(){}; + + virtual bool TryRenderCachedNativeControl(ControlCacheKey const& rControlCacheKey, int nX, + int nY) + = 0; + + virtual bool RenderAndCacheNativeControl(CompatibleDC& rWhite, CompatibleDC& rBlack, int nX, + int nY, ControlCacheKey& aControlCacheKey) + = 0; + + // If true is returned, the following functions are used for text rendering. + virtual bool UseTextDraw() const { return false; } + virtual void PreDrawText() {} + virtual void PostDrawText() {} + virtual void DrawMask(CompatibleDC::Texture* /*rTexture*/, Color /*nMaskColor*/, + const SalTwoRect& /*rPosAry*/){}; + virtual void DeferredTextDraw(const CompatibleDC::Texture* /*pTexture*/, Color /*nMaskColor*/, + const SalTwoRect& /*rPosAry*/){}; +}; + +#endif // INCLUDED_VCL_INC_WIN_WINGDIIMPL_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/win/winlayout.hxx b/vcl/inc/win/winlayout.hxx index 035998e2bcd9..aef394fa83e3 100644 --- a/vcl/inc/win/winlayout.hxx +++ b/vcl/inc/win/winlayout.hxx @@ -26,8 +26,6 @@ #include <svsys.h> #include <win/salgdi.h> -#include <opengl/PackedTextureAtlas.hxx> - class WinFontInstance; namespace @@ -38,11 +36,11 @@ const int GLYPH_SPACE_RATIO = 8; const int GLYPH_OFFSET_RATIO = GLYPH_SPACE_RATIO * 2; } -struct OpenGLGlyphDrawElement +struct WinGlyphDrawElement { tools::Rectangle maLocation; int maLeftOverhangs; - OpenGLTexture maTexture; + std::unique_ptr<CompatibleDC::Texture> maTexture; int mnBaselineOffset; int mnHeight; bool mbVertical; @@ -58,87 +56,48 @@ struct OpenGLGlyphDrawElement } }; -class OpenGLGlyphCache; +class WinGlyphCache; -struct GlobalOpenGLGlyphCache +struct GlobalWinGlyphCache { - GlobalOpenGLGlyphCache() - : maPackedTextureAtlas(2048, 2048) - {} + std::unordered_set<WinGlyphCache*> maWinGlyphCaches; - PackedTextureAtlasManager maPackedTextureAtlas; - std::unordered_set<OpenGLGlyphCache*> maOpenGLGlyphCaches; + static GlobalWinGlyphCache * get(); - static GlobalOpenGLGlyphCache * get(); + virtual bool AllocateTexture(WinGlyphDrawElement& rElement, int nWidth, int nHeight) = 0; }; -class OpenGLGlyphCache +class WinGlyphCache { -private: - std::unordered_map<int, OpenGLGlyphDrawElement> maOpenGLTextureCache; +protected: + std::unordered_map<int, WinGlyphDrawElement> maWinTextureCache; public: - OpenGLGlyphCache() - { - GlobalOpenGLGlyphCache::get()->maOpenGLGlyphCaches.insert(this); - } - - ~OpenGLGlyphCache() - { - GlobalOpenGLGlyphCache::get()->maOpenGLGlyphCaches.erase(this); - } - - static bool ReserveTextureSpace(OpenGLGlyphDrawElement& rElement, int nWidth, int nHeight) + WinGlyphCache() { - GlobalOpenGLGlyphCache* pGlobalOpenGLGlyphCache = GlobalOpenGLGlyphCache::get(); - rElement.maTexture = pGlobalOpenGLGlyphCache->maPackedTextureAtlas.Reserve(nWidth, nHeight); - if (!rElement.maTexture) - return false; - std::vector<GLuint> aTextureIDs = pGlobalOpenGLGlyphCache->maPackedTextureAtlas.ReduceTextureNumber(8); - if (!aTextureIDs.empty()) - { - for (auto& pOpenGLGlyphCache: pGlobalOpenGLGlyphCache->maOpenGLGlyphCaches) - { - pOpenGLGlyphCache->RemoveTextures(aTextureIDs); - } - } - return true; + GlobalWinGlyphCache::get()->maWinGlyphCaches.insert(this); } - void RemoveTextures(std::vector<GLuint>& rTextureIDs) + virtual ~WinGlyphCache() { - auto it = maOpenGLTextureCache.begin(); - - while (it != maOpenGLTextureCache.end()) - { - GLuint nTextureID = it->second.maTexture.Id(); - - if (std::find(rTextureIDs.begin(), rTextureIDs.end(), nTextureID) != rTextureIDs.end()) - { - it = maOpenGLTextureCache.erase(it); - } - else - { - ++it; - } - } + GlobalWinGlyphCache::get()->maWinGlyphCaches.erase(this); } - void PutDrawElementInCache(const OpenGLGlyphDrawElement& rElement, int nGlyphIndex) + void PutDrawElementInCache(WinGlyphDrawElement&& rElement, int nGlyphIndex) { assert(!IsGlyphCached(nGlyphIndex)); - maOpenGLTextureCache[nGlyphIndex] = rElement; + maWinTextureCache[nGlyphIndex] = std::move( rElement ); } - OpenGLGlyphDrawElement& GetDrawElement(int nGlyphIndex) + WinGlyphDrawElement& GetDrawElement(int nGlyphIndex) { assert(IsGlyphCached(nGlyphIndex)); - return maOpenGLTextureCache[nGlyphIndex]; + return maWinTextureCache[nGlyphIndex]; } bool IsGlyphCached(int nGlyphIndex) const { - return maOpenGLTextureCache.find(nGlyphIndex) != maOpenGLTextureCache.end(); + return maWinTextureCache.find(nGlyphIndex) != maWinTextureCache.end(); } }; @@ -167,7 +126,7 @@ public: WinFontFace * GetFontFace() { return static_cast<WinFontFace *>(LogicalFontInstance::GetFontFace()); } bool CacheGlyphToAtlas(HDC hDC, HFONT hFont, int nGlyphIndex, SalGraphics& rGraphics, const GenericSalLayout& rLayout); - OpenGLGlyphCache& GetOpenGLGlyphCache() { return maOpenGLGlyphCache; } + WinGlyphCache& GetWinGlyphCache() { return maWinGlyphCache; } bool GetGlyphOutline(sal_GlyphId, basegfx::B2DPolyPolygon&, bool) const override; @@ -180,7 +139,7 @@ private: WinSalGraphics *m_pGraphics; HFONT m_hFont; float m_fScale; - OpenGLGlyphCache maOpenGLGlyphCache; + WinGlyphCache maWinGlyphCache; }; class TextOutRenderer diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx index 30d2299978ea..0f0e40dd7eaa 100644 --- a/vcl/opengl/gdiimpl.cxx +++ b/vcl/opengl/gdiimpl.cxx @@ -1324,12 +1324,6 @@ void OpenGLSalGraphicsImpl::DrawMask( OpenGLTexture& rMask, Color nMaskColor, co mpProgram->Clean(); } -void OpenGLSalGraphicsImpl::DeferredTextDraw(OpenGLTexture const & rTexture, Color aMaskColor, const SalTwoRect& rPosAry) -{ - mpRenderList->addDrawTextureWithMaskColor(rTexture, aMaskColor, rPosAry); - PostBatchDraw(); -} - void OpenGLSalGraphicsImpl::FlushLinesOrTriangles(DrawShaderType eType, RenderParameters const & rParameters) { if (!UseProgram("combinedVertexShader", "combinedFragmentShader", "#define USE_VERTEX_COLORS")) diff --git a/vcl/opengl/win/gdiimpl.cxx b/vcl/opengl/win/gdiimpl.cxx index b0d1188519c2..d71a03714198 100644 --- a/vcl/opengl/win/gdiimpl.cxx +++ b/vcl/opengl/win/gdiimpl.cxx @@ -756,6 +756,37 @@ ControlCacheType & TheTextureCache::get() { return data->m_pTextureCache->cache; } +OpenGLCompatibleDC::OpenGLCompatibleDC(SalGraphics &rGraphics, int x, int y, int width, int height) +: CompatibleDC( rGraphics, x, y, width, height, false ) +{ +} + +OpenGLTexture* OpenGLCompatibleDC::getOpenGLTexture() +{ + if (!mpImpl) + return nullptr; + + // turn what's in the mpData into a texture + return new OpenGLTexture(maRects.mnSrcWidth, maRects.mnSrcHeight, GL_BGRA, GL_UNSIGNED_BYTE, mpData); +} + +std::unique_ptr<CompatibleDC::Texture> OpenGLCompatibleDC::getTexture() +{ + auto ret = std::make_unique<OpenGLCompatibleDC::Texture>(); + ret->texture = OpenGLTexture(maRects.mnSrcWidth, maRects.mnSrcHeight, GL_BGRA, GL_UNSIGNED_BYTE, mpData); + return ret; +} + +bool OpenGLCompatibleDC::copyToTexture(CompatibleDC::Texture& aTexture) +{ + if (!mpImpl) + return false; + + assert(dynamic_cast<OpenGLCompatibleDC::Texture*>(&aTexture)); + return static_cast<OpenGLCompatibleDC::Texture&>(aTexture).texture.CopyData( + maRects.mnSrcWidth, maRects.mnSrcHeight, GL_BGRA, GL_UNSIGNED_BYTE, reinterpret_cast<sal_uInt8*>(mpData)); +} + bool WinOpenGLSalGraphicsImpl::TryRenderCachedNativeControl(ControlCacheKey const & rControlCacheKey, int nX, int nY) { static bool gbCacheEnabled = !getenv("SAL_WITHOUT_WIDGET_CACHE"); @@ -801,8 +832,8 @@ bool WinOpenGLSalGraphicsImpl::RenderCompatibleDC(OpenGLCompatibleDC& rWhite, Op PreDraw(); - rCombo.mpTexture.reset(rWhite.getTexture()); - rCombo.mpMask.reset(rBlack.getTexture()); + rCombo.mpTexture.reset(rWhite.getOpenGLTexture()); + rCombo.mpMask.reset(rBlack.getOpenGLTexture()); bRet = RenderTextureCombo(rCombo, nX, nY); @@ -810,12 +841,16 @@ bool WinOpenGLSalGraphicsImpl::RenderCompatibleDC(OpenGLCompatibleDC& rWhite, Op return bRet; } -bool WinOpenGLSalGraphicsImpl::RenderAndCacheNativeControl(OpenGLCompatibleDC& rWhite, OpenGLCompatibleDC& rBlack, +bool WinOpenGLSalGraphicsImpl::RenderAndCacheNativeControl(CompatibleDC& rWhite, CompatibleDC& rBlack, int nX, int nY , ControlCacheKey& aControlCacheKey) { + assert(dynamic_cast<OpenGLCompatibleDC*>(&rWhite)); + assert(dynamic_cast<OpenGLCompatibleDC*>(&rBlack)); + std::unique_ptr<TextureCombo> pCombo(new TextureCombo); - bool bResult = RenderCompatibleDC(rWhite, rBlack, nX, nY, *pCombo); + bool bResult = RenderCompatibleDC(static_cast<OpenGLCompatibleDC&>(rWhite), + static_cast<OpenGLCompatibleDC&>(rBlack), nX, nY, *pCombo); if (!bResult) return false; @@ -828,4 +863,28 @@ bool WinOpenGLSalGraphicsImpl::RenderAndCacheNativeControl(OpenGLCompatibleDC& r return bResult; } +void WinOpenGLSalGraphicsImpl::PreDrawText() +{ + PreDraw(); +} + +void WinOpenGLSalGraphicsImpl::PostDrawText() +{ + PostDraw(); +} + +void WinOpenGLSalGraphicsImpl::DeferredTextDraw(const CompatibleDC::Texture* pTexture, Color aMaskColor, const SalTwoRect& rPosAry) +{ + assert(dynamic_cast<const OpenGLCompatibleDC::Texture*>(pTexture)); + mpRenderList->addDrawTextureWithMaskColor( + static_cast<const OpenGLCompatibleDC::Texture*>(pTexture)->texture, aMaskColor, rPosAry); + PostBatchDraw(); +} + +void WinOpenGLSalGraphicsImpl::DrawMask( CompatibleDC::Texture* pTexture, Color nMaskColor, const SalTwoRect& rPosAry ) +{ + assert(dynamic_cast<OpenGLCompatibleDC::Texture*>(pTexture)); + DrawMask( static_cast<OpenGLCompatibleDC::Texture*>(pTexture)->texture, nMaskColor, rPosAry ); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/opengl/win/winlayout.cxx b/vcl/opengl/win/winlayout.cxx new file mode 100644 index 000000000000..ddc72c8b28cf --- /dev/null +++ b/vcl/opengl/win/winlayout.cxx @@ -0,0 +1,56 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <opengl/win/winlayout.hxx> + +#include <opengl/win/gdiimpl.hxx> + +bool OpenGLGlobalWinGlyphCache::AllocateTexture(WinGlyphDrawElement& rElement, int nWidth, + int nHeight) +{ + assert(rElement.maTexture.get() == nullptr); + OpenGLCompatibleDC::Texture* texture = new OpenGLCompatibleDC::Texture; + rElement.maTexture.reset(texture); + texture->texture = maPackedTextureAtlas.Reserve(nWidth, nHeight); + if (!texture->texture) + return false; + std::vector<GLuint> aTextureIDs = maPackedTextureAtlas.ReduceTextureNumber(8); + if (!aTextureIDs.empty()) + { + for (auto& pWinGlyphCache : maWinGlyphCaches) + { + assert(dynamic_cast<OpenGLWinGlyphCache*>(pWinGlyphCache)); + static_cast<OpenGLWinGlyphCache*>(pWinGlyphCache)->RemoveTextures(aTextureIDs); + } + } + return true; +} + +void OpenGLWinGlyphCache::RemoveTextures(std::vector<GLuint>& rTextureIDs) +{ + auto it = maWinTextureCache.begin(); + + while (it != maWinTextureCache.end()) + { + assert(dynamic_cast<OpenGLCompatibleDC::Texture*>(it->second.maTexture.get())); + GLuint nTextureID + = static_cast<OpenGLCompatibleDC::Texture*>(it->second.maTexture.get())->texture.Id(); + + if (std::find(rTextureIDs.begin(), rTextureIDs.end(), nTextureID) != rTextureIDs.end()) + { + it = maWinTextureCache.erase(it); + } + else + { + ++it; + } + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/skia/win/gdiimpl.cxx b/vcl/skia/win/gdiimpl.cxx index 0763334f0ebf..ccfd59572424 100644 --- a/vcl/skia/win/gdiimpl.cxx +++ b/vcl/skia/win/gdiimpl.cxx @@ -87,9 +87,8 @@ bool WinSkiaSalGraphicsImpl::TryRenderCachedNativeControl(ControlCacheKey const& return false; // TODO } -// TODO OpenGLCompatibleDC? -bool WinSkiaSalGraphicsImpl::RenderAndCacheNativeControl(OpenGLCompatibleDC& rWhite, - OpenGLCompatibleDC& rBlack, int nX, int nY, +bool WinSkiaSalGraphicsImpl::RenderAndCacheNativeControl(CompatibleDC& rWhite, CompatibleDC& rBlack, + int nX, int nY, ControlCacheKey& aControlCacheKey) { (void)rWhite; diff --git a/vcl/unx/generic/gdi/gdiimpl.hxx b/vcl/unx/generic/gdi/gdiimpl.hxx index 315ed4094f8b..edacdac787c5 100644 --- a/vcl/unx/generic/gdi/gdiimpl.hxx +++ b/vcl/unx/generic/gdi/gdiimpl.hxx @@ -283,8 +283,6 @@ public: virtual bool drawGradient(const tools::PolyPolygon& rPolygon, const Gradient& rGradient) override; public: - // implementation of X11GraphicsImpl - void Init() override; }; diff --git a/vcl/win/gdi/gdiimpl.cxx b/vcl/win/gdi/gdiimpl.cxx index 79621f53bf60..f63258b83dd2 100644 --- a/vcl/win/gdi/gdiimpl.cxx +++ b/vcl/win/gdi/gdiimpl.cxx @@ -2576,12 +2576,12 @@ bool WinSalGraphicsImpl::drawGradient(const tools::PolyPolygon& /*rPolygon*/, return false; } -bool WinSalGraphicsImpl::TryRenderCachedNativeControl(ControlCacheKey& /*rControlCacheKey*/, int /*nX*/, int /*nY*/) +bool WinSalGraphicsImpl::TryRenderCachedNativeControl(const ControlCacheKey& /*rControlCacheKey*/, int /*nX*/, int /*nY*/) { return false; } -bool WinSalGraphicsImpl::RenderAndCacheNativeControl(OpenGLCompatibleDC& /*rWhite*/, OpenGLCompatibleDC& /*rBlack*/, +bool WinSalGraphicsImpl::RenderAndCacheNativeControl(CompatibleDC& /*rWhite*/, CompatibleDC& /*rBlack*/, int /*nX*/, int /*nY*/ , ControlCacheKey& /*aControlCacheKey*/) { return false; diff --git a/vcl/win/gdi/gdiimpl.hxx b/vcl/win/gdi/gdiimpl.hxx index bc4a6ac27414..d7d37557565c 100644 --- a/vcl/win/gdi/gdiimpl.hxx +++ b/vcl/win/gdi/gdiimpl.hxx @@ -22,6 +22,7 @@ #include <salgdiimpl.hxx> #include <win/salgdi.h> +#include <win/wingdiimpl.hxx> #include <vcl/gradient.hxx> @@ -30,7 +31,7 @@ class WinSalGraphics; -class WinSalGraphicsImpl : public SalGraphicsImpl +class WinSalGraphicsImpl : public SalGraphicsImpl, public WinSalGraphicsImplBase { private: @@ -238,10 +239,11 @@ public: virtual bool drawGradient(const tools::PolyPolygon& rPolygon, const Gradient& rGradient) override; - virtual bool TryRenderCachedNativeControl(ControlCacheKey& rControlCacheKey, int nX, int nY); + virtual bool TryRenderCachedNativeControl(const ControlCacheKey& rControlCacheKey, + int nX, int nY) override; - virtual bool RenderAndCacheNativeControl(OpenGLCompatibleDC& rWhite, OpenGLCompatibleDC& rBlack, - int nX, int nY , ControlCacheKey& aControlCacheKey); + virtual bool RenderAndCacheNativeControl(CompatibleDC& rWhite, CompatibleDC& rBlack, + int nX, int nY , ControlCacheKey& aControlCacheKey) override; }; #endif // INCLUDED_VCL_WIN_GDI_GDIIMPL_HXX diff --git a/vcl/win/gdi/salgdi.cxx b/vcl/win/gdi/salgdi.cxx index 6da451de36aa..29c6f83e11f6 100644 --- a/vcl/win/gdi/salgdi.cxx +++ b/vcl/win/gdi/salgdi.cxx @@ -547,21 +547,30 @@ void ImplClearHDCCache( SalData* pData ) } } -OpenGLCompatibleDC::OpenGLCompatibleDC(SalGraphics &rGraphics, int x, int y, int width, int height) +std::unique_ptr< CompatibleDC > CompatibleDC::create(SalGraphics &rGraphics, int x, int y, int width, int height) +{ + if (OpenGLHelper::isVCLOpenGLEnabled()) + return std::make_unique< OpenGLCompatibleDC >( rGraphics, x, y, width, height ); + return std::unique_ptr< CompatibleDC >( new CompatibleDC( rGraphics, x, y, width, height )); +} + +CompatibleDC::CompatibleDC(SalGraphics &rGraphics, int x, int y, int width, int height, bool disable) : mhBitmap(nullptr) , mpData(nullptr) , maRects(0, 0, width, height, x, y, width, height) + , mpImpl(nullptr) { WinSalGraphics& rWinGraphics = static_cast<WinSalGraphics&>(rGraphics); - mpImpl = dynamic_cast<WinOpenGLSalGraphicsImpl*>(rWinGraphics.mpImpl.get()); - if (!mpImpl) + if( disable ) { // we avoid the OpenGL drawing, instead we draw directly to the DC mhCompatibleDC = rWinGraphics.getHDC(); return; } + mpImpl = dynamic_cast<WinSalGraphicsImplBase*>(rWinGraphics.GetImpl()); + assert(mpImpl != nullptr); mhCompatibleDC = CreateCompatibleDC(rWinGraphics.getHDC()); // move the origin so that we always paint at 0,0 - to keep the bitmap @@ -573,7 +582,7 @@ OpenGLCompatibleDC::OpenGLCompatibleDC(SalGraphics &rGraphics, int x, int y, int mhOrigBitmap = static_cast<HBITMAP>(SelectObject(mhCompatibleDC, mhBitmap)); } -OpenGLCompatibleDC::~OpenGLCompatibleDC() +CompatibleDC::~CompatibleDC() { if (mpImpl) { @@ -583,7 +592,7 @@ OpenGLCompatibleDC::~OpenGLCompatibleDC() } } -void OpenGLCompatibleDC::fill(sal_uInt32 color) +void CompatibleDC::fill(sal_uInt32 color) { if (!mpData) return; @@ -593,23 +602,6 @@ void OpenGLCompatibleDC::fill(sal_uInt32 color) *p++ = color; } -OpenGLTexture* OpenGLCompatibleDC::getTexture() -{ - if (!mpImpl) - return nullptr; - - // turn what's in the mpData into a texture - return new OpenGLTexture(maRects.mnSrcWidth, maRects.mnSrcHeight, GL_BGRA, GL_UNSIGNED_BYTE, mpData); -} - -bool OpenGLCompatibleDC::copyToTexture(OpenGLTexture& aTexture) -{ - if (!mpImpl) - return false; - - return aTexture.CopyData(maRects.mnSrcWidth, maRects.mnSrcHeight, GL_BGRA, GL_UNSIGNED_BYTE, reinterpret_cast<sal_uInt8*>(mpData)); -} - WinSalGraphics::WinSalGraphics(WinSalGraphics::Type eType, bool bScreen, HWND hWnd, SalGeometryProvider *pProvider): mhLocalDC(nullptr), mbPrinter(eType == WinSalGraphics::PRINTER), diff --git a/vcl/win/gdi/winlayout.cxx b/vcl/win/gdi/winlayout.cxx index 7fa273a79c97..9305f38e9dd9 100644 --- a/vcl/win/gdi/winlayout.cxx +++ b/vcl/win/gdi/winlayout.cxx @@ -26,12 +26,13 @@ #include <comphelper/windowserrorstring.hxx> #include <comphelper/scopeguard.hxx> -#include <opengl/texture.hxx> #include <opengl/win/gdiimpl.hxx> +#include <opengl/win/winlayout.hxx> #include <vcl/opengl/OpenGLHelper.hxx> #include <win/salgdi.h> #include <win/saldata.hxx> +#include <win/wingdiimpl.hxx> #include <outdev.h> #include <win/DWriteTextRenderer.hxx> @@ -51,18 +52,18 @@ #include <shlwapi.h> #include <winver.h> -GlobalOpenGLGlyphCache * GlobalOpenGLGlyphCache::get() +GlobalWinGlyphCache * GlobalWinGlyphCache::get() { SalData *data = GetSalData(); - if (!data->m_pGlobalOpenGLGlyphCache) - data->m_pGlobalOpenGLGlyphCache.reset(new GlobalOpenGLGlyphCache); - return data->m_pGlobalOpenGLGlyphCache.get(); + if (!data->m_pGlobalWinGlyphCache) // TODO SKIA + data->m_pGlobalWinGlyphCache.reset(new OpenGLGlobalWinGlyphCache); + return data->m_pGlobalWinGlyphCache.get(); } bool WinFontInstance::CacheGlyphToAtlas(HDC hDC, HFONT hFont, int nGlyphIndex, SalGraphics& rGraphics, const GenericSalLayout& rLayout) { - OpenGLGlyphDrawElement aElement; + WinGlyphDrawElement aElement; ScopedHDC aHDC(CreateCompatibleDC(hDC)); @@ -144,14 +145,14 @@ bool WinFontInstance::CacheGlyphToAtlas(HDC hDC, HFONT hFont, int nGlyphIndex, aElement.maLocation.SetBottom(bounds.getHeight() + aElement.getExtraSpace()); nPos = aEnds[0]; - OpenGLCompatibleDC aDC(rGraphics, 0, 0, nBitmapWidth, nBitmapHeight); + std::unique_ptr<CompatibleDC> aDC(CompatibleDC::create(rGraphics, 0, 0, nBitmapWidth, nBitmapHeight)); - SetTextColor(aDC.getCompatibleHDC(), RGB(0, 0, 0)); - SetBkColor(aDC.getCompatibleHDC(), RGB(255, 255, 255)); + SetTextColor(aDC->getCompatibleHDC(), RGB(0, 0, 0)); + SetBkColor(aDC->getCompatibleHDC(), RGB(255, 255, 255)); - aDC.fill(RGB(0xff, 0xff, 0xff)); + aDC->fill(RGB(0xff, 0xff, 0xff)); - pTxt->BindDC(aDC.getCompatibleHDC(), tools::Rectangle(0, 0, nBitmapWidth, nBitmapHeight)); + pTxt->BindDC(aDC->getCompatibleHDC(), tools::Rectangle(0, 0, nBitmapWidth, nBitmapHeight)); auto pRT = pTxt->GetRenderTarget(); ID2D1SolidColorBrush* pBrush = nullptr; @@ -193,12 +194,12 @@ bool WinFontInstance::CacheGlyphToAtlas(HDC hDC, HFONT hFont, int nGlyphIndex, return false; } - if (!OpenGLGlyphCache::ReserveTextureSpace(aElement, nBitmapWidth, nBitmapHeight)) + if (!GlobalWinGlyphCache::get()->AllocateTexture(aElement, nBitmapWidth, nBitmapHeight)) return false; - if (!aDC.copyToTexture(aElement.maTexture)) + if (!aDC->copyToTexture(*aElement.maTexture.get())) return false; - maOpenGLGlyphCache.PutDrawElementInCache(aElement, nGlyphIndex); + maWinGlyphCache.PutDrawElementInCache(std::move(aElement), nGlyphIndex); return true; } @@ -457,7 +458,7 @@ bool WinSalGraphics::CacheGlyphs(const GenericSalLayout& rLayout) const GlyphItem* pGlyph; while (rLayout.GetNextGlyph(&pGlyph, aPos, nStart)) { - if (!rFont.GetOpenGLGlyphCache().IsGlyphCached(pGlyph->glyphId())) + if (!rFont.GetWinGlyphCache().IsGlyphCached(pGlyph->glyphId())) { if (!rFont.CacheGlyphToAtlas(hDC, hFONT, pGlyph->glyphId(), *this, rLayout)) return false; @@ -489,19 +490,19 @@ bool WinSalGraphics::DrawCachedGlyphs(const GenericSalLayout& rLayout) const GlyphItem* pGlyph; while (rLayout.GetNextGlyph(&pGlyph, aPos, nStart)) { - OpenGLGlyphDrawElement& rElement(rFont.GetOpenGLGlyphCache().GetDrawElement(pGlyph->glyphId())); - OpenGLTexture& rTexture = rElement.maTexture; + WinGlyphDrawElement& rElement(rFont.GetWinGlyphCache().GetDrawElement(pGlyph->glyphId())); + const CompatibleDC::Texture* texture = rElement.maTexture.get(); - if (!rTexture) + if (!texture || !texture->isValid()) return false; SalTwoRect a2Rects(0, 0, - rTexture.GetWidth(), rTexture.GetHeight(), + texture->GetWidth(), texture->GetHeight(), aPos.X() - rElement.getExtraOffset() + rElement.maLeftOverhangs, aPos.Y() - rElement.mnBaselineOffset - rElement.getExtraOffset(), - rTexture.GetWidth(), rTexture.GetHeight()); + texture->GetWidth(), texture->GetHeight()); - pImpl->DeferredTextDraw(rTexture, salColor, a2Rects); + pImpl->DeferredTextDraw(texture, salColor, a2Rects); } return true; @@ -519,14 +520,14 @@ void WinSalGraphics::DrawTextLayout(const GenericSalLayout& rLayout) const WinFontInstance* pWinFont = static_cast<const WinFontInstance*>(&rLayout.GetFont()); const HFONT hLayoutFont = pWinFont->GetHFONT(); - // TODO SKIA - bool bUseOpenGL = OpenGLHelper::isVCLOpenGLEnabled() && !mbPrinter; + WinSalGraphicsImplBase* pImpl = dynamic_cast<WinSalGraphicsImplBase*>(mpImpl.get()); + bool bUseClassic = !pImpl->UseTextDraw() || mbPrinter; // Our DirectWrite renderer is incomplete, skip it for vertical text where glyphs are not // rotated. bool bForceGDI = rLayout.GetFont().GetFontSelectPattern().mbVertical; - if (!bUseOpenGL) + if (bUseClassic) { // no OpenGL, just classic rendering const HFONT hOrigFont = ::SelectFont(hDC, hLayoutFont); @@ -568,45 +569,39 @@ void WinSalGraphics::DrawTextLayout(const GenericSalLayout& rLayout) tools::Rectangle aRect; rLayout.GetBoundRect(aRect); - // TODO SKIA - WinOpenGLSalGraphicsImpl *pImpl = dynamic_cast<WinOpenGLSalGraphicsImpl*>(mpImpl.get()); - - if (pImpl) - { - pImpl->PreDraw(); + pImpl->PreDrawText(); - OpenGLCompatibleDC aDC(*this, aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight()); + std::unique_ptr<CompatibleDC> aDC(CompatibleDC::create(*this, aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight())); - // we are making changes to the DC, make sure we got a new one - assert(aDC.getCompatibleHDC() != hDC); + // we are making changes to the DC, make sure we got a new one + assert(aDC->getCompatibleHDC() != hDC); - RECT aWinRect = { aRect.Left(), aRect.Top(), aRect.Left() + aRect.GetWidth(), aRect.Top() + aRect.GetHeight() }; - ::FillRect(aDC.getCompatibleHDC(), &aWinRect, static_cast<HBRUSH>(::GetStockObject(WHITE_BRUSH))); + RECT aWinRect = { aRect.Left(), aRect.Top(), aRect.Left() + aRect.GetWidth(), aRect.Top() + aRect.GetHeight() }; + ::FillRect(aDC->getCompatibleHDC(), &aWinRect, static_cast<HBRUSH>(::GetStockObject(WHITE_BRUSH))); - // setup the hidden DC with black color and white background, we will - // use the result of the text drawing later as a mask only - const HFONT hOrigFont = ::SelectFont(aDC.getCompatibleHDC(), hLayoutFont); + // setup the hidden DC with black color and white background, we will + // use the result of the text drawing later as a mask only + const HFONT hOrigFont = ::SelectFont(aDC->getCompatibleHDC(), hLayoutFont); - ::SetTextColor(aDC.getCompatibleHDC(), RGB(0, 0, 0)); - ::SetBkColor(aDC.getCompatibleHDC(), RGB(255, 255, 255)); + ::SetTextColor(aDC->getCompatibleHDC(), RGB(0, 0, 0)); + ::SetBkColor(aDC->getCompatibleHDC(), RGB(255, 255, 255)); - UINT nTextAlign = ::GetTextAlign(hDC); - ::SetTextAlign(aDC.getCompatibleHDC(), nTextAlign); + UINT nTextAlign = ::GetTextAlign(hDC); + ::SetTextAlign(aDC->getCompatibleHDC(), nTextAlign); - COLORREF color = ::GetTextColor(hDC); - Color salColor(GetRValue(color), GetGValue(color), GetBValue(color)); + COLORREF color = ::GetTextColor(hDC); + Color salColor(GetRValue(color), GetGValue(color), GetBValue(color)); - // the actual drawing - DrawTextLayout(rLayout, aDC.getCompatibleHDC(), !bForceGDI); + // the actual drawing + DrawTextLayout(rLayout, aDC->getCompatibleHDC(), !bForceGDI); - std::unique_ptr<OpenGLTexture> xTexture(aDC.getTexture()); - if (xTexture) - pImpl->DrawMask(*xTexture, salColor, aDC.getTwoRect()); + std::unique_ptr<CompatibleDC::Texture> xTexture(aDC->getTexture()); + if (xTexture) + pImpl->DrawMask(xTexture.get(), salColor, aDC->getTwoRect()); - ::SelectFont(aDC.getCompatibleHDC(), hOrigFont); + ::SelectFont(aDC->getCompatibleHDC(), hOrigFont); - pImpl->PostDraw(); - } + pImpl->PostDrawText(); } } |