[Libreoffice-commits] core.git: sw/CppunitTest_sw_core_text.mk sw/qa sw/source

Miklos Vajna (via logerrit) logerrit at kemper.freedesktop.org
Tue Jan 7 08:27:20 UTC 2020


 sw/CppunitTest_sw_core_text.mk |    1 
 sw/qa/core/text/text.cxx       |   32 +++++++++++++++++
 sw/source/core/text/inftxt.cxx |   75 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 108 insertions(+)

New commits:
commit bf540873f5e258452fed5006f65a403c95e7872a
Author:     Miklos Vajna <vmiklos at collabora.com>
AuthorDate: Mon Jan 6 20:35:08 2020 +0100
Commit:     Miklos Vajna <vmiklos at collabora.com>
CommitDate: Tue Jan 7 09:26:47 2020 +0100

    sw: add rendering for semi-transparent text
    
    I considered passing the text color's alpha value down to the various
    vcl backends, but this would need changes everywhere (cairo, opengl, pdf
    export, etc). It's much easier to go via DrawTransparent(), that's how
    semi-transparent text in Draw/Impress already works.
    
    Change-Id: I96f15e6764c3c88ba67dd72dc8708414d7c6050c
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/86294
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <vmiklos at collabora.com>

diff --git a/sw/CppunitTest_sw_core_text.mk b/sw/CppunitTest_sw_core_text.mk
index 9fe4fadbf357..cb901fde29f2 100644
--- a/sw/CppunitTest_sw_core_text.mk
+++ b/sw/CppunitTest_sw_core_text.mk
@@ -27,6 +27,7 @@ $(eval $(call gb_CppunitTest_use_libraries,sw_core_text, \
     test \
     unotest \
     utl \
+    vcl \
 ))
 
 $(eval $(call gb_CppunitTest_use_externals,sw_core_text,\
diff --git a/sw/qa/core/text/text.cxx b/sw/qa/core/text/text.cxx
index 8074cbc9f45e..4e6d4fcdb14e 100644
--- a/sw/qa/core/text/text.cxx
+++ b/sw/qa/core/text/text.cxx
@@ -8,6 +8,9 @@
  */
 
 #include <swmodeltestbase.hxx>
+
+#include <vcl/gdimtf.hxx>
+
 #include <wrtsh.hxx>
 
 static char const DATA_DIRECTORY[] = "/sw/qa/core/text/data/";
@@ -46,6 +49,35 @@ CPPUNIT_TEST_FIXTURE(SwCoreTextTest, testFootnoteConnect)
     pWrtShell->DelLeft();
 }
 
+CPPUNIT_TEST_FIXTURE(SwCoreTextTest, testSemiTransparentText)
+{
+    // Create an in-memory empty document.
+    loadURL("private:factory/swriter", nullptr);
+
+    // Set text to half-transparent and type a character.
+    uno::Reference<beans::XPropertySet> xParagraph(getParagraph(1), uno::UNO_QUERY);
+    CPPUNIT_ASSERT(xParagraph.is());
+    sal_Int16 nTransparence = 50;
+    xParagraph->setPropertyValue("CharTransparence", uno::makeAny(nTransparence));
+    uno::Reference<text::XTextRange> xTextRange(xParagraph, uno::UNO_QUERY);
+    CPPUNIT_ASSERT(xTextRange.is());
+    xTextRange->setString("x");
+
+    // Render the document to a metafile.
+    SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get());
+    CPPUNIT_ASSERT(pTextDoc);
+    SwDocShell* pDocShell = pTextDoc->GetDocShell();
+    CPPUNIT_ASSERT(pDocShell);
+    std::shared_ptr<GDIMetaFile> xMetaFile = pDocShell->GetPreviewMetaFile();
+    CPPUNIT_ASSERT(xMetaFile);
+
+    // Make sure that DrawTransparent() was used during rendering.
+    MetafileXmlDump dumper;
+    xmlDocPtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
+    CPPUNIT_ASSERT(pXmlDoc);
+    assertXPath(pXmlDoc, "//floattransparent");
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/inftxt.cxx b/sw/source/core/text/inftxt.cxx
index 9fc9116fe1e4..efe9d54e1222 100644
--- a/sw/source/core/text/inftxt.cxx
+++ b/sw/source/core/text/inftxt.cxx
@@ -64,6 +64,9 @@
 #include <EnhancedPDFExportHelper.hxx>
 #include <docsh.hxx>
 #include <strings.hrc>
+#include <vcl/gdimtf.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/gradient.hxx>
 
 using namespace ::com::sun::star;
 using namespace ::com::sun::star::linguistic2;
@@ -552,6 +555,71 @@ static bool lcl_IsDarkBackground( const SwTextPaintInfo& rInf )
     return pCol->IsDark();
 }
 
+namespace
+{
+/**
+ * Context class that captures the draw operations on rDrawInf's output device for transparency
+ * purposes.
+ */
+class SwTransparentTextGuard
+{
+    ScopedVclPtrInstance<VirtualDevice> m_aContentVDev;
+    GDIMetaFile m_aContentMetafile;
+    MapMode m_aNewMapMode;
+    SwRect m_aPorRect;
+    SwTextPaintInfo& m_rPaintInf;
+    SwDrawTextInfo& m_rDrawInf;
+
+public:
+    SwTransparentTextGuard(const SwLinePortion& rPor, SwTextPaintInfo& rPaintInf,
+                           SwDrawTextInfo& rDrawInf);
+    ~SwTransparentTextGuard();
+};
+
+SwTransparentTextGuard::SwTransparentTextGuard(const SwLinePortion& rPor,
+                                               SwTextPaintInfo& rPaintInf, SwDrawTextInfo& rDrawInf)
+    : m_aNewMapMode(rPaintInf.GetOut()->GetMapMode())
+    , m_rPaintInf(rPaintInf)
+    , m_rDrawInf(rDrawInf)
+{
+    rPaintInf.CalcRect(rPor, &m_aPorRect);
+    rDrawInf.SetOut(*m_aContentVDev);
+    m_aContentVDev->SetMapMode(rPaintInf.GetOut()->GetMapMode());
+    m_aContentMetafile.Record(m_aContentVDev.get());
+    m_aContentVDev->SetLineColor(rPaintInf.GetOut()->GetLineColor());
+    m_aContentVDev->SetFillColor(rPaintInf.GetOut()->GetFillColor());
+    m_aContentVDev->SetFont(rPaintInf.GetOut()->GetFont());
+    m_aContentVDev->SetDrawMode(rPaintInf.GetOut()->GetDrawMode());
+    m_aContentVDev->SetSettings(rPaintInf.GetOut()->GetSettings());
+    m_aContentVDev->SetRefPoint(rPaintInf.GetOut()->GetRefPoint());
+}
+
+SwTransparentTextGuard::~SwTransparentTextGuard()
+{
+    m_aContentMetafile.Stop();
+    m_aContentMetafile.WindStart();
+    m_aNewMapMode.SetOrigin(m_aPorRect.TopLeft());
+    m_aContentMetafile.SetPrefMapMode(m_aNewMapMode);
+    m_aContentMetafile.SetPrefSize(m_aPorRect.SSize());
+    m_rDrawInf.SetOut(*m_rPaintInf.GetOut());
+    Gradient aVCLGradient;
+    sal_uInt8 nTransPercentVcl = m_rPaintInf.GetFont()->GetColor().GetTransparency();
+    const Color aTransColor(nTransPercentVcl, nTransPercentVcl, nTransPercentVcl);
+    aVCLGradient.SetStyle(GradientStyle::Linear);
+    aVCLGradient.SetStartColor(aTransColor);
+    aVCLGradient.SetEndColor(aTransColor);
+    aVCLGradient.SetAngle(0);
+    aVCLGradient.SetBorder(0);
+    aVCLGradient.SetOfsX(0);
+    aVCLGradient.SetOfsY(0);
+    aVCLGradient.SetStartIntensity(100);
+    aVCLGradient.SetEndIntensity(100);
+    aVCLGradient.SetSteps(2);
+    m_rPaintInf.GetOut()->DrawTransparent(m_aContentMetafile, m_aPorRect.TopLeft(),
+                                          m_aPorRect.SSize(), aVCLGradient);
+}
+}
+
 void SwTextPaintInfo::DrawText_( const OUString &rText, const SwLinePortion &rPor,
                                 TextFrameIndex const nStart, TextFrameIndex const nLength,
                                 const bool bKern, const bool bWrong,
@@ -678,6 +746,13 @@ void SwTextPaintInfo::DrawText_( const OUString &rText, const SwLinePortion &rPo
             aFontPos.setY( 0 );
     }
 
+    // Handle semi-transparent text if necessary.
+    std::unique_ptr<SwTransparentTextGuard> pTransparentText;
+    if (m_pFnt->GetColor() != COL_AUTO && m_pFnt->GetColor().GetTransparency() != 0)
+    {
+        pTransparentText.reset(new SwTransparentTextGuard(rPor, *this, aDrawInf));
+    }
+
     if( GetTextFly().IsOn() )
     {
         // aPos needs to be the TopLeft, because we cannot calculate the


More information about the Libreoffice-commits mailing list