external/skia/fix-shader-locale.patch.1 | 95 +++++++++++++------------------- vcl/inc/opengl/win/gdiimpl.hxx | 6 +- vcl/inc/skia/win/gdiimpl.hxx | 8 +- vcl/inc/win/salgdi.h | 7 +- vcl/inc/win/wingdiimpl.hxx | 4 - vcl/opengl/win/gdiimpl.cxx | 4 - vcl/skia/gdiimpl.cxx | 17 +---- vcl/skia/win/gdiimpl.cxx | 79 +++++++++++++++++++++++--- vcl/win/gdi/winlayout.cxx | 9 ++- 9 files changed, 136 insertions(+), 93 deletions(-)
New commits: commit 477f604ae0508c9fb7c936c55bab862c5c0ae803 Author: Luboš Luňák <[email protected]> AuthorDate: Fri Oct 25 16:29:49 2019 +0200 Commit: Luboš Luňák <[email protected]> CommitDate: Fri Oct 25 20:09:33 2019 +0200 fix Skia Windows text rendering There are two cases in WinSalGraphics::DrawTextLayout(), with and without cached glyphs: - Cached case DeferredTextDraw() gets data as BGRA with the glyph drawn in white, it just needs to be modulated to the proper color and drawn. - Uncached case DrawTextMask() gets data as BGRA with A invalid, it must be used as mask for the color to drawn, but without the inverse alpha VCL idiosyncracy that DrawMask() handles. Change-Id: I05dcec994df68d5986cd85cffa42a8f9f23c42c4 diff --git a/vcl/inc/opengl/win/gdiimpl.hxx b/vcl/inc/opengl/win/gdiimpl.hxx index 142af9768387..2101818472ae 100644 --- a/vcl/inc/opengl/win/gdiimpl.hxx +++ b/vcl/inc/opengl/win/gdiimpl.hxx @@ -26,8 +26,8 @@ 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 + virtual std::unique_ptr<Texture> getAsMaskTexture() override; + // caller must delete OpenGLTexture* getOpenGLTexture(); virtual bool copyToTexture(Texture& aTexture) override; @@ -68,7 +68,7 @@ public: 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; + virtual void DrawTextMask( 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; diff --git a/vcl/inc/skia/win/gdiimpl.hxx b/vcl/inc/skia/win/gdiimpl.hxx index bc177337b3de..6bd52b073aa5 100644 --- a/vcl/inc/skia/win/gdiimpl.hxx +++ b/vcl/inc/skia/win/gdiimpl.hxx @@ -28,10 +28,12 @@ class SkiaCompatibleDC : public CompatibleDC public: SkiaCompatibleDC(SalGraphics& rGraphics, int x, int y, int width, int height); - virtual std::unique_ptr<Texture> getTexture() override; + virtual std::unique_ptr<Texture> getAsMaskTexture() override; virtual bool copyToTexture(Texture& aTexture) override; + virtual bool wantsTextColorWhite() const override { return true; } + struct Texture; }; @@ -65,8 +67,8 @@ public: 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; + virtual void DrawTextMask(CompatibleDC::Texture* rTexture, Color nMaskColor, + const SalTwoRect& rPosAry) override; virtual void DeferredTextDraw(const CompatibleDC::Texture* pTexture, Color nMaskColor, const SalTwoRect& rPosAry) override; diff --git a/vcl/inc/win/salgdi.h b/vcl/inc/win/salgdi.h index f7fb206624b5..fc12bc823b93 100644 --- a/vcl/inc/win/salgdi.h +++ b/vcl/inc/win/salgdi.h @@ -138,11 +138,14 @@ public: /// Base texture class (OpenGL and Skia will provide their implementations). struct Texture; - /// Obtain the texture. - virtual std::unique_ptr<Texture> getTexture() { abort(); }; + /// Obtain the texture in format for WinSalGraphicsImplBase::DrawTextMask(). + virtual std::unique_ptr<Texture> getAsMaskTexture() { abort(); }; /// Copy bitmap data to the texture. Texture must be initialized and the correct size to hold the bitmap. virtual bool copyToTexture(Texture& /*aTexture*/) { abort(); }; + + /// Return true if text glyphs should be drawn as white instead of black. + virtual bool wantsTextColorWhite() const { return false; } }; struct CompatibleDC::Texture diff --git a/vcl/inc/win/wingdiimpl.hxx b/vcl/inc/win/wingdiimpl.hxx index 2264eecf353d..84884220318f 100644 --- a/vcl/inc/win/wingdiimpl.hxx +++ b/vcl/inc/win/wingdiimpl.hxx @@ -39,8 +39,8 @@ public: 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 DrawTextMask(CompatibleDC::Texture* /*rTexture*/, Color /*nMaskColor*/, + const SalTwoRect& /*rPosAry*/) { abort(); }; diff --git a/vcl/opengl/win/gdiimpl.cxx b/vcl/opengl/win/gdiimpl.cxx index d71a03714198..bb6e5bf0a16c 100644 --- a/vcl/opengl/win/gdiimpl.cxx +++ b/vcl/opengl/win/gdiimpl.cxx @@ -770,7 +770,7 @@ OpenGLTexture* OpenGLCompatibleDC::getOpenGLTexture() return new OpenGLTexture(maRects.mnSrcWidth, maRects.mnSrcHeight, GL_BGRA, GL_UNSIGNED_BYTE, mpData); } -std::unique_ptr<CompatibleDC::Texture> OpenGLCompatibleDC::getTexture() +std::unique_ptr<CompatibleDC::Texture> OpenGLCompatibleDC::getAsMaskTexture() { auto ret = std::make_unique<OpenGLCompatibleDC::Texture>(); ret->texture = OpenGLTexture(maRects.mnSrcWidth, maRects.mnSrcHeight, GL_BGRA, GL_UNSIGNED_BYTE, mpData); @@ -881,7 +881,7 @@ void WinOpenGLSalGraphicsImpl::DeferredTextDraw(const CompatibleDC::Texture* pTe PostBatchDraw(); } -void WinOpenGLSalGraphicsImpl::DrawMask( CompatibleDC::Texture* pTexture, Color nMaskColor, const SalTwoRect& rPosAry ) +void WinOpenGLSalGraphicsImpl::DrawTextMask( CompatibleDC::Texture* pTexture, Color nMaskColor, const SalTwoRect& rPosAry ) { assert(dynamic_cast<OpenGLCompatibleDC::Texture*>(pTexture)); DrawMask( static_cast<OpenGLCompatibleDC::Texture*>(pTexture)->texture, nMaskColor, rPosAry ); diff --git a/vcl/skia/win/gdiimpl.cxx b/vcl/skia/win/gdiimpl.cxx index 9a41ffc7da27..e583cea86f3c 100644 --- a/vcl/skia/win/gdiimpl.cxx +++ b/vcl/skia/win/gdiimpl.cxx @@ -12,6 +12,9 @@ #include <tools/sk_app/win/WindowContextFactory_win.h> #include <tools/sk_app/WindowContext.h> +#include <SkColorFilter.h> +#include <SkPixelRef.h> + WinSkiaSalGraphicsImpl::WinSkiaSalGraphicsImpl(WinSalGraphics& rGraphics, SalGeometryProvider* mpProvider) : SkiaSalGraphicsImpl(rGraphics, mpProvider) @@ -102,18 +105,54 @@ void WinSkiaSalGraphicsImpl::PreDrawText() { preDraw(); } void WinSkiaSalGraphicsImpl::PostDrawText() { postDraw(); } +SkColor toSkColor(Color color) +{ + return SkColorSetARGB(255 - color.GetTransparency(), color.GetRed(), color.GetGreen(), + color.GetBlue()); +} + void WinSkiaSalGraphicsImpl::DeferredTextDraw(const CompatibleDC::Texture* pTexture, Color aMaskColor, const SalTwoRect& rPosAry) { assert(dynamic_cast<const SkiaCompatibleDC::Texture*>(pTexture)); - drawMask(rPosAry, static_cast<const SkiaCompatibleDC::Texture*>(pTexture)->bitmap, aMaskColor); + preDraw(); + SkPaint paint; + // The glyph is painted as white, modulate it to be of the appropriate color. + // SkiaCompatibleDC::wantsTextColorWhite() ensures the glyph is white. + // TODO maybe other black/white in WinFontInstance::CacheGlyphToAtlas() should be swapped. + paint.setColorFilter(SkColorFilters::Blend(toSkColor(aMaskColor), SkBlendMode::kModulate)); + mSurface->getCanvas()->drawBitmapRect( + static_cast<const SkiaCompatibleDC::Texture*>(pTexture)->bitmap, + SkRect::MakeXYWH(rPosAry.mnSrcX, rPosAry.mnSrcY, rPosAry.mnSrcWidth, rPosAry.mnSrcHeight), + SkRect::MakeXYWH(rPosAry.mnDestX, rPosAry.mnDestY, rPosAry.mnDestWidth, + rPosAry.mnDestHeight), + &paint); + postDraw(); } -void WinSkiaSalGraphicsImpl::DrawMask(CompatibleDC::Texture* pTexture, Color nMaskColor, - const SalTwoRect& rPosAry) +void WinSkiaSalGraphicsImpl::DrawTextMask(CompatibleDC::Texture* pTexture, Color nMaskColor, + const SalTwoRect& rPosAry) { assert(dynamic_cast<SkiaCompatibleDC::Texture*>(pTexture)); - drawMask(rPosAry, static_cast<const SkiaCompatibleDC::Texture*>(pTexture)->bitmap, nMaskColor); + const SkBitmap& bitmap = static_cast<const SkiaCompatibleDC::Texture*>(pTexture)->bitmap; + preDraw(); + SkBitmap tmpBitmap; + if (!tmpBitmap.tryAllocN32Pixels(bitmap.width(), bitmap.height())) + abort(); + tmpBitmap.eraseColor(toSkColor(nMaskColor)); + SkPaint paint; + // Draw the color with the given mask. + // TODO figure out the right blend mode to avoid the temporary bitmap + paint.setBlendMode(SkBlendMode::kDstOut); + SkCanvas canvas(tmpBitmap); + canvas.drawBitmap(bitmap, 0, 0, &paint); + mSurface->getCanvas()->drawBitmapRect( + tmpBitmap, + SkRect::MakeXYWH(rPosAry.mnSrcX, rPosAry.mnSrcY, rPosAry.mnSrcWidth, rPosAry.mnSrcHeight), + SkRect::MakeXYWH(rPosAry.mnDestX, rPosAry.mnDestY, rPosAry.mnDestWidth, + rPosAry.mnDestHeight), + nullptr); + postDraw(); } SkiaCompatibleDC::SkiaCompatibleDC(SalGraphics& rGraphics, int x, int y, int width, int height) @@ -121,15 +160,35 @@ SkiaCompatibleDC::SkiaCompatibleDC(SalGraphics& rGraphics, int x, int y, int wid { } -std::unique_ptr<CompatibleDC::Texture> SkiaCompatibleDC::getTexture() +std::unique_ptr<CompatibleDC::Texture> SkiaCompatibleDC::getAsMaskTexture() { auto ret = std::make_unique<SkiaCompatibleDC::Texture>(); - // TODO is this correct? - // TODO make copy of data? - if (!ret->bitmap.installPixels(SkImageInfo::Make(maRects.mnSrcWidth, maRects.mnSrcHeight, - kBGRA_8888_SkColorType, kUnpremul_SkAlphaType), - mpData, maRects.mnSrcWidth * 4)) + // mpData is in the BGRA format, with A unused (and set to 0), and RGB are grey, + // so convert it to Skia format, then to 8bit and finally use as alpha mask + SkBitmap tmpBitmap; + if (!tmpBitmap.installPixels(SkImageInfo::Make(maRects.mnSrcWidth, maRects.mnSrcHeight, + kBGRA_8888_SkColorType, kOpaque_SkAlphaType), + mpData, maRects.mnSrcWidth * 4)) + abort(); + SkBitmap bitmap8; + if (!bitmap8.tryAllocPixels(SkImageInfo::Make(maRects.mnSrcWidth, maRects.mnSrcHeight, + kGray_8_SkColorType, kOpaque_SkAlphaType))) abort(); + SkCanvas canvas8(bitmap8); + SkPaint paint8; + paint8.setBlendMode(SkBlendMode::kSrc); // copy and convert depth + // The data we got is upside-down. + SkMatrix matrix; + matrix.preTranslate(0, maRects.mnSrcHeight); + matrix.setConcat(matrix, SkMatrix::MakeScale(1, -1)); + canvas8.concat(matrix); + canvas8.drawBitmap(tmpBitmap, 0, 0, &paint8); + // use the 8bit data as an alpha channel + SkBitmap alpha; + alpha.setInfo(bitmap8.info().makeColorType(kAlpha_8_SkColorType), bitmap8.rowBytes()); + alpha.setPixelRef(sk_ref_sp(bitmap8.pixelRef()), bitmap8.pixelRefOrigin().x(), + bitmap8.pixelRefOrigin().y()); + ret->bitmap = alpha; return ret; } diff --git a/vcl/win/gdi/winlayout.cxx b/vcl/win/gdi/winlayout.cxx index d8ccc3783ab1..a5e1056d1379 100644 --- a/vcl/win/gdi/winlayout.cxx +++ b/vcl/win/gdi/winlayout.cxx @@ -169,7 +169,8 @@ bool WinFontInstance::CacheGlyphToAtlas(HDC hDC, HFONT hFont, int nGlyphIndex, auto pRT = pTxt->GetRenderTarget(); ID2D1SolidColorBrush* pBrush = nullptr; - if (!SUCCEEDED(pRT->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Black), &pBrush))) + D2D1::ColorF textColor = aDC->wantsTextColorWhite() ? D2D1::ColorF::White : D2D1::ColorF::Black; + if (!SUCCEEDED(pRT->CreateSolidColorBrush(textColor, &pBrush))) return false; D2D1_POINT_2F baseline = { @@ -579,9 +580,9 @@ void WinSalGraphics::DrawTextLayout(const GenericSalLayout& rLayout) // the actual drawing DrawTextLayout(rLayout, aDC->getCompatibleHDC(), !bForceGDI); - std::unique_ptr<CompatibleDC::Texture> xTexture(aDC->getTexture()); + std::unique_ptr<CompatibleDC::Texture> xTexture(aDC->getAsMaskTexture()); if (xTexture) - pImpl->DrawMask(xTexture.get(), salColor, aDC->getTwoRect()); + pImpl->DrawTextMask(xTexture.get(), salColor, aDC->getTwoRect()); ::SelectFont(aDC->getCompatibleHDC(), hOrigFont); commit 1f0ebf6a0cba419280e2e9d3f9dd7c104ebdb57d Author: Luboš Luňák <[email protected]> AuthorDate: Fri Oct 25 16:07:26 2019 +0200 Commit: Luboš Luňák <[email protected]> CommitDate: Fri Oct 25 20:09:30 2019 +0200 fix SkiaSalGraphicsImpl::drawMask() Now that SalBitmap::convertDataBitCount() has been fixed, the implementation here gets rather trivial. This breaks Windows text drawing, which uses drawMask() incorrectly (to be fixed in the next commit). Change-Id: I98f11c1bd4b1600bb5e03e570319d29b40daa27e diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx index 560dcab6b99a..d6a956e4e76f 100644 --- a/vcl/skia/gdiimpl.cxx +++ b/vcl/skia/gdiimpl.cxx @@ -652,23 +652,16 @@ void SkiaSalGraphicsImpl::drawMask(const SalTwoRect& rPosAry, const SkBitmap& rB Color nMaskColor) { preDraw(); - SkBitmap tmpBitmap; - if (!tmpBitmap.tryAllocN32Pixels(rBitmap.width(), rBitmap.height())) - abort(); - SkCanvas canvas(tmpBitmap); SkPaint paint; - paint.setBlendMode(SkBlendMode::kSrc); - canvas.drawBitmap(rBitmap, 0, 0, &paint); - // TODO what is this function supposed to do exactly? - // Text drawing on Windows doesn't work if this is uncommented. - // tmpBitmap.eraseColor(toSkColor(nMaskColor)); - (void)nMaskColor; + // Draw the color with the given mask, and mask uses inversed alpha. + paint.setBlendMode(SkBlendMode::kDstOut); + paint.setColor(toSkColor(nMaskColor)); mSurface->getCanvas()->drawBitmapRect( - tmpBitmap, + rBitmap, SkRect::MakeXYWH(rPosAry.mnSrcX, rPosAry.mnSrcY, rPosAry.mnSrcWidth, rPosAry.mnSrcHeight), SkRect::MakeXYWH(rPosAry.mnDestX, rPosAry.mnDestY, rPosAry.mnDestWidth, rPosAry.mnDestHeight), - nullptr); + &paint); postDraw(); } commit 0e02f6b773e5a0173ce8ad8ccdb478d473bbedd8 Author: Luboš Luňák <[email protected]> AuthorDate: Fri Oct 25 15:17:56 2019 +0200 Commit: Luboš Luňák <[email protected]> CommitDate: Fri Oct 25 20:09:27 2019 +0200 skip text drawing if there is nothing to draw If the rectangle is empty, there is nothing to draw. This also avoids problems with WinSalVirtualDevice::ImplCreateVirDevBitmap() calling CreateDIBSection() with zero dimensions. Change-Id: I3a56e64fc32cfb855443f4ab665d53604d724d9b diff --git a/vcl/win/gdi/winlayout.cxx b/vcl/win/gdi/winlayout.cxx index f92f16d4e732..d8ccc3783ab1 100644 --- a/vcl/win/gdi/winlayout.cxx +++ b/vcl/win/gdi/winlayout.cxx @@ -550,6 +550,8 @@ void WinSalGraphics::DrawTextLayout(const GenericSalLayout& rLayout) tools::Rectangle aRect; rLayout.GetBoundRect(aRect); + if( aRect.IsEmpty()) + return; pImpl->PreDrawText(); commit 6778b361c9b90c0acd074eef7da2537c289670e4 Author: Luboš Luňák <[email protected]> AuthorDate: Fri Oct 25 10:45:34 2019 +0200 Commit: Luboš Luňák <[email protected]> CommitDate: Fri Oct 25 20:09:23 2019 +0200 update Skia fix-shader-locale.patch.1 to the upstream version Change-Id: Ie8606f30d3f821d7b195aa7978886d529a57bfd2 diff --git a/external/skia/fix-shader-locale.patch.1 b/external/skia/fix-shader-locale.patch.1 index 71a5b0e00c82..af6405fe517c 100644 --- a/external/skia/fix-shader-locale.patch.1 +++ b/external/skia/fix-shader-locale.patch.1 @@ -1,57 +1,40 @@ -https://bugs.chromium.org/p/skia/issues/detail?id=9550 +From b653813d58146fb41cd1852e5f24cdfc0ad9532a Mon Sep 17 00:00:00 2001 +From: Ethan Nicholas <[email protected]> +Date: Tue, 22 Oct 2019 16:00:18 -0400 +Subject: [PATCH 1/7] Vulkan SkSL code now works in locales which use ',' as + the decimal separator. + +Bug: skia:9550 +Change-Id: Ib844971bd1daebdf7a0f93388ad40e4977822233 +Reviewed-on: https://skia-review.googlesource.com/c/skia/+/250076 +Reviewed-by: Greg Daniel <[email protected]> +Commit-Queue: Ethan Nicholas <[email protected]> +--- + src/gpu/vk/GrVkPipelineStateBuilder.cpp | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/src/gpu/vk/GrVkPipelineStateBuilder.cpp b/src/gpu/vk/GrVkPipelineStateBuilder.cpp +index 4d595e7eca..dbe16f6e7f 100644 +--- a/src/gpu/vk/GrVkPipelineStateBuilder.cpp ++++ b/src/gpu/vk/GrVkPipelineStateBuilder.cpp +@@ -6,6 +6,7 @@ + */ + + #include "include/gpu/GrContext.h" ++#include "src/gpu/GrAutoLocaleSetter.h" + #include "src/gpu/GrContextPriv.h" + #include "src/gpu/GrPersistentCacheUtils.h" + #include "src/gpu/GrShaderCaps.h" +@@ -27,6 +28,9 @@ GrVkPipelineState* GrVkPipelineStateBuilder::CreatePipelineState( + GrPrimitiveType primitiveType, + Desc* desc, + VkRenderPass compatibleRenderPass) { ++ // ensure that we use "." as a decimal separator when creating SkSL code ++ GrAutoLocaleSetter als("C"); ++ + // create a builder. This will be handed off to effects so they can use it to add + // uniforms, varyings, textures, etc + GrVkPipelineStateBuilder builder(gpu, renderTarget, programInfo, desc); +-- +2.16.4 -diff --git a/src/core/SkString.cpp b/src/core/SkString.cpp -index d42ee6f07e..1e3ebddf95 100644 ---- a/src/core/SkString.cpp -+++ b/src/core/SkString.cpp -@@ -502,11 +502,15 @@ void SkString::appendf(const char format[], ...) { - } - - void SkString::appendVAList(const char format[], va_list args) { -+ char* oldlocale = strdup( setlocale( LC_NUMERIC, nullptr )); -+ setlocale( LC_NUMERIC, "C" ); - char buffer[kBufferSize]; - int length = vsnprintf(buffer, kBufferSize, format, args); - SkASSERT(length >= 0 && length < SkToInt(kBufferSize)); - - this->append(buffer, length); -+ setlocale( LC_NUMERIC, oldlocale ); -+ free( oldlocale ); - } - - void SkString::prependf(const char format[], ...) { -@@ -519,11 +523,15 @@ void SkString::prependf(const char format[], ...) { - } - - void SkString::prependVAList(const char format[], va_list args) { -+ char* oldlocale = strdup( setlocale( LC_NUMERIC, nullptr )); -+ setlocale( LC_NUMERIC, "C" ); - char buffer[kBufferSize]; - int length = vsnprintf(buffer, kBufferSize, format, args); - SkASSERT(length >= 0 && length < SkToInt(kBufferSize)); - - this->prepend(buffer, length); -+ setlocale( LC_NUMERIC, oldlocale ); -+ free( oldlocale ); - } - - -diff --git a/src/sksl/SkSLOutputStream.cpp b/src/sksl/SkSLOutputStream.cpp -index f72637d4cb..6e31e8f302 100644 ---- a/src/sksl/SkSLOutputStream.cpp -+++ b/src/sksl/SkSLOutputStream.cpp -@@ -21,10 +21,14 @@ void OutputStream::printf(const char format[], ...) { - } - - void OutputStream::appendVAList(const char format[], va_list args) { -+ char* oldlocale = strdup( setlocale( LC_NUMERIC, nullptr )); -+ setlocale( LC_NUMERIC, "C" ); - char buffer[kBufferSize]; - int length = vsnprintf(buffer, kBufferSize, format, args); - SkASSERT(length >= 0 && length < (int) kBufferSize); - this->write(buffer, length); -+ setlocale( LC_NUMERIC, oldlocale ); -+ free( oldlocale ); - } - - } _______________________________________________ Libreoffice-commits mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
