[Libreoffice-commits] core.git: Branch 'feature/drawinglayercore' - 118 commits - bin/distro-install-file-lists bridges/source chart2/qa chart2/source comphelper/source compilerplugins/clang configure.ac connectivity/source cppu/CppunitTest_cppu_typelib.mk cppu/Module_cppu.mk cppu/qa cppu/source cui/inc cui/source cui/uiconfig dbaccess/IwyuFilter_dbaccess.yaml dbaccess/source distro-configs/LibreOfficeiOS_Sim.conf distro-configs/LibreOfficeVanillaMacAppStore.conf download.lst drawinglayer/CppunitTest_drawinglayer_border.mk drawinglayer/inc drawinglayer/Library_drawinglayercore.mk drawinglayer/Library_drawinglayer.mk drawinglayer/Module_drawinglayer.mk drawinglayer/source editeng/source emfio/CppunitTest_emfio_emf_test.mk emfio/Library_emfio.mk external/python3 extras/CustomTarget_tplpresnt.mk extras/source filter/Library_svgfilter.mk filter/source formula/inc fpicker/source hardened_runtime.xcent hardened_runtime.xcent.in helpcontent2 hwpfilter/source icon-themes/breeze icon-themes/breeze_dark ic on-themes/breeze_dark_svg icon-themes/breeze_svg icon-themes/elementary icon-themes/elementary_svg icon-themes/karasa_jaga icon-themes/karasa_jaga_svg icon-themes/README icon-themes/sifr icon-themes/sifr_dark icon-themes/sifr_dark_svg icon-themes/sifr_svg icon-themes/tango icon-themes/tango_svg include/comphelper include/cui include/drawinglayer include/editeng include/filter include/formula include/oox include/rtl include/sax include/sfx2 include/svtools include/svx include/vcl include/xmloff linguistic/source lo.xcent offapi/com officecfg/registry oox/inc oox/source osx/soffice.xcodeproj readlicense_oo/license reportdesign/source Repository.mk sal/osl sc/CppunitTest_sc_ucalc.mk sc/inc sc/Library_sc.mk sc/qa sc/source sd/CppunitTest_sd_uimpress.mk sd/Library_sd.mk sd/qa sd/source sd/uiconfig sfx2/inc sfx2/Library_sfx.mk sfx2/source sfx2/uiconfig sfx2/UIConfig_sfx.mk slideshow/source solenv/bin solenv/clang-format solenv/sanitizers starmath/inc starmath/source svgio/CppunitTest_svgi o.mk svgio/Library_svgio.mk svgio/source svtools/inc svtools/source svx/CppunitTest_svx_unit.mk svx/inc svx/Library_svxcore.mk svx/Library_svx.mk svx/source svx/uiconfig sw/CppunitTest_sw_core_objectpositioning.mk sw/CppunitTest_sw_uwriter.mk sw/inc sw/Library_sw.mk sw/Library_swui.mk sw/Module_sw.mk sw/qa sw/source translations ucb/source uitest/uitest unoxml/source vcl/Executable_fodtfuzzer.mk vcl/Library_vcl.mk vcl/qa vcl/quartz vcl/source vcl/unx writerfilter/qa writerfilter/source writerperfect/source xmlhelp/source xmloff/inc xmloff/source xmlsecurity/source
Tomaž Vajngerl (via logerrit)
logerrit at kemper.freedesktop.org
Thu Apr 30 06:52:43 UTC 2020
Rebased ref, commits from common ancestor:
commit 82ec858f9d4997568142e5455d96b4493d7f1a14
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
AuthorDate: Thu Apr 30 07:54:46 2020 +0200
Commit: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
CommitDate: Thu Apr 30 08:51:55 2020 +0200
test import and export of multi-page PDF with PDFium filter
The test checks that the exported PDFs contain embedded PDF for
different pages.
Change-Id: I4e5cd108d8597851d86aa774efbde0d4f2b9d2ac
diff --git a/vcl/qa/cppunit/pdfexport/data/SimpleMultiPagePDF.pdf b/vcl/qa/cppunit/pdfexport/data/SimpleMultiPagePDF.pdf
new file mode 100644
index 000000000000..af665fcba8a0
Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/SimpleMultiPagePDF.pdf differ
diff --git a/vcl/qa/cppunit/pdfexport/pdfexport.cxx b/vcl/qa/cppunit/pdfexport/pdfexport.cxx
index 313dbdd278b4..c228cc7945a6 100644
--- a/vcl/qa/cppunit/pdfexport/pdfexport.cxx
+++ b/vcl/qa/cppunit/pdfexport/pdfexport.cxx
@@ -26,6 +26,7 @@
#include <com/sun/star/document/XExporter.hpp>
#include <com/sun/star/io/XOutputStream.hpp>
+#include <comphelper/scopeguard.hxx>
#include <comphelper/processfactory.hxx>
#include <comphelper/propertysequence.hxx>
#include <test/bootstrapfixture.hxx>
@@ -146,6 +147,8 @@ public:
void testLargePage();
void testVersion15();
void testDefaultVersion();
+ void testMultiPagePDF();
+
CPPUNIT_TEST_SUITE(PdfExportTest);
CPPUNIT_TEST(testTdf106059);
@@ -189,6 +192,7 @@ public:
CPPUNIT_TEST(testLargePage);
CPPUNIT_TEST(testVersion15);
CPPUNIT_TEST(testDefaultVersion);
+ CPPUNIT_TEST(testMultiPagePDF);
CPPUNIT_TEST_SUITE_END();
};
@@ -2154,6 +2158,136 @@ void PdfExportTest::testVersion15()
CPPUNIT_ASSERT_EQUAL(15, nFileVersion);
}
+// Check round-trip of importing and exporting the PDF with PDFium filter,
+// which imports the PDF document as multiple PDFs as graphic object.
+// Each page in the document has one PDF graphic object which content is
+// the correcponding page in the PDF. When such a document is exported,
+// the PDF graphic gets embedded into the exported PDF document (as a
+// Form XObject).
+void PdfExportTest::testMultiPagePDF()
+{
+ // We need to enable PDFium import (and make sure to disable after the test)
+ bool bResetEnvVar = false;
+ if (getenv("LO_IMPORT_USE_PDFIUM") == nullptr)
+ {
+ bResetEnvVar = true;
+ setenv("LO_IMPORT_USE_PDFIUM", "1", false);
+ }
+ comphelper::ScopeGuard aPDFiumEnvVarGuard([&]() {
+ if (bResetEnvVar)
+ unsetenv("LO_IMPORT_USE_PDFIUM");
+ });
+
+ // Load the PDF and save as PDF
+ OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "SimpleMultiPagePDF.pdf";
+ mxComponent = loadFromDesktop(aURL);
+ CPPUNIT_ASSERT(mxComponent.is());
+
+ uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
+ utl::MediaDescriptor aMediaDescriptor;
+ aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export");
+ xStorable->storeToURL(maTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList());
+
+ // Parse the export result.
+ vcl::filter::PDFDocument aDocument;
+ SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ);
+ CPPUNIT_ASSERT(aDocument.Read(aStream));
+
+ std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), aPages.size());
+
+ vcl::filter::PDFObjectElement* pResources = aPages[0]->LookupObject("Resources");
+ CPPUNIT_ASSERT(pResources);
+
+ auto pXObjects = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pResources->Lookup("XObject"));
+ CPPUNIT_ASSERT(pXObjects);
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), pXObjects->GetItems().size()); // 3 PDFs as Form XObjects
+
+ std::vector<OString> rIDs;
+ for (auto const & rPair : pXObjects->GetItems()) {
+ rIDs.push_back(rPair.first);
+ }
+
+ // Let's check the embedded PDF pages - just make sure the size differs,
+ // which should indicate we don't have 3 times the same page.
+
+ { // embedded PDF page 1
+ vcl::filter::PDFObjectElement* pXObject1 = pXObjects->LookupObject(rIDs[0]);
+ CPPUNIT_ASSERT(pXObject1);
+ CPPUNIT_ASSERT_EQUAL(OString("Im19"), rIDs[0]);
+
+ auto pSubtype1 = dynamic_cast<vcl::filter::PDFNameElement*>(pXObject1->Lookup("Subtype"));
+ CPPUNIT_ASSERT(pSubtype1);
+ CPPUNIT_ASSERT_EQUAL(OString("Form"), pSubtype1->GetValue());
+
+ auto pXObjectResources = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pXObject1->Lookup("Resources"));
+ CPPUNIT_ASSERT(pXObjectResources);
+ auto pXObjectForms = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pXObjectResources->LookupElement("XObject"));
+ CPPUNIT_ASSERT(pXObjectForms);
+ vcl::filter::PDFObjectElement* pForm = pXObjectForms->LookupObject(pXObjectForms->GetItems().begin()->first);
+ CPPUNIT_ASSERT(pForm);
+
+ vcl::filter::PDFStreamElement* pStream = pForm->GetStream();
+ CPPUNIT_ASSERT(pStream);
+ SvMemoryStream& rObjectStream = pStream->GetMemory();
+ rObjectStream.Seek(STREAM_SEEK_TO_BEGIN);
+
+ // Just check that the size of the page stream is what is expected.
+ CPPUNIT_ASSERT_EQUAL(sal_uInt64(230), rObjectStream.remainingSize());
+ }
+
+ { // embedded PDF page 2
+ vcl::filter::PDFObjectElement* pXObject2 = pXObjects->LookupObject(rIDs[1]);
+ CPPUNIT_ASSERT(pXObject2);
+ CPPUNIT_ASSERT_EQUAL(OString("Im34"), rIDs[1]);
+
+ auto pSubtype2 = dynamic_cast<vcl::filter::PDFNameElement*>(pXObject2->Lookup("Subtype"));
+ CPPUNIT_ASSERT(pSubtype2);
+ CPPUNIT_ASSERT_EQUAL(OString("Form"), pSubtype2->GetValue());
+
+ auto pXObjectResources = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pXObject2->Lookup("Resources"));
+ CPPUNIT_ASSERT(pXObjectResources);
+ auto pXObjectForms = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pXObjectResources->LookupElement("XObject"));
+ CPPUNIT_ASSERT(pXObjectForms);
+ vcl::filter::PDFObjectElement* pForm = pXObjectForms->LookupObject(pXObjectForms->GetItems().begin()->first);
+ CPPUNIT_ASSERT(pForm);
+
+ vcl::filter::PDFStreamElement* pStream = pForm->GetStream();
+ CPPUNIT_ASSERT(pStream);
+ SvMemoryStream& rObjectStream = pStream->GetMemory();
+ rObjectStream.Seek(STREAM_SEEK_TO_BEGIN);
+
+ // Just check that the size of the page stream is what is expected
+ CPPUNIT_ASSERT_EQUAL(sal_uInt64(309), rObjectStream.remainingSize());
+ }
+
+ { // embedded PDF page 3
+ vcl::filter::PDFObjectElement* pXObject3 = pXObjects->LookupObject(rIDs[2]);
+ CPPUNIT_ASSERT(pXObject3);
+ CPPUNIT_ASSERT_EQUAL(OString("Im4"), rIDs[2]);
+
+ auto pSubtype3 = dynamic_cast<vcl::filter::PDFNameElement*>(pXObject3->Lookup("Subtype"));
+ CPPUNIT_ASSERT(pSubtype3);
+ CPPUNIT_ASSERT_EQUAL(OString("Form"), pSubtype3->GetValue());
+
+ auto pXObjectResources = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pXObject3->Lookup("Resources"));
+ CPPUNIT_ASSERT(pXObjectResources);
+ auto pXObjectForms = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pXObjectResources->LookupElement("XObject"));
+ CPPUNIT_ASSERT(pXObjectForms);
+ vcl::filter::PDFObjectElement* pForm = pXObjectForms->LookupObject(pXObjectForms->GetItems().begin()->first);
+ CPPUNIT_ASSERT(pForm);
+
+ vcl::filter::PDFStreamElement* pStream = pForm->GetStream();
+ CPPUNIT_ASSERT(pStream);
+ SvMemoryStream& rObjectStream = pStream->GetMemory();
+ rObjectStream.Seek(STREAM_SEEK_TO_BEGIN);
+
+ // Just check that the size of the page stream is what is expected
+ CPPUNIT_ASSERT_EQUAL(sal_uInt64(193), rObjectStream.remainingSize());
+ }
+}
+
CPPUNIT_TEST_SUITE_REGISTRATION(PdfExportTest);
}
commit eacf3707682a735f067923afb3252d8fd2d39a64
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
AuthorDate: Wed Apr 29 17:50:06 2020 +0200
Commit: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
CommitDate: Thu Apr 30 08:51:54 2020 +0200
remove vclpixelprocessor2d.cxx from clang-format blacklist
Change-Id: I03ad72d0754cb8c180f4eab0e8040c3dab533ef9
diff --git a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
index 654fa6e6168f..f09c6ad0fd76 100644
--- a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
@@ -65,826 +65,891 @@ using namespace com::sun::star;
namespace drawinglayer::processor2d
{
- struct VclPixelProcessor2D::Impl
- {
- AntialiasingFlags m_nOrigAntiAliasing;
+struct VclPixelProcessor2D::Impl
+{
+ AntialiasingFlags m_nOrigAntiAliasing;
+
+ explicit Impl(OutputDevice const& rOutDev)
+ : m_nOrigAntiAliasing(rOutDev.GetAntialiasing())
+ {
+ }
+};
+
+VclPixelProcessor2D::VclPixelProcessor2D(const geometry::ViewInformation2D& rViewInformation,
+ OutputDevice& rOutDev)
+ : VclProcessor2D(rViewInformation, rOutDev)
+ , m_pImpl(new Impl(rOutDev))
+{
+ // prepare maCurrentTransformation matrix with viewTransformation to target directly to pixels
+ maCurrentTransformation = rViewInformation.getObjectToViewTransformation();
+
+ // prepare output directly to pixels
+ mpOutputDevice->Push(PushFlags::MAPMODE);
+ mpOutputDevice->SetMapMode();
+
+ // react on AntiAliasing settings
+ if (getOptionsDrawinglayer().IsAntiAliasing())
+ {
+ mpOutputDevice->SetAntialiasing(m_pImpl->m_nOrigAntiAliasing
+ | AntialiasingFlags::EnableB2dDraw);
+ }
+ else
+ {
+ mpOutputDevice->SetAntialiasing(m_pImpl->m_nOrigAntiAliasing
+ & ~AntialiasingFlags::EnableB2dDraw);
+ }
+}
+
+VclPixelProcessor2D::~VclPixelProcessor2D()
+{
+ // restore MapMode
+ mpOutputDevice->Pop();
- explicit Impl(OutputDevice const& rOutDev)
- : m_nOrigAntiAliasing(rOutDev.GetAntialiasing())
- { }
- };
+ // restore AntiAliasing
+ mpOutputDevice->SetAntialiasing(m_pImpl->m_nOrigAntiAliasing);
+}
- VclPixelProcessor2D::VclPixelProcessor2D(const geometry::ViewInformation2D& rViewInformation, OutputDevice& rOutDev)
- : VclProcessor2D(rViewInformation, rOutDev)
- , m_pImpl(new Impl(rOutDev))
- {
- // prepare maCurrentTransformation matrix with viewTransformation to target directly to pixels
- maCurrentTransformation = rViewInformation.getObjectToViewTransformation();
+void VclPixelProcessor2D::tryDrawPolyPolygonColorPrimitive2DDirect(
+ const drawinglayer::primitive2d::PolyPolygonColorPrimitive2D& rSource, double fTransparency)
+{
+ if (!rSource.getB2DPolyPolygon().count() || fTransparency < 0.0 || fTransparency >= 1.0)
+ {
+ // no geometry, done
+ return;
+ }
+
+ const basegfx::BColor aPolygonColor(
+ maBColorModifierStack.getModifiedColor(rSource.getBColor()));
+
+ mpOutputDevice->SetFillColor(Color(aPolygonColor));
+ mpOutputDevice->SetLineColor();
+ mpOutputDevice->DrawTransparent(maCurrentTransformation, rSource.getB2DPolyPolygon(),
+ fTransparency);
+}
+
+bool VclPixelProcessor2D::tryDrawPolygonHairlinePrimitive2DDirect(
+ const drawinglayer::primitive2d::PolygonHairlinePrimitive2D& rSource, double fTransparency)
+{
+ const basegfx::B2DPolygon& rLocalPolygon(rSource.getB2DPolygon());
- // prepare output directly to pixels
- mpOutputDevice->Push(PushFlags::MAPMODE);
- mpOutputDevice->SetMapMode();
+ if (!rLocalPolygon.count() || fTransparency < 0.0 || fTransparency >= 1.0)
+ {
+ // no geometry, done
+ return true;
+ }
- // react on AntiAliasing settings
- if(getOptionsDrawinglayer().IsAntiAliasing())
- {
- mpOutputDevice->SetAntialiasing(
- m_pImpl->m_nOrigAntiAliasing | AntialiasingFlags::EnableB2dDraw);
- }
- else
- {
- mpOutputDevice->SetAntialiasing(
- m_pImpl->m_nOrigAntiAliasing & ~AntialiasingFlags::EnableB2dDraw);
- }
- }
+ const basegfx::BColor aLineColor(maBColorModifierStack.getModifiedColor(rSource.getBColor()));
- VclPixelProcessor2D::~VclPixelProcessor2D()
- {
- // restore MapMode
- mpOutputDevice->Pop();
+ mpOutputDevice->SetFillColor();
+ mpOutputDevice->SetLineColor(Color(aLineColor));
+ //aLocalPolygon.transform(maCurrentTransformation);
- // restore AntiAliasing
- mpOutputDevice->SetAntialiasing(m_pImpl->m_nOrigAntiAliasing);
- }
+ // try drawing; if it did not work, use standard fallback
+ return mpOutputDevice->DrawPolyLineDirect(maCurrentTransformation, rLocalPolygon, 0.0,
+ fTransparency);
+}
- void VclPixelProcessor2D::tryDrawPolyPolygonColorPrimitive2DDirect(const drawinglayer::primitive2d::PolyPolygonColorPrimitive2D& rSource, double fTransparency)
+bool VclPixelProcessor2D::tryDrawPolygonStrokePrimitive2DDirect(
+ const drawinglayer::primitive2d::PolygonStrokePrimitive2D& rSource, double fTransparency)
+{
+ const basegfx::B2DPolygon& rLocalPolygon(rSource.getB2DPolygon());
+
+ if (!rLocalPolygon.count() || fTransparency < 0.0 || fTransparency >= 1.0)
+ {
+ // no geometry, done
+ return true;
+ }
+
+ if (basegfx::B2DLineJoin::NONE == rSource.getLineAttribute().getLineJoin()
+ && css::drawing::LineCap_BUTT != rSource.getLineAttribute().getLineCap())
+ {
+ // better use decompose to get that combination done for now, see discussion
+ // at https://bugs.documentfoundation.org/show_bug.cgi?id=130478#c17 and ff
+ return false;
+ }
+
+ // MM01: Radically change here - no dismantle/applyLineDashing,
+ // let that happen low-level at DrawPolyLineDirect implementations
+ // to open up for buffering and evtl. direct draw with sys-dep
+ // graphic systems. Check for stroke is in use
+ const bool bStrokeAttributeNotUsed(rSource.getStrokeAttribute().isDefault()
+ || 0.0 == rSource.getStrokeAttribute().getFullDotDashLen());
+
+ const basegfx::BColor aLineColor(
+ maBColorModifierStack.getModifiedColor(rSource.getLineAttribute().getColor()));
+
+ mpOutputDevice->SetFillColor();
+ mpOutputDevice->SetLineColor(Color(aLineColor));
+
+ // MM01 draw direct, hand over dash data if available
+ return mpOutputDevice->DrawPolyLineDirect(
+ maCurrentTransformation, rLocalPolygon,
+ // tdf#124848 use LineWidth direct, do not try to solve for zero-case (aka hairline)
+ rSource.getLineAttribute().getWidth(), fTransparency,
+ bStrokeAttributeNotUsed ? nullptr : &rSource.getStrokeAttribute().getDotDashArray(),
+ rSource.getLineAttribute().getLineJoin(), rSource.getLineAttribute().getLineCap(),
+ rSource.getLineAttribute().getMiterMinimumAngle()
+ /* false bBypassAACheck, default*/);
+}
+
+void VclPixelProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate)
+{
+ switch (rCandidate.getPrimitive2DID())
+ {
+ case PRIMITIVE2D_ID_WRONGSPELLPRIMITIVE2D:
{
- if(!rSource.getB2DPolyPolygon().count() || fTransparency < 0.0 || fTransparency >= 1.0)
- {
- // no geometry, done
- return;
- }
-
- const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(rSource.getBColor()));
-
- mpOutputDevice->SetFillColor(Color(aPolygonColor));
- mpOutputDevice->SetLineColor();
- mpOutputDevice->DrawTransparent(
- maCurrentTransformation,
- rSource.getB2DPolyPolygon(),
- fTransparency);
+ processWrongSpellPrimitive2D(
+ static_cast<const primitive2d::WrongSpellPrimitive2D&>(rCandidate));
+ break;
}
-
- bool VclPixelProcessor2D::tryDrawPolygonHairlinePrimitive2DDirect(const drawinglayer::primitive2d::PolygonHairlinePrimitive2D& rSource, double fTransparency)
+ case PRIMITIVE2D_ID_TEXTSIMPLEPORTIONPRIMITIVE2D:
{
- const basegfx::B2DPolygon& rLocalPolygon(rSource.getB2DPolygon());
-
- if(!rLocalPolygon.count() || fTransparency < 0.0 || fTransparency >= 1.0)
- {
- // no geometry, done
- return true;
- }
-
- const basegfx::BColor aLineColor(maBColorModifierStack.getModifiedColor(rSource.getBColor()));
-
- mpOutputDevice->SetFillColor();
- mpOutputDevice->SetLineColor(Color(aLineColor));
- //aLocalPolygon.transform(maCurrentTransformation);
-
- // try drawing; if it did not work, use standard fallback
- return mpOutputDevice->DrawPolyLineDirect(
- maCurrentTransformation,
- rLocalPolygon,
- 0.0,
- fTransparency);
+ processTextSimplePortionPrimitive2D(
+ static_cast<const primitive2d::TextSimplePortionPrimitive2D&>(rCandidate));
+ break;
}
-
- bool VclPixelProcessor2D::tryDrawPolygonStrokePrimitive2DDirect(const drawinglayer::primitive2d::PolygonStrokePrimitive2D& rSource, double fTransparency)
+ case PRIMITIVE2D_ID_TEXTDECORATEDPORTIONPRIMITIVE2D:
{
- const basegfx::B2DPolygon& rLocalPolygon(rSource.getB2DPolygon());
-
- if(!rLocalPolygon.count() || fTransparency < 0.0 || fTransparency >= 1.0)
- {
- // no geometry, done
- return true;
- }
-
- if (basegfx::B2DLineJoin::NONE == rSource.getLineAttribute().getLineJoin()
- && css::drawing::LineCap_BUTT != rSource.getLineAttribute().getLineCap())
- {
- // better use decompose to get that combination done for now, see discussion
- // at https://bugs.documentfoundation.org/show_bug.cgi?id=130478#c17 and ff
- return false;
- }
-
- // MM01: Radically change here - no dismantle/applyLineDashing,
- // let that happen low-level at DrawPolyLineDirect implementations
- // to open up for buffering and evtl. direct draw with sys-dep
- // graphic systems. Check for stroke is in use
- const bool bStrokeAttributeNotUsed(rSource.getStrokeAttribute().isDefault()
- || 0.0 == rSource.getStrokeAttribute().getFullDotDashLen());
-
- const basegfx::BColor aLineColor(
- maBColorModifierStack.getModifiedColor(
- rSource.getLineAttribute().getColor()));
-
- mpOutputDevice->SetFillColor();
- mpOutputDevice->SetLineColor(Color(aLineColor));
-
- // MM01 draw direct, hand over dash data if available
- return mpOutputDevice->DrawPolyLineDirect(
- maCurrentTransformation,
- rLocalPolygon,
- // tdf#124848 use LineWidth direct, do not try to solve for zero-case (aka hairline)
- rSource.getLineAttribute().getWidth(),
- fTransparency,
- bStrokeAttributeNotUsed ? nullptr : &rSource.getStrokeAttribute().getDotDashArray(),
- rSource.getLineAttribute().getLineJoin(),
- rSource.getLineAttribute().getLineCap(),
- rSource.getLineAttribute().getMiterMinimumAngle()
- /* false bBypassAACheck, default*/);
- }
-
- void VclPixelProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate)
- {
- switch(rCandidate.getPrimitive2DID())
- {
- case PRIMITIVE2D_ID_WRONGSPELLPRIMITIVE2D :
- {
- processWrongSpellPrimitive2D(static_cast<const primitive2d::WrongSpellPrimitive2D&>(rCandidate));
- break;
- }
- case PRIMITIVE2D_ID_TEXTSIMPLEPORTIONPRIMITIVE2D :
- {
- processTextSimplePortionPrimitive2D(static_cast<const primitive2d::TextSimplePortionPrimitive2D&>(rCandidate));
- break;
- }
- case PRIMITIVE2D_ID_TEXTDECORATEDPORTIONPRIMITIVE2D :
- {
- processTextDecoratedPortionPrimitive2D(static_cast<const primitive2d::TextSimplePortionPrimitive2D&>(rCandidate));
- break;
- }
- case PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D :
- {
- processPolygonHairlinePrimitive2D(static_cast<const primitive2d::PolygonHairlinePrimitive2D&>(rCandidate));
- break;
- }
- case PRIMITIVE2D_ID_BITMAPPRIMITIVE2D :
- {
- // direct draw of transformed BitmapEx primitive
- processBitmapPrimitive2D(static_cast<const primitive2d::BitmapPrimitive2D&>(rCandidate));
- break;
- }
- case PRIMITIVE2D_ID_FILLGRAPHICPRIMITIVE2D :
- {
- // direct draw of fillBitmapPrimitive
- RenderFillGraphicPrimitive2D(static_cast< const primitive2d::FillGraphicPrimitive2D& >(rCandidate));
- break;
- }
- case PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D :
- {
- processPolyPolygonGradientPrimitive2D(static_cast<const primitive2d::PolyPolygonGradientPrimitive2D&>(rCandidate));
- break;
- }
- case PRIMITIVE2D_ID_POLYPOLYGONGRAPHICPRIMITIVE2D :
- {
- // direct draw of bitmap
- RenderPolyPolygonGraphicPrimitive2D(static_cast< const primitive2d::PolyPolygonGraphicPrimitive2D& >(rCandidate));
- break;
- }
- case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D :
- {
- processPolyPolygonColorPrimitive2D(static_cast<const primitive2d::PolyPolygonColorPrimitive2D&>(rCandidate));
- break;
- }
- case PRIMITIVE2D_ID_METAFILEPRIMITIVE2D :
- {
- processMetaFilePrimitive2D(rCandidate);
- break;
- }
- case PRIMITIVE2D_ID_MASKPRIMITIVE2D :
- {
- // mask group.
- RenderMaskPrimitive2DPixel(static_cast< const primitive2d::MaskPrimitive2D& >(rCandidate));
- break;
- }
- case PRIMITIVE2D_ID_MODIFIEDCOLORPRIMITIVE2D :
- {
- // modified color group. Force output to unified color.
- RenderModifiedColorPrimitive2D(static_cast< const primitive2d::ModifiedColorPrimitive2D& >(rCandidate));
- break;
- }
- case PRIMITIVE2D_ID_UNIFIEDTRANSPARENCEPRIMITIVE2D :
- {
- processUnifiedTransparencePrimitive2D(static_cast<const primitive2d::UnifiedTransparencePrimitive2D&>(rCandidate));
- break;
- }
- case PRIMITIVE2D_ID_TRANSPARENCEPRIMITIVE2D :
- {
- // sub-transparence group. Draw to VDev first.
- RenderTransparencePrimitive2D(static_cast< const primitive2d::TransparencePrimitive2D& >(rCandidate));
- break;
- }
- case PRIMITIVE2D_ID_TRANSFORMPRIMITIVE2D :
- {
- // transform group.
- RenderTransformPrimitive2D(static_cast< const primitive2d::TransformPrimitive2D& >(rCandidate));
- break;
- }
- case PRIMITIVE2D_ID_PAGEPREVIEWPRIMITIVE2D :
- {
- // new XDrawPage for ViewInformation2D
- RenderPagePreviewPrimitive2D(static_cast< const primitive2d::PagePreviewPrimitive2D& >(rCandidate));
- break;
- }
- case PRIMITIVE2D_ID_MARKERARRAYPRIMITIVE2D :
- {
- // marker array
- RenderMarkerArrayPrimitive2D(static_cast< const primitive2d::MarkerArrayPrimitive2D& >(rCandidate));
- break;
- }
- case PRIMITIVE2D_ID_POINTARRAYPRIMITIVE2D :
- {
- // point array
- RenderPointArrayPrimitive2D(static_cast< const primitive2d::PointArrayPrimitive2D& >(rCandidate));
- break;
- }
- case PRIMITIVE2D_ID_CONTROLPRIMITIVE2D :
- {
- processControlPrimitive2D(static_cast<const primitive2d::ControlPrimitive2D&>(rCandidate));
- break;
- }
- case PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D:
- {
- processPolygonStrokePrimitive2D(static_cast<const primitive2d::PolygonStrokePrimitive2D&>(rCandidate));
- break;
- }
- case PRIMITIVE2D_ID_FILLHATCHPRIMITIVE2D :
- {
- processFillHatchPrimitive2D(static_cast<const primitive2d::FillHatchPrimitive2D&>(rCandidate));
- break;
- }
- case PRIMITIVE2D_ID_BACKGROUNDCOLORPRIMITIVE2D :
- {
- processBackgroundColorPrimitive2D(static_cast<const primitive2d::BackgroundColorPrimitive2D&>(rCandidate));
- break;
- }
- case PRIMITIVE2D_ID_TEXTHIERARCHYEDITPRIMITIVE2D :
- {
- // #i97628#
- // This primitive means that the content is derived from an active text edit,
- // not from model data itself. Some renderers need to suppress this content, e.g.
- // the pixel renderer used for displaying the edit view (like this one). It's
- // not to be suppressed by the MetaFile renderers, so that the edited text is
- // part of the MetaFile, e.g. needed for presentation previews.
- // Action: Ignore here, do nothing.
- break;
- }
- case PRIMITIVE2D_ID_INVERTPRIMITIVE2D :
- {
- processInvertPrimitive2D(rCandidate);
- break;
- }
- case PRIMITIVE2D_ID_EPSPRIMITIVE2D :
- {
- RenderEpsPrimitive2D(static_cast< const primitive2d::EpsPrimitive2D& >(rCandidate));
- break;
- }
- case PRIMITIVE2D_ID_SVGLINEARATOMPRIMITIVE2D:
- {
- RenderSvgLinearAtomPrimitive2D(static_cast< const primitive2d::SvgLinearAtomPrimitive2D& >(rCandidate));
- break;
- }
- case PRIMITIVE2D_ID_SVGRADIALATOMPRIMITIVE2D:
- {
- RenderSvgRadialAtomPrimitive2D(static_cast< const primitive2d::SvgRadialAtomPrimitive2D& >(rCandidate));
- break;
- }
- case PRIMITIVE2D_ID_BORDERLINEPRIMITIVE2D:
- {
- processBorderLinePrimitive2D(static_cast<const drawinglayer::primitive2d::BorderLinePrimitive2D&>(rCandidate));
- break;
- }
- case PRIMITIVE2D_ID_GLOWPRIMITIVE2D:
- {
- processGlowPrimitive2D(static_cast<const drawinglayer::primitive2d::GlowPrimitive2D&>(rCandidate));
- break;
- }
- default :
- {
- SAL_INFO("drawinglayer", "default case for " << drawinglayer::primitive2d::idToString(rCandidate.getPrimitive2DID()));
- // process recursively
- process(rCandidate);
- break;
- }
- }
+ processTextDecoratedPortionPrimitive2D(
+ static_cast<const primitive2d::TextSimplePortionPrimitive2D&>(rCandidate));
+ break;
}
-
- void VclPixelProcessor2D::processWrongSpellPrimitive2D(const primitive2d::WrongSpellPrimitive2D& rWrongSpellPrimitive)
+ case PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D:
{
- if(!renderWrongSpellPrimitive2D(
- rWrongSpellPrimitive,
- *mpOutputDevice,
- maCurrentTransformation,
- maBColorModifierStack))
- {
- // fallback to decomposition (MetaFile)
- process(rWrongSpellPrimitive);
- }
+ processPolygonHairlinePrimitive2D(
+ static_cast<const primitive2d::PolygonHairlinePrimitive2D&>(rCandidate));
+ break;
}
-
- void VclPixelProcessor2D::processTextSimplePortionPrimitive2D(const primitive2d::TextSimplePortionPrimitive2D& rCandidate)
+ case PRIMITIVE2D_ID_BITMAPPRIMITIVE2D:
{
- // Adapt evtl. used special DrawMode
- const DrawModeFlags nOriginalDrawMode(mpOutputDevice->GetDrawMode());
- adaptTextToFillDrawMode();
-
- if(getOptionsDrawinglayer().IsRenderSimpleTextDirect())
- {
- RenderTextSimpleOrDecoratedPortionPrimitive2D(rCandidate);
- }
- else
- {
- process(rCandidate);
- }
-
- // restore DrawMode
- mpOutputDevice->SetDrawMode(nOriginalDrawMode);
+ // direct draw of transformed BitmapEx primitive
+ processBitmapPrimitive2D(
+ static_cast<const primitive2d::BitmapPrimitive2D&>(rCandidate));
+ break;
}
-
- void VclPixelProcessor2D::processTextDecoratedPortionPrimitive2D(const primitive2d::TextSimplePortionPrimitive2D& rCandidate)
+ case PRIMITIVE2D_ID_FILLGRAPHICPRIMITIVE2D:
{
- // Adapt evtl. used special DrawMode
- const DrawModeFlags nOriginalDrawMode(mpOutputDevice->GetDrawMode());
- adaptTextToFillDrawMode();
-
- if(getOptionsDrawinglayer().IsRenderDecoratedTextDirect())
- {
- RenderTextSimpleOrDecoratedPortionPrimitive2D(rCandidate);
- }
- else
- {
- process(rCandidate);
- }
-
- // restore DrawMode
- mpOutputDevice->SetDrawMode(nOriginalDrawMode);
+ // direct draw of fillBitmapPrimitive
+ RenderFillGraphicPrimitive2D(
+ static_cast<const primitive2d::FillGraphicPrimitive2D&>(rCandidate));
+ break;
}
-
- void VclPixelProcessor2D::processPolygonHairlinePrimitive2D(const primitive2d::PolygonHairlinePrimitive2D& rPolygonHairlinePrimitive2D)
+ case PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D:
{
- if(tryDrawPolygonHairlinePrimitive2DDirect(rPolygonHairlinePrimitive2D, 0.0))
- {
- return;
- }
-
- // direct draw of hairline
- RenderPolygonHairlinePrimitive2D(rPolygonHairlinePrimitive2D, true);
+ processPolyPolygonGradientPrimitive2D(
+ static_cast<const primitive2d::PolyPolygonGradientPrimitive2D&>(rCandidate));
+ break;
}
-
- void VclPixelProcessor2D::processBitmapPrimitive2D(const primitive2d::BitmapPrimitive2D& rBitmapCandidate)
+ case PRIMITIVE2D_ID_POLYPOLYGONGRAPHICPRIMITIVE2D:
{
- // check if graphic content is inside discrete local ViewPort
- const basegfx::B2DRange& rDiscreteViewPort(getViewInformation2D().getDiscreteViewport());
- const basegfx::B2DHomMatrix aLocalTransform(maCurrentTransformation * rBitmapCandidate.getTransform());
-
- if(!rDiscreteViewPort.isEmpty())
- {
- basegfx::B2DRange aUnitRange(0.0, 0.0, 1.0, 1.0);
-
- aUnitRange.transform(aLocalTransform);
-
- if(!aUnitRange.overlaps(rDiscreteViewPort))
- {
- // content is outside discrete local ViewPort
- return;
- }
- }
-
- RenderBitmapPrimitive2D(rBitmapCandidate);
+ // direct draw of bitmap
+ RenderPolyPolygonGraphicPrimitive2D(
+ static_cast<const primitive2d::PolyPolygonGraphicPrimitive2D&>(rCandidate));
+ break;
}
-
- void VclPixelProcessor2D::processPolyPolygonGradientPrimitive2D(const primitive2d::PolyPolygonGradientPrimitive2D& rPolygonCandidate)
+ case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D:
{
- // direct draw of gradient
- const attribute::FillGradientAttribute& rGradient(rPolygonCandidate.getFillGradient());
- basegfx::BColor aStartColor(maBColorModifierStack.getModifiedColor(rGradient.getStartColor()));
- basegfx::BColor aEndColor(maBColorModifierStack.getModifiedColor(rGradient.getEndColor()));
- basegfx::B2DPolyPolygon aLocalPolyPolygon(rPolygonCandidate.getB2DPolyPolygon());
-
- if(!aLocalPolyPolygon.count())
- return;
-
- aLocalPolyPolygon.transform(maCurrentTransformation);
-
- if(aStartColor == aEndColor)
- {
- // no gradient at all, draw as polygon in AA and non-AA case
- mpOutputDevice->SetLineColor();
- mpOutputDevice->SetFillColor(Color(aStartColor));
- mpOutputDevice->DrawPolyPolygon(aLocalPolyPolygon);
- }
- else
- {
- // use the primitive decomposition of the metafile
- process(rPolygonCandidate);
- }
+ processPolyPolygonColorPrimitive2D(
+ static_cast<const primitive2d::PolyPolygonColorPrimitive2D&>(rCandidate));
+ break;
}
-
- void VclPixelProcessor2D::processPolyPolygonColorPrimitive2D(const primitive2d::PolyPolygonColorPrimitive2D& rPolyPolygonColorPrimitive2D)
+ case PRIMITIVE2D_ID_METAFILEPRIMITIVE2D:
{
- // try to use directly
- basegfx::B2DPolyPolygon aLocalPolyPolygon;
-
- tryDrawPolyPolygonColorPrimitive2DDirect(rPolyPolygonColorPrimitive2D, 0.0);
- // okay, done. In this case no gaps should have to be repaired, too
-
- // when AA is on and this filled polygons are the result of stroked line geometry,
- // draw the geometry once extra as lines to avoid AA 'gaps' between partial polygons
- // Caution: This is needed in both cases (!)
- if(!(mnPolygonStrokePrimitive2D
- && getOptionsDrawinglayer().IsAntiAliasing()
- && (mpOutputDevice->GetAntialiasing() & AntialiasingFlags::EnableB2dDraw)))
- return;
-
- const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(rPolyPolygonColorPrimitive2D.getBColor()));
- sal_uInt32 nCount(aLocalPolyPolygon.count());
-
- if(!nCount)
- {
- aLocalPolyPolygon = rPolyPolygonColorPrimitive2D.getB2DPolyPolygon();
- aLocalPolyPolygon.transform(maCurrentTransformation);
- nCount = aLocalPolyPolygon.count();
- }
-
- mpOutputDevice->SetFillColor();
- mpOutputDevice->SetLineColor(Color(aPolygonColor));
-
- for(sal_uInt32 a(0); a < nCount; a++)
- {
- mpOutputDevice->DrawPolyLine(aLocalPolyPolygon.getB2DPolygon(a), 0.0);
- }
+ processMetaFilePrimitive2D(rCandidate);
+ break;
}
-
- void VclPixelProcessor2D::processUnifiedTransparencePrimitive2D(const primitive2d::UnifiedTransparencePrimitive2D& rUniTransparenceCandidate)
+ case PRIMITIVE2D_ID_MASKPRIMITIVE2D:
{
- // Detect if a single PolyPolygonColorPrimitive2D is contained; in that case,
- // use the faster OutputDevice::DrawTransparent method
- const primitive2d::Primitive2DContainer& rContent = rUniTransparenceCandidate.getChildren();
-
- if(rContent.empty())
- return;
-
- if(0.0 == rUniTransparenceCandidate.getTransparence())
- {
- // not transparent at all, use content
- process(rUniTransparenceCandidate.getChildren());
- }
- else if(rUniTransparenceCandidate.getTransparence() > 0.0 && rUniTransparenceCandidate.getTransparence() < 1.0)
- {
- bool bDrawTransparentUsed(false);
-
- if(1 == rContent.size())
- {
- const primitive2d::Primitive2DReference xReference(rContent[0]);
- const primitive2d::BasePrimitive2D* pBasePrimitive = dynamic_cast< const primitive2d::BasePrimitive2D* >(xReference.get());
-
- if(pBasePrimitive)
- {
- switch(pBasePrimitive->getPrimitive2DID())
- {
- case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D:
- {
- // single transparent tools::PolyPolygon identified, use directly
- const primitive2d::PolyPolygonColorPrimitive2D* pPoPoColor = static_cast< const primitive2d::PolyPolygonColorPrimitive2D* >(pBasePrimitive);
- SAL_WARN_IF(!pPoPoColor, "drawinglayer", "OOps, PrimitiveID and PrimitiveType do not match (!)");
- bDrawTransparentUsed = true;
- tryDrawPolyPolygonColorPrimitive2DDirect(*pPoPoColor, rUniTransparenceCandidate.getTransparence());
- break;
- }
- case PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D:
- {
- // single transparent PolygonHairlinePrimitive2D identified, use directly
- const primitive2d::PolygonHairlinePrimitive2D* pPoHair = static_cast< const primitive2d::PolygonHairlinePrimitive2D* >(pBasePrimitive);
- SAL_WARN_IF(!pPoHair, "drawinglayer", "OOps, PrimitiveID and PrimitiveType do not match (!)");
-
- // do no tallow by default - problem is that self-overlapping parts of this geometry will
- // not be in an all-same transparency but will already alpha-cover themselves with blending.
- // This is not what the UnifiedTransparencePrimitive2D defines: It requires all its
- // content to be uniformly transparent.
- // For hairline the effect is pretty minimal, but still not correct.
- bDrawTransparentUsed = false;
- break;
- }
- case PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D:
- {
- // single transparent PolygonStrokePrimitive2D identified, use directly
- const primitive2d::PolygonStrokePrimitive2D* pPoStroke = static_cast< const primitive2d::PolygonStrokePrimitive2D* >(pBasePrimitive);
- SAL_WARN_IF(!pPoStroke, "drawinglayer", "OOps, PrimitiveID and PrimitiveType do not match (!)");
-
- // do no tallow by default - problem is that self-overlapping parts of this geometry will
- // not be in an all-same transparency but will already alpha-cover themselves with blending.
- // This is not what the UnifiedTransparencePrimitive2D defines: It requires all its
- // content to be uniformly transparent.
- // To check, activate and draw a wide transparent self-crossing line/curve
- bDrawTransparentUsed = false;
- break;
- }
- default:
- SAL_INFO("drawinglayer", "default case for " << drawinglayer::primitive2d::idToString(rUniTransparenceCandidate.getPrimitive2DID()));
- break;
- }
- }
- }
-
- if(!bDrawTransparentUsed)
- {
- // unified sub-transparence. Draw to VDev first.
- RenderUnifiedTransparencePrimitive2D(rUniTransparenceCandidate);
- }
- }
+ // mask group.
+ RenderMaskPrimitive2DPixel(
+ static_cast<const primitive2d::MaskPrimitive2D&>(rCandidate));
+ break;
}
-
- void VclPixelProcessor2D::processControlPrimitive2D(const primitive2d::ControlPrimitive2D& rControlPrimitive)
+ case PRIMITIVE2D_ID_MODIFIEDCOLORPRIMITIVE2D:
{
- // control primitive
- const uno::Reference< awt::XControl >& rXControl(rControlPrimitive.getXControl());
-
- try
- {
- // remember old graphics and create new
- uno::Reference< awt::XView > xControlView(rXControl, uno::UNO_QUERY_THROW);
- const uno::Reference< awt::XGraphics > xOriginalGraphics(xControlView->getGraphics());
- const uno::Reference< awt::XGraphics > xNewGraphics(mpOutputDevice->CreateUnoGraphics());
-
- if(xNewGraphics.is())
- {
- // link graphics and view
- xControlView->setGraphics(xNewGraphics);
-
- // get position
- const basegfx::B2DHomMatrix aObjectToPixel(maCurrentTransformation * rControlPrimitive.getTransform());
- const basegfx::B2DPoint aTopLeftPixel(aObjectToPixel * basegfx::B2DPoint(0.0, 0.0));
-
- // find out if the control is already visualized as a VCL-ChildWindow. If yes,
- // it does not need to be painted at all.
- uno::Reference< awt::XWindow2 > xControlWindow(rXControl, uno::UNO_QUERY_THROW);
- const bool bControlIsVisibleAsChildWindow(rXControl->getPeer().is() && xControlWindow->isVisible());
-
- if(!bControlIsVisibleAsChildWindow)
- {
- // draw it. Do not forget to use the evtl. offsetted origin of the target device,
- // e.g. when used with mask/transparence buffer device
- const Point aOrigin(mpOutputDevice->GetMapMode().GetOrigin());
- xControlView->draw(
- aOrigin.X() + basegfx::fround(aTopLeftPixel.getX()),
- aOrigin.Y() + basegfx::fround(aTopLeftPixel.getY()));
- }
-
- // restore original graphics
- xControlView->setGraphics(xOriginalGraphics);
- }
- }
- catch(const uno::Exception&)
- {
- // #i116763# removing since there is a good alternative when the xControlView
- // is not found and it is allowed to happen
- // DBG_UNHANDLED_EXCEPTION();
-
- // process recursively and use the decomposition as Bitmap
- process(rControlPrimitive);
- }
+ // modified color group. Force output to unified color.
+ RenderModifiedColorPrimitive2D(
+ static_cast<const primitive2d::ModifiedColorPrimitive2D&>(rCandidate));
+ break;
}
-
- void VclPixelProcessor2D::processPolygonStrokePrimitive2D(const primitive2d::PolygonStrokePrimitive2D& rPolygonStrokePrimitive2D)
+ case PRIMITIVE2D_ID_UNIFIEDTRANSPARENCEPRIMITIVE2D:
{
- // try to use directly
- if(tryDrawPolygonStrokePrimitive2DDirect(rPolygonStrokePrimitive2D, 0.0))
- {
- return;
- }
+ processUnifiedTransparencePrimitive2D(
+ static_cast<const primitive2d::UnifiedTransparencePrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_TRANSPARENCEPRIMITIVE2D:
+ {
+ // sub-transparence group. Draw to VDev first.
+ RenderTransparencePrimitive2D(
+ static_cast<const primitive2d::TransparencePrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_TRANSFORMPRIMITIVE2D:
+ {
+ // transform group.
+ RenderTransformPrimitive2D(
+ static_cast<const primitive2d::TransformPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_PAGEPREVIEWPRIMITIVE2D:
+ {
+ // new XDrawPage for ViewInformation2D
+ RenderPagePreviewPrimitive2D(
+ static_cast<const primitive2d::PagePreviewPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_MARKERARRAYPRIMITIVE2D:
+ {
+ // marker array
+ RenderMarkerArrayPrimitive2D(
+ static_cast<const primitive2d::MarkerArrayPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_POINTARRAYPRIMITIVE2D:
+ {
+ // point array
+ RenderPointArrayPrimitive2D(
+ static_cast<const primitive2d::PointArrayPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_CONTROLPRIMITIVE2D:
+ {
+ processControlPrimitive2D(
+ static_cast<const primitive2d::ControlPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D:
+ {
+ processPolygonStrokePrimitive2D(
+ static_cast<const primitive2d::PolygonStrokePrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_FILLHATCHPRIMITIVE2D:
+ {
+ processFillHatchPrimitive2D(
+ static_cast<const primitive2d::FillHatchPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_BACKGROUNDCOLORPRIMITIVE2D:
+ {
+ processBackgroundColorPrimitive2D(
+ static_cast<const primitive2d::BackgroundColorPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_TEXTHIERARCHYEDITPRIMITIVE2D:
+ {
+ // #i97628#
+ // This primitive means that the content is derived from an active text edit,
+ // not from model data itself. Some renderers need to suppress this content, e.g.
+ // the pixel renderer used for displaying the edit view (like this one). It's
+ // not to be suppressed by the MetaFile renderers, so that the edited text is
+ // part of the MetaFile, e.g. needed for presentation previews.
+ // Action: Ignore here, do nothing.
+ break;
+ }
+ case PRIMITIVE2D_ID_INVERTPRIMITIVE2D:
+ {
+ processInvertPrimitive2D(rCandidate);
+ break;
+ }
+ case PRIMITIVE2D_ID_EPSPRIMITIVE2D:
+ {
+ RenderEpsPrimitive2D(static_cast<const primitive2d::EpsPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_SVGLINEARATOMPRIMITIVE2D:
+ {
+ RenderSvgLinearAtomPrimitive2D(
+ static_cast<const primitive2d::SvgLinearAtomPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_SVGRADIALATOMPRIMITIVE2D:
+ {
+ RenderSvgRadialAtomPrimitive2D(
+ static_cast<const primitive2d::SvgRadialAtomPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_BORDERLINEPRIMITIVE2D:
+ {
+ processBorderLinePrimitive2D(
+ static_cast<const drawinglayer::primitive2d::BorderLinePrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_GLOWPRIMITIVE2D:
+ {
+ processGlowPrimitive2D(
+ static_cast<const drawinglayer::primitive2d::GlowPrimitive2D&>(rCandidate));
+ break;
+ }
+ default:
+ {
+ SAL_INFO("drawinglayer", "default case for " << drawinglayer::primitive2d::idToString(
+ rCandidate.getPrimitive2DID()));
+ // process recursively
+ process(rCandidate);
+ break;
+ }
+ }
+}
- // the stroke primitive may be decomposed to filled polygons. To keep
- // evtl. set DrawModes aka DrawModeFlags::BlackLine, DrawModeFlags::GrayLine,
- // DrawModeFlags::GhostedLine, DrawModeFlags::WhiteLine or DrawModeFlags::SettingsLine
- // working, these need to be copied to the corresponding fill modes
- const DrawModeFlags nOriginalDrawMode(mpOutputDevice->GetDrawMode());
- adaptLineToFillDrawMode();
+void VclPixelProcessor2D::processWrongSpellPrimitive2D(
+ const primitive2d::WrongSpellPrimitive2D& rWrongSpellPrimitive)
+{
+ if (!renderWrongSpellPrimitive2D(rWrongSpellPrimitive, *mpOutputDevice, maCurrentTransformation,
+ maBColorModifierStack))
+ {
+ // fallback to decomposition (MetaFile)
+ process(rWrongSpellPrimitive);
+ }
+}
+
+void VclPixelProcessor2D::processTextSimplePortionPrimitive2D(
+ const primitive2d::TextSimplePortionPrimitive2D& rCandidate)
+{
+ // Adapt evtl. used special DrawMode
+ const DrawModeFlags nOriginalDrawMode(mpOutputDevice->GetDrawMode());
+ adaptTextToFillDrawMode();
+
+ if (getOptionsDrawinglayer().IsRenderSimpleTextDirect())
+ {
+ RenderTextSimpleOrDecoratedPortionPrimitive2D(rCandidate);
+ }
+ else
+ {
+ process(rCandidate);
+ }
+
+ // restore DrawMode
+ mpOutputDevice->SetDrawMode(nOriginalDrawMode);
+}
+
+void VclPixelProcessor2D::processTextDecoratedPortionPrimitive2D(
+ const primitive2d::TextSimplePortionPrimitive2D& rCandidate)
+{
+ // Adapt evtl. used special DrawMode
+ const DrawModeFlags nOriginalDrawMode(mpOutputDevice->GetDrawMode());
+ adaptTextToFillDrawMode();
+
+ if (getOptionsDrawinglayer().IsRenderDecoratedTextDirect())
+ {
+ RenderTextSimpleOrDecoratedPortionPrimitive2D(rCandidate);
+ }
+ else
+ {
+ process(rCandidate);
+ }
+
+ // restore DrawMode
+ mpOutputDevice->SetDrawMode(nOriginalDrawMode);
+}
+
+void VclPixelProcessor2D::processPolygonHairlinePrimitive2D(
+ const primitive2d::PolygonHairlinePrimitive2D& rPolygonHairlinePrimitive2D)
+{
+ if (tryDrawPolygonHairlinePrimitive2DDirect(rPolygonHairlinePrimitive2D, 0.0))
+ {
+ return;
+ }
- // polygon stroke primitive
+ // direct draw of hairline
+ RenderPolygonHairlinePrimitive2D(rPolygonHairlinePrimitive2D, true);
+}
- // Lines with 1 and 2 pixel width without AA need special treatment since their visualization
- // as filled polygons is geometrically correct but looks wrong since polygon filling avoids
- // the right and bottom pixels. The used method evaluates that and takes the correct action,
- // including calling recursively with decomposition if line is wide enough
- RenderPolygonStrokePrimitive2D(rPolygonStrokePrimitive2D);
+void VclPixelProcessor2D::processBitmapPrimitive2D(
+ const primitive2d::BitmapPrimitive2D& rBitmapCandidate)
+{
+ // check if graphic content is inside discrete local ViewPort
+ const basegfx::B2DRange& rDiscreteViewPort(getViewInformation2D().getDiscreteViewport());
+ const basegfx::B2DHomMatrix aLocalTransform(maCurrentTransformation
+ * rBitmapCandidate.getTransform());
- // restore DrawMode
- mpOutputDevice->SetDrawMode(nOriginalDrawMode);
- }
+ if (!rDiscreteViewPort.isEmpty())
+ {
+ basegfx::B2DRange aUnitRange(0.0, 0.0, 1.0, 1.0);
- void VclPixelProcessor2D::processFillHatchPrimitive2D(const primitive2d::FillHatchPrimitive2D& rFillHatchPrimitive)
- {
- if(getOptionsDrawinglayer().IsAntiAliasing())
- {
- // if AA is used (or ignore smoothing is on), there is no need to smooth
- // hatch painting, use decomposition
- process(rFillHatchPrimitive);
- }
- else
- {
- // without AA, use VCL to draw the hatch. It snaps hatch distances to the next pixel
- // and forces hatch distance to be >= 3 pixels to make the hatch display look smoother.
- // This is wrong in principle, but looks nicer. This could also be done here directly
- // without VCL usage if needed
- const attribute::FillHatchAttribute& rFillHatchAttributes = rFillHatchPrimitive.getFillHatch();
-
- // create hatch polygon in range size and discrete coordinates
- basegfx::B2DRange aHatchRange(rFillHatchPrimitive.getOutputRange());
- aHatchRange.transform(maCurrentTransformation);
- const basegfx::B2DPolygon aHatchPolygon(basegfx::utils::createPolygonFromRect(aHatchRange));
-
- if(rFillHatchAttributes.isFillBackground())
- {
- // #i111846# background fill is active; draw fill polygon
- const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(rFillHatchPrimitive.getBColor()));
+ aUnitRange.transform(aLocalTransform);
- mpOutputDevice->SetFillColor(Color(aPolygonColor));
- mpOutputDevice->SetLineColor();
- mpOutputDevice->DrawPolygon(aHatchPolygon);
- }
+ if (!aUnitRange.overlaps(rDiscreteViewPort))
+ {
+ // content is outside discrete local ViewPort
+ return;
+ }
+ }
- // set hatch line color
- const basegfx::BColor aHatchColor(maBColorModifierStack.getModifiedColor(rFillHatchPrimitive.getBColor()));
- mpOutputDevice->SetFillColor();
- mpOutputDevice->SetLineColor(Color(aHatchColor));
+ RenderBitmapPrimitive2D(rBitmapCandidate);
+}
- // get hatch style
- HatchStyle eHatchStyle(HatchStyle::Single);
+void VclPixelProcessor2D::processPolyPolygonGradientPrimitive2D(
+ const primitive2d::PolyPolygonGradientPrimitive2D& rPolygonCandidate)
+{
+ // direct draw of gradient
+ const attribute::FillGradientAttribute& rGradient(rPolygonCandidate.getFillGradient());
+ basegfx::BColor aStartColor(maBColorModifierStack.getModifiedColor(rGradient.getStartColor()));
+ basegfx::BColor aEndColor(maBColorModifierStack.getModifiedColor(rGradient.getEndColor()));
+ basegfx::B2DPolyPolygon aLocalPolyPolygon(rPolygonCandidate.getB2DPolyPolygon());
+
+ if (!aLocalPolyPolygon.count())
+ return;
+
+ aLocalPolyPolygon.transform(maCurrentTransformation);
+
+ if (aStartColor == aEndColor)
+ {
+ // no gradient at all, draw as polygon in AA and non-AA case
+ mpOutputDevice->SetLineColor();
+ mpOutputDevice->SetFillColor(Color(aStartColor));
+ mpOutputDevice->DrawPolyPolygon(aLocalPolyPolygon);
+ }
+ else
+ {
+ // use the primitive decomposition of the metafile
+ process(rPolygonCandidate);
+ }
+}
+
+void VclPixelProcessor2D::processPolyPolygonColorPrimitive2D(
+ const primitive2d::PolyPolygonColorPrimitive2D& rPolyPolygonColorPrimitive2D)
+{
+ // try to use directly
+ basegfx::B2DPolyPolygon aLocalPolyPolygon;
+
+ tryDrawPolyPolygonColorPrimitive2DDirect(rPolyPolygonColorPrimitive2D, 0.0);
+ // okay, done. In this case no gaps should have to be repaired, too
+
+ // when AA is on and this filled polygons are the result of stroked line geometry,
+ // draw the geometry once extra as lines to avoid AA 'gaps' between partial polygons
+ // Caution: This is needed in both cases (!)
+ if (!(mnPolygonStrokePrimitive2D && getOptionsDrawinglayer().IsAntiAliasing()
+ && (mpOutputDevice->GetAntialiasing() & AntialiasingFlags::EnableB2dDraw)))
+ return;
+
+ const basegfx::BColor aPolygonColor(
+ maBColorModifierStack.getModifiedColor(rPolyPolygonColorPrimitive2D.getBColor()));
+ sal_uInt32 nCount(aLocalPolyPolygon.count());
+
+ if (!nCount)
+ {
+ aLocalPolyPolygon = rPolyPolygonColorPrimitive2D.getB2DPolyPolygon();
+ aLocalPolyPolygon.transform(maCurrentTransformation);
+ nCount = aLocalPolyPolygon.count();
+ }
+
+ mpOutputDevice->SetFillColor();
+ mpOutputDevice->SetLineColor(Color(aPolygonColor));
+
+ for (sal_uInt32 a(0); a < nCount; a++)
+ {
+ mpOutputDevice->DrawPolyLine(aLocalPolyPolygon.getB2DPolygon(a), 0.0);
+ }
+}
+
+void VclPixelProcessor2D::processUnifiedTransparencePrimitive2D(
+ const primitive2d::UnifiedTransparencePrimitive2D& rUniTransparenceCandidate)
+{
+ // Detect if a single PolyPolygonColorPrimitive2D is contained; in that case,
+ // use the faster OutputDevice::DrawTransparent method
+ const primitive2d::Primitive2DContainer& rContent = rUniTransparenceCandidate.getChildren();
+
+ if (rContent.empty())
+ return;
+
+ if (0.0 == rUniTransparenceCandidate.getTransparence())
+ {
+ // not transparent at all, use content
+ process(rUniTransparenceCandidate.getChildren());
+ }
+ else if (rUniTransparenceCandidate.getTransparence() > 0.0
+ && rUniTransparenceCandidate.getTransparence() < 1.0)
+ {
+ bool bDrawTransparentUsed(false);
+
+ if (1 == rContent.size())
+ {
+ const primitive2d::Primitive2DReference xReference(rContent[0]);
+ const primitive2d::BasePrimitive2D* pBasePrimitive
+ = dynamic_cast<const primitive2d::BasePrimitive2D*>(xReference.get());
- switch(rFillHatchAttributes.getStyle())
+ if (pBasePrimitive)
+ {
+ switch (pBasePrimitive->getPrimitive2DID())
{
- default : // HatchStyle::Single
+ case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D:
{
+ // single transparent tools::PolyPolygon identified, use directly
+ const primitive2d::PolyPolygonColorPrimitive2D* pPoPoColor
+ = static_cast<const primitive2d::PolyPolygonColorPrimitive2D*>(
+ pBasePrimitive);
+ SAL_WARN_IF(!pPoPoColor, "drawinglayer",
+ "OOps, PrimitiveID and PrimitiveType do not match (!)");
+ bDrawTransparentUsed = true;
+ tryDrawPolyPolygonColorPrimitive2DDirect(
+ *pPoPoColor, rUniTransparenceCandidate.getTransparence());
break;
}
- case attribute::HatchStyle::Double :
+ case PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D:
{
- eHatchStyle = HatchStyle::Double;
+ // single transparent PolygonHairlinePrimitive2D identified, use directly
+ const primitive2d::PolygonHairlinePrimitive2D* pPoHair
+ = static_cast<const primitive2d::PolygonHairlinePrimitive2D*>(
+ pBasePrimitive);
+ SAL_WARN_IF(!pPoHair, "drawinglayer",
+ "OOps, PrimitiveID and PrimitiveType do not match (!)");
+
+ // do no tallow by default - problem is that self-overlapping parts of this geometry will
+ // not be in an all-same transparency but will already alpha-cover themselves with blending.
+ // This is not what the UnifiedTransparencePrimitive2D defines: It requires all its
+ // content to be uniformly transparent.
+ // For hairline the effect is pretty minimal, but still not correct.
+ bDrawTransparentUsed = false;
break;
}
- case attribute::HatchStyle::Triple :
+ case PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D:
{
- eHatchStyle = HatchStyle::Triple;
+ // single transparent PolygonStrokePrimitive2D identified, use directly
+ const primitive2d::PolygonStrokePrimitive2D* pPoStroke
+ = static_cast<const primitive2d::PolygonStrokePrimitive2D*>(
+ pBasePrimitive);
+ SAL_WARN_IF(!pPoStroke, "drawinglayer",
+ "OOps, PrimitiveID and PrimitiveType do not match (!)");
+
+ // do no tallow by default - problem is that self-overlapping parts of this geometry will
+ // not be in an all-same transparency but will already alpha-cover themselves with blending.
+ // This is not what the UnifiedTransparencePrimitive2D defines: It requires all its
+ // content to be uniformly transparent.
+ // To check, activate and draw a wide transparent self-crossing line/curve
+ bDrawTransparentUsed = false;
break;
}
+ default:
+ SAL_INFO("drawinglayer",
+ "default case for " << drawinglayer::primitive2d::idToString(
+ rUniTransparenceCandidate.getPrimitive2DID()));
+ break;
}
-
- // create hatch
- const basegfx::B2DVector aDiscreteDistance(maCurrentTransformation * basegfx::B2DVector(rFillHatchAttributes.getDistance(), 0.0));
- const sal_uInt32 nDistance(basegfx::fround(aDiscreteDistance.getLength()));
- const sal_uInt16 nAngle10(static_cast<sal_uInt16>(basegfx::fround(rFillHatchAttributes.getAngle() / F_PI1800)));
- ::Hatch aVCLHatch(eHatchStyle, Color(rFillHatchAttributes.getColor()), nDistance, nAngle10);
-
- // draw hatch using VCL
- mpOutputDevice->DrawHatch(::tools::PolyPolygon(::tools::Polygon(aHatchPolygon)), aVCLHatch);
}
}
- void VclPixelProcessor2D::processBackgroundColorPrimitive2D(const primitive2d::BackgroundColorPrimitive2D& rPrimitive)
+ if (!bDrawTransparentUsed)
{
- // #i98404# Handle directly, especially when AA is active
- const AntialiasingFlags nOriginalAA(mpOutputDevice->GetAntialiasing());
+ // unified sub-transparence. Draw to VDev first.
+ RenderUnifiedTransparencePrimitive2D(rUniTransparenceCandidate);
+ }
+ }
+}
- // switch AA off in all cases
- mpOutputDevice->SetAntialiasing(mpOutputDevice->GetAntialiasing() & ~AntialiasingFlags::EnableB2dDraw);
+void VclPixelProcessor2D::processControlPrimitive2D(
+ const primitive2d::ControlPrimitive2D& rControlPrimitive)
+{
+ // control primitive
+ const uno::Reference<awt::XControl>& rXControl(rControlPrimitive.getXControl());
- // create color for fill
- const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(rPrimitive.getBColor()));
- Color aFillColor(aPolygonColor);
- aFillColor.SetTransparency(sal_uInt8((rPrimitive.getTransparency() * 255.0) + 0.5));
- mpOutputDevice->SetFillColor(aFillColor);
- mpOutputDevice->SetLineColor();
+ try
+ {
+ // remember old graphics and create new
+ uno::Reference<awt::XView> xControlView(rXControl, uno::UNO_QUERY_THROW);
+ const uno::Reference<awt::XGraphics> xOriginalGraphics(xControlView->getGraphics());
+ const uno::Reference<awt::XGraphics> xNewGraphics(mpOutputDevice->CreateUnoGraphics());
- // create rectangle for fill
- const basegfx::B2DRange& aViewport(getViewInformation2D().getDiscreteViewport());
- const ::tools::Rectangle aRectangle(
- static_cast<sal_Int32>(floor(aViewport.getMinX())), static_cast<sal_Int32>(floor(aViewport.getMinY())),
- static_cast<sal_Int32>(ceil(aViewport.getMaxX())), static_cast<sal_Int32>(ceil(aViewport.getMaxY())));
- mpOutputDevice->DrawRect(aRectangle);
-
- // restore AA setting
- mpOutputDevice->SetAntialiasing(nOriginalAA);
- }
-
- void VclPixelProcessor2D::processBorderLinePrimitive2D(const drawinglayer::primitive2d::BorderLinePrimitive2D& rBorder)
- {
- // Process recursively, but switch off AntiAliasing for
- // horizontal/vertical lines (*not* diagonal lines).
- // Checked using AntialiasingFlags::PixelSnapHairline instead,
- // but with AntiAliasing on the display really is too 'ghosty' when
- // using fine stroking. Correct, but 'ghosty'.
-
- // It has shown that there are quite some problems here:
- // - vcl OutDev renderer methods still use fallbacks to paint
- // multiple single lines between discrete sizes of < 3.5 what
- // looks bad and does not match
- // - mix of filled Polygons and Lines is bad when AA switched off
- // - Alignment of AA with non-AA may be bad in diverse different
- // renderers
- //
- // Due to these reasons I change the strategy: Always draw AAed, but
- // allow fallback to test/check and if needed. The normal case
- // where BorderLines will be system-dependently snapped to have at
- // least a single discrete width per partial line (there may be up to
- // three) works well nowadays due to most renderers moving the AA stuff
- // by 0.5 pixels (discrete units) to match well with the non-AAed parts.
- //
- // Env-Switch for steering this, default is off.
- // Enable by setting at all (and to something)
- static const char* pSwitchOffAntiAliasingForHorVerBorderlines(getenv("SAL_SWITCH_OFF_ANTIALIASING_FOR_HOR_VER_BORTDERLINES"));
- static bool bSwitchOffAntiAliasingForHorVerBorderlines(nullptr != pSwitchOffAntiAliasingForHorVerBorderlines);
-
- if (bSwitchOffAntiAliasingForHorVerBorderlines && rBorder.isHorizontalOrVertical(getViewInformation2D()))
- {
- AntialiasingFlags nAntiAliasing = mpOutputDevice->GetAntialiasing();
- mpOutputDevice->SetAntialiasing(nAntiAliasing & ~AntialiasingFlags::EnableB2dDraw);
- process(rBorder);
- mpOutputDevice->SetAntialiasing(nAntiAliasing);
- }
- else
+ if (xNewGraphics.is())
+ {
+ // link graphics and view
+ xControlView->setGraphics(xNewGraphics);
+
+ // get position
+ const basegfx::B2DHomMatrix aObjectToPixel(maCurrentTransformation
+ * rControlPrimitive.getTransform());
+ const basegfx::B2DPoint aTopLeftPixel(aObjectToPixel * basegfx::B2DPoint(0.0, 0.0));
+
+ // find out if the control is already visualized as a VCL-ChildWindow. If yes,
+ // it does not need to be painted at all.
+ uno::Reference<awt::XWindow2> xControlWindow(rXControl, uno::UNO_QUERY_THROW);
+ const bool bControlIsVisibleAsChildWindow(rXControl->getPeer().is()
+ && xControlWindow->isVisible());
+
+ if (!bControlIsVisibleAsChildWindow)
{
- process(rBorder);
+ // draw it. Do not forget to use the evtl. offsetted origin of the target device,
+ // e.g. when used with mask/transparence buffer device
+ const Point aOrigin(mpOutputDevice->GetMapMode().GetOrigin());
+ xControlView->draw(aOrigin.X() + basegfx::fround(aTopLeftPixel.getX()),
+ aOrigin.Y() + basegfx::fround(aTopLeftPixel.getY()));
}
- }
- void VclPixelProcessor2D::processInvertPrimitive2D(const primitive2d::BasePrimitive2D& rCandidate)
+ // restore original graphics
+ xControlView->setGraphics(xOriginalGraphics);
+ }
+ }
+ catch (const uno::Exception&)
+ {
+ // #i116763# removing since there is a good alternative when the xControlView
+ // is not found and it is allowed to happen
+ // DBG_UNHANDLED_EXCEPTION();
+
+ // process recursively and use the decomposition as Bitmap
+ process(rControlPrimitive);
+ }
+}
+
+void VclPixelProcessor2D::processPolygonStrokePrimitive2D(
+ const primitive2d::PolygonStrokePrimitive2D& rPolygonStrokePrimitive2D)
+{
+ // try to use directly
+ if (tryDrawPolygonStrokePrimitive2DDirect(rPolygonStrokePrimitive2D, 0.0))
+ {
+ return;
+ }
+
+ // the stroke primitive may be decomposed to filled polygons. To keep
+ // evtl. set DrawModes aka DrawModeFlags::BlackLine, DrawModeFlags::GrayLine,
+ // DrawModeFlags::GhostedLine, DrawModeFlags::WhiteLine or DrawModeFlags::SettingsLine
+ // working, these need to be copied to the corresponding fill modes
+ const DrawModeFlags nOriginalDrawMode(mpOutputDevice->GetDrawMode());
+ adaptLineToFillDrawMode();
+
+ // polygon stroke primitive
+
+ // Lines with 1 and 2 pixel width without AA need special treatment since their visualization
+ // as filled polygons is geometrically correct but looks wrong since polygon filling avoids
+ // the right and bottom pixels. The used method evaluates that and takes the correct action,
+ // including calling recursively with decomposition if line is wide enough
+ RenderPolygonStrokePrimitive2D(rPolygonStrokePrimitive2D);
+
+ // restore DrawMode
+ mpOutputDevice->SetDrawMode(nOriginalDrawMode);
+}
+
+void VclPixelProcessor2D::processFillHatchPrimitive2D(
+ const primitive2d::FillHatchPrimitive2D& rFillHatchPrimitive)
+{
+ if (getOptionsDrawinglayer().IsAntiAliasing())
+ {
+ // if AA is used (or ignore smoothing is on), there is no need to smooth
+ // hatch painting, use decomposition
+ process(rFillHatchPrimitive);
+ }
+ else
+ {
+ // without AA, use VCL to draw the hatch. It snaps hatch distances to the next pixel
+ // and forces hatch distance to be >= 3 pixels to make the hatch display look smoother.
+ // This is wrong in principle, but looks nicer. This could also be done here directly
+ // without VCL usage if needed
+ const attribute::FillHatchAttribute& rFillHatchAttributes
+ = rFillHatchPrimitive.getFillHatch();
+
+ // create hatch polygon in range size and discrete coordinates
+ basegfx::B2DRange aHatchRange(rFillHatchPrimitive.getOutputRange());
+ aHatchRange.transform(maCurrentTransformation);
+ const basegfx::B2DPolygon aHatchPolygon(basegfx::utils::createPolygonFromRect(aHatchRange));
+
+ if (rFillHatchAttributes.isFillBackground())
{
- // invert primitive (currently only used for HighContrast fallback for selection in SW and SC).
- // (Not true, also used at least for the drawing of dragged column and row boundaries in SC.)
- // Set OutDev to XOR and switch AA off (XOR does not work with AA)
- mpOutputDevice->Push();
- mpOutputDevice->SetRasterOp( RasterOp::Xor );
- const AntialiasingFlags nAntiAliasing(mpOutputDevice->GetAntialiasing());
- mpOutputDevice->SetAntialiasing(nAntiAliasing & ~AntialiasingFlags::EnableB2dDraw);
-
- // process content recursively
- process(rCandidate);
+ // #i111846# background fill is active; draw fill polygon
+ const basegfx::BColor aPolygonColor(
+ maBColorModifierStack.getModifiedColor(rFillHatchPrimitive.getBColor()));
- // restore OutDev
- mpOutputDevice->Pop();
- mpOutputDevice->SetAntialiasing(nAntiAliasing);
+ mpOutputDevice->SetFillColor(Color(aPolygonColor));
+ mpOutputDevice->SetLineColor();
+ mpOutputDevice->DrawPolygon(aHatchPolygon);
}
- void VclPixelProcessor2D::processMetaFilePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate)
- {
- // #i98289#
- const bool bForceLineSnap(getOptionsDrawinglayer().IsAntiAliasing() && getOptionsDrawinglayer().IsSnapHorVerLinesToDiscrete());
- const AntialiasingFlags nOldAntiAliase(mpOutputDevice->GetAntialiasing());
+ // set hatch line color
+ const basegfx::BColor aHatchColor(
+ maBColorModifierStack.getModifiedColor(rFillHatchPrimitive.getBColor()));
+ mpOutputDevice->SetFillColor();
+ mpOutputDevice->SetLineColor(Color(aHatchColor));
+
+ // get hatch style
+ HatchStyle eHatchStyle(HatchStyle::Single);
- if(bForceLineSnap)
+ switch (rFillHatchAttributes.getStyle())
+ {
+ default: // HatchStyle::Single
{
- mpOutputDevice->SetAntialiasing(nOldAntiAliase | AntialiasingFlags::PixelSnapHairline);
+ break;
}
-
- process(rCandidate);
-
- if(bForceLineSnap)
+ case attribute::HatchStyle::Double:
{
- mpOutputDevice->SetAntialiasing(nOldAntiAliase);
+ eHatchStyle = HatchStyle::Double;
+ break;
}
- }
-
- void VclPixelProcessor2D::processGlowPrimitive2D(const primitive2d::GlowPrimitive2D& rCandidate)
- {
- basegfx::B2DRange aRange(rCandidate.getB2DRange(getViewInformation2D()));
- aRange.transform(maCurrentTransformation);
- aRange.grow(10.0);
- impBufferDevice aBufferDevice(*mpOutputDevice, aRange);
- if (aBufferDevice.isVisible())
+ case attribute::HatchStyle::Triple:
{
- // remember last OutDev and set to content
- OutputDevice* pLastOutputDevice = mpOutputDevice;
- mpOutputDevice = &aBufferDevice.getTransparence();
- // paint content to virtual device
- mpOutputDevice->Erase();
- process(rCandidate);
-
- // obtain result as a bitmap
- auto bitmap = mpOutputDevice->GetBitmapEx(Point(aRange.getMinX(), aRange.getMinY()), Size(aRange.getWidth(), aRange.getHeight()));
- constexpr double nRadius = 5.0;
- bitmap.Scale(Size(aRange.getWidth()-nRadius, aRange.getHeight()-nRadius));
- // use bitmap later as mask
- auto mask = bitmap.GetBitmap();
-
- mpOutputDevice = &aBufferDevice.getContent();
- process(rCandidate);
- bitmap = mpOutputDevice->GetBitmapEx(Point(aRange.getMinX(), aRange.getMinY()), Size(aRange.getWidth(), aRange.getHeight()));
- bitmap.Scale(Size(aRange.getWidth()-nRadius, aRange.getHeight()-nRadius));
-
- // calculate blurry effect
- BitmapFilterStackBlur glowFilter(nRadius);
- BitmapFilter::Filter(bitmap, glowFilter);
- // back to old OutDev
- mpOutputDevice = pLastOutputDevice;
- mpOutputDevice->DrawBitmapEx(Point(aRange.getMinX()-nRadius/2, aRange.getMinY()-nRadius/2), BitmapEx(bitmap.GetBitmap(), mask));
-
- // paint result
- //aBufferDevice.paint();
+ eHatchStyle = HatchStyle::Triple;
+ break;
}
- else
- SAL_WARN("drawinglayer", "Temporary buffered virtual device is not visible");
}
+
+ // create hatch
+ const basegfx::B2DVector aDiscreteDistance(
+ maCurrentTransformation * basegfx::B2DVector(rFillHatchAttributes.getDistance(), 0.0));
+ const sal_uInt32 nDistance(basegfx::fround(aDiscreteDistance.getLength()));
+ const sal_uInt16 nAngle10(
+ static_cast<sal_uInt16>(basegfx::fround(rFillHatchAttributes.getAngle() / F_PI1800)));
+ ::Hatch aVCLHatch(eHatchStyle, Color(rFillHatchAttributes.getColor()), nDistance, nAngle10);
+
+ // draw hatch using VCL
+ mpOutputDevice->DrawHatch(::tools::PolyPolygon(::tools::Polygon(aHatchPolygon)), aVCLHatch);
+ }
+}
+
+void VclPixelProcessor2D::processBackgroundColorPrimitive2D(
+ const primitive2d::BackgroundColorPrimitive2D& rPrimitive)
+{
+ // #i98404# Handle directly, especially when AA is active
+ const AntialiasingFlags nOriginalAA(mpOutputDevice->GetAntialiasing());
+
+ // switch AA off in all cases
+ mpOutputDevice->SetAntialiasing(mpOutputDevice->GetAntialiasing()
+ & ~AntialiasingFlags::EnableB2dDraw);
+
+ // create color for fill
+ const basegfx::BColor aPolygonColor(
+ maBColorModifierStack.getModifiedColor(rPrimitive.getBColor()));
+ Color aFillColor(aPolygonColor);
+ aFillColor.SetTransparency(sal_uInt8((rPrimitive.getTransparency() * 255.0) + 0.5));
+ mpOutputDevice->SetFillColor(aFillColor);
+ mpOutputDevice->SetLineColor();
+
+ // create rectangle for fill
+ const basegfx::B2DRange& aViewport(getViewInformation2D().getDiscreteViewport());
+ const ::tools::Rectangle aRectangle(static_cast<sal_Int32>(floor(aViewport.getMinX())),
+ static_cast<sal_Int32>(floor(aViewport.getMinY())),
+ static_cast<sal_Int32>(ceil(aViewport.getMaxX())),
+ static_cast<sal_Int32>(ceil(aViewport.getMaxY())));
+ mpOutputDevice->DrawRect(aRectangle);
+
+ // restore AA setting
+ mpOutputDevice->SetAntialiasing(nOriginalAA);
+}
+
+void VclPixelProcessor2D::processBorderLinePrimitive2D(
+ const drawinglayer::primitive2d::BorderLinePrimitive2D& rBorder)
+{
+ // Process recursively, but switch off AntiAliasing for
+ // horizontal/vertical lines (*not* diagonal lines).
+ // Checked using AntialiasingFlags::PixelSnapHairline instead,
+ // but with AntiAliasing on the display really is too 'ghosty' when
+ // using fine stroking. Correct, but 'ghosty'.
+
+ // It has shown that there are quite some problems here:
+ // - vcl OutDev renderer methods still use fallbacks to paint
+ // multiple single lines between discrete sizes of < 3.5 what
+ // looks bad and does not match
+ // - mix of filled Polygons and Lines is bad when AA switched off
+ // - Alignment of AA with non-AA may be bad in diverse different
+ // renderers
+ //
+ // Due to these reasons I change the strategy: Always draw AAed, but
+ // allow fallback to test/check and if needed. The normal case
+ // where BorderLines will be system-dependently snapped to have at
+ // least a single discrete width per partial line (there may be up to
+ // three) works well nowadays due to most renderers moving the AA stuff
+ // by 0.5 pixels (discrete units) to match well with the non-AAed parts.
+ //
+ // Env-Switch for steering this, default is off.
+ // Enable by setting at all (and to something)
+ static const char* pSwitchOffAntiAliasingForHorVerBorderlines(
+ getenv("SAL_SWITCH_OFF_ANTIALIASING_FOR_HOR_VER_BORTDERLINES"));
+ static bool bSwitchOffAntiAliasingForHorVerBorderlines(
+ nullptr != pSwitchOffAntiAliasingForHorVerBorderlines);
+
+ if (bSwitchOffAntiAliasingForHorVerBorderlines
+ && rBorder.isHorizontalOrVertical(getViewInformation2D()))
+ {
+ AntialiasingFlags nAntiAliasing = mpOutputDevice->GetAntialiasing();
+ mpOutputDevice->SetAntialiasing(nAntiAliasing & ~AntialiasingFlags::EnableB2dDraw);
+ process(rBorder);
+ mpOutputDevice->SetAntialiasing(nAntiAliasing);
+ }
+ else
+ {
+ process(rBorder);
+ }
+}
+
+void VclPixelProcessor2D::processInvertPrimitive2D(const primitive2d::BasePrimitive2D& rCandidate)
+{
+ // invert primitive (currently only used for HighContrast fallback for selection in SW and SC).
+ // (Not true, also used at least for the drawing of dragged column and row boundaries in SC.)
+ // Set OutDev to XOR and switch AA off (XOR does not work with AA)
+ mpOutputDevice->Push();
+ mpOutputDevice->SetRasterOp(RasterOp::Xor);
+ const AntialiasingFlags nAntiAliasing(mpOutputDevice->GetAntialiasing());
+ mpOutputDevice->SetAntialiasing(nAntiAliasing & ~AntialiasingFlags::EnableB2dDraw);
+
+ // process content recursively
+ process(rCandidate);
+
+ // restore OutDev
+ mpOutputDevice->Pop();
+ mpOutputDevice->SetAntialiasing(nAntiAliasing);
+}
+
+void VclPixelProcessor2D::processMetaFilePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate)
+{
+ // #i98289#
+ const bool bForceLineSnap(getOptionsDrawinglayer().IsAntiAliasing()
+ && getOptionsDrawinglayer().IsSnapHorVerLinesToDiscrete());
+ const AntialiasingFlags nOldAntiAliase(mpOutputDevice->GetAntialiasing());
+
+ if (bForceLineSnap)
+ {
+ mpOutputDevice->SetAntialiasing(nOldAntiAliase | AntialiasingFlags::PixelSnapHairline);
+ }
+
+ process(rCandidate);
+
+ if (bForceLineSnap)
+ {
+ mpOutputDevice->SetAntialiasing(nOldAntiAliase);
+ }
+}
+
+void VclPixelProcessor2D::processGlowPrimitive2D(const primitive2d::GlowPrimitive2D& rCandidate)
+{
+ basegfx::B2DRange aRange(rCandidate.getB2DRange(getViewInformation2D()));
+ aRange.transform(maCurrentTransformation);
+ aRange.grow(10.0);
+ impBufferDevice aBufferDevice(*mpOutputDevice, aRange);
+ if (aBufferDevice.isVisible())
+ {
+ // remember last OutDev and set to content
+ OutputDevice* pLastOutputDevice = mpOutputDevice;
+ mpOutputDevice = &aBufferDevice.getTransparence();
+ // paint content to virtual device
+ mpOutputDevice->Erase();
+ process(rCandidate);
+
+ // obtain result as a bitmap
+ auto bitmap = mpOutputDevice->GetBitmapEx(Point(aRange.getMinX(), aRange.getMinY()),
+ Size(aRange.getWidth(), aRange.getHeight()));
+ constexpr double nRadius = 5.0;
+ bitmap.Scale(Size(aRange.getWidth() - nRadius, aRange.getHeight() - nRadius));
+ // use bitmap later as mask
+ auto mask = bitmap.GetBitmap();
+
+ mpOutputDevice = &aBufferDevice.getContent();
+ process(rCandidate);
+ bitmap = mpOutputDevice->GetBitmapEx(Point(aRange.getMinX(), aRange.getMinY()),
+ Size(aRange.getWidth(), aRange.getHeight()));
+ bitmap.Scale(Size(aRange.getWidth() - nRadius, aRange.getHeight() - nRadius));
+
+ // calculate blurry effect
+ BitmapFilterStackBlur glowFilter(nRadius);
+ BitmapFilter::Filter(bitmap, glowFilter);
+ // back to old OutDev
+ mpOutputDevice = pLastOutputDevice;
+ mpOutputDevice->DrawBitmapEx(
+ Point(aRange.getMinX() - nRadius / 2, aRange.getMinY() - nRadius / 2),
+ BitmapEx(bitmap.GetBitmap(), mask));
+
+ // paint result
+ //aBufferDevice.paint();
+ }
+ else
+ SAL_WARN("drawinglayer", "Temporary buffered virtual device is not visible");
+}
} // end of namespace
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/solenv/clang-format/blacklist b/solenv/clang-format/blacklist
index 298369ee7da6..375ed4dd1647 100644
--- a/solenv/clang-format/blacklist
+++ b/solenv/clang-format/blacklist
@@ -3756,7 +3756,6 @@ drawinglayer/source/processor2d/vclhelperbufferdevice.cxx
drawinglayer/source/processor2d/vclhelperbufferdevice.hxx
drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
drawinglayer/source/processor2d/vclmetafileprocessor2d.hxx
-drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
drawinglayer/source/processor3d/baseprocessor3d.cxx
drawinglayer/source/processor3d/cutfindprocessor3d.cxx
drawinglayer/source/processor3d/defaultprocessor3d.cxx
commit 62adba3bb3f95739a4fe7b3dd6e6c11ef4e5f43c
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
AuthorDate: Wed Apr 29 15:14:54 2020 +0200
Commit: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
CommitDate: Thu Apr 30 08:51:54 2020 +0200
remove vclprocessor2d.cxx from clang-format blacklist
Change-Id: I359dfb0fe6fdf88e9c8141186a770c4cde777161
diff --git a/drawinglayer/source/processor2d/vclprocessor2d.cxx b/drawinglayer/source/processor2d/vclprocessor2d.cxx
index f44c85c54eef..c5460f0433e1 100644
--- a/drawinglayer/source/processor2d/vclprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclprocessor2d.cxx
@@ -72,1373 +72,1434 @@ using namespace com::sun::star;
namespace
{
- sal_uInt32 calculateStepsForSvgGradient(const basegfx::BColor& rColorA, const basegfx::BColor& rColorB, double fDelta, double fDiscreteUnit)
- {
- // use color distance, assume to do every color step
- sal_uInt32 nSteps(basegfx::fround(rColorA.getDistance(rColorB) * 255.0));
+sal_uInt32 calculateStepsForSvgGradient(const basegfx::BColor& rColorA,
+ const basegfx::BColor& rColorB, double fDelta,
+ double fDiscreteUnit)
+{
+ // use color distance, assume to do every color step
+ sal_uInt32 nSteps(basegfx::fround(rColorA.getDistance(rColorB) * 255.0));
- if(nSteps)
- {
- // calc discrete length to change color each discrete unit (pixel)
- const sal_uInt32 nDistSteps(basegfx::fround(fDelta / fDiscreteUnit));
+ if (nSteps)
+ {
+ // calc discrete length to change color each discrete unit (pixel)
+ const sal_uInt32 nDistSteps(basegfx::fround(fDelta / fDiscreteUnit));
- nSteps = std::min(nSteps, nDistSteps);
- }
+ nSteps = std::min(nSteps, nDistSteps);
+ }
- // reduce quality to 3 discrete units or every 3rd color step for rendering
- nSteps /= 2;
+ // reduce quality to 3 discrete units or every 3rd color step for rendering
+ nSteps /= 2;
- // roughly cut when too big or too small (not full quality, reduce complexity)
- nSteps = std::min(nSteps, sal_uInt32(255));
- nSteps = std::max(nSteps, sal_uInt32(1));
+ // roughly cut when too big or too small (not full quality, reduce complexity)
+ nSteps = std::min(nSteps, sal_uInt32(255));
+ nSteps = std::max(nSteps, sal_uInt32(1));
- return nSteps;
- }
+ return nSteps;
+}
}
namespace drawinglayer::processor2d
{
- // rendering support
+// rendering support
+
+// directdraw of text simple portion or decorated portion primitive. When decorated, all the extra
+// information is translated to VCL parameters and set at the font.
+// Acceptance is restricted to no shearing and positive scaling in X and Y (no font mirroring
+// for VCL)
+void VclProcessor2D::RenderTextSimpleOrDecoratedPortionPrimitive2D(
+ const primitive2d::TextSimplePortionPrimitive2D& rTextCandidate)
+{
+ // decompose matrix to have position and size of text
+ basegfx::B2DHomMatrix aLocalTransform(maCurrentTransformation
+ * rTextCandidate.getTextTransform());
+ basegfx::B2DVector aFontScaling, aTranslate;
+ double fRotate, fShearX;
+ aLocalTransform.decompose(aFontScaling, aTranslate, fRotate, fShearX);
+ bool bPrimitiveAccepted(false);
+
+ // tdf#95581: Assume tiny shears are rounding artefacts or whatever and can be ignored,
+ // especially if the effect is less than a pixel.
+ if (std::abs(aFontScaling.getY() * fShearX) < 1)
+ {
+ if (basegfx::fTools::less(aFontScaling.getX(), 0.0)
+ && basegfx::fTools::less(aFontScaling.getY(), 0.0))
+ {
+ // handle special case: If scale is negative in (x,y) (3rd quadrant), it can
+ // be expressed as rotation by PI. Use this since the Font rendering will not
+ // apply the negative scales in any form
+ aFontScaling = basegfx::absolute(aFontScaling);
+ fRotate += F_PI;
+ }
- // directdraw of text simple portion or decorated portion primitive. When decorated, all the extra
- // information is translated to VCL parameters and set at the font.
- // Acceptance is restricted to no shearing and positive scaling in X and Y (no font mirroring
- // for VCL)
- void VclProcessor2D::RenderTextSimpleOrDecoratedPortionPrimitive2D(const primitive2d::TextSimplePortionPrimitive2D& rTextCandidate)
+ if (basegfx::fTools::more(aFontScaling.getX(), 0.0)
+ && basegfx::fTools::more(aFontScaling.getY(), 0.0))
{
- // decompose matrix to have position and size of text
- basegfx::B2DHomMatrix aLocalTransform(maCurrentTransformation * rTextCandidate.getTextTransform());
- basegfx::B2DVector aFontScaling, aTranslate;
- double fRotate, fShearX;
- aLocalTransform.decompose(aFontScaling, aTranslate, fRotate, fShearX);
- bool bPrimitiveAccepted(false);
+ // Get the VCL font (use FontHeight as FontWidth)
+ vcl::Font aFont(primitive2d::getVclFontFromFontAttribute(
+ rTextCandidate.getFontAttribute(), aFontScaling.getX(), aFontScaling.getY(),
+ fRotate, rTextCandidate.getLocale()));
+
+ // set FillColor Attribute
+ const Color aFillColor(rTextCandidate.getTextFillColor());
+ if (aFillColor != COL_TRANSPARENT)
+ {
+ aFont.SetFillColor(aFillColor);
+ aFont.SetTransparent(false);
+ }
+
+ // Don't draw fonts without height
+ if (aFont.GetFontHeight() <= 0)
+ return;
+
+ // handle additional font attributes
+ const primitive2d::TextDecoratedPortionPrimitive2D* pTCPP
+ = dynamic_cast<const primitive2d::TextDecoratedPortionPrimitive2D*>(
+ &rTextCandidate);
- // tdf#95581: Assume tiny shears are rounding artefacts or whatever and can be ignored,
- // especially if the effect is less than a pixel.
- if(std::abs(aFontScaling.getY() * fShearX) < 1)
+ if (pTCPP != nullptr)
{
- if(basegfx::fTools::less(aFontScaling.getX(), 0.0) && basegfx::fTools::less(aFontScaling.getY(), 0.0))
+ // set the color of text decorations
+ const basegfx::BColor aTextlineColor
+ = maBColorModifierStack.getModifiedColor(pTCPP->getTextlineColor());
+ mpOutputDevice->SetTextLineColor(Color(aTextlineColor));
+
+ // set Overline attribute
+ const FontLineStyle eFontOverline(
+ primitive2d::mapTextLineToFontLineStyle(pTCPP->getFontOverline()));
+ if (eFontOverline != LINESTYLE_NONE)
{
- // handle special case: If scale is negative in (x,y) (3rd quadrant), it can
- // be expressed as rotation by PI. Use this since the Font rendering will not
- // apply the negative scales in any form
- aFontScaling = basegfx::absolute(aFontScaling);
- fRotate += F_PI;
+ aFont.SetOverline(eFontOverline);
+ const basegfx::BColor aOverlineColor
+ = maBColorModifierStack.getModifiedColor(pTCPP->getOverlineColor());
+ mpOutputDevice->SetOverlineColor(Color(aOverlineColor));
+ if (pTCPP->getWordLineMode())
+ aFont.SetWordLineMode(true);
}
- if(basegfx::fTools::more(aFontScaling.getX(), 0.0) && basegfx::fTools::more(aFontScaling.getY(), 0.0))
+ // set Underline attribute
+ const FontLineStyle eFontLineStyle(
+ primitive2d::mapTextLineToFontLineStyle(pTCPP->getFontUnderline()));
+ if (eFontLineStyle != LINESTYLE_NONE)
{
- // Get the VCL font (use FontHeight as FontWidth)
- vcl::Font aFont(primitive2d::getVclFontFromFontAttribute(
- rTextCandidate.getFontAttribute(),
- aFontScaling.getX(),
- aFontScaling.getY(),
- fRotate,
- rTextCandidate.getLocale()));
-
- // set FillColor Attribute
- const Color aFillColor( rTextCandidate.getTextFillColor() );
- if( aFillColor != COL_TRANSPARENT )
- {
- aFont.SetFillColor(aFillColor);
- aFont.SetTransparent(false);
- }
-
- // Don't draw fonts without height
- if( aFont.GetFontHeight() <= 0 )
- return;
-
- // handle additional font attributes
- const primitive2d::TextDecoratedPortionPrimitive2D* pTCPP =
- dynamic_cast<const primitive2d::TextDecoratedPortionPrimitive2D*>( &rTextCandidate );
-
- if( pTCPP != nullptr )
- {
-
- // set the color of text decorations
- const basegfx::BColor aTextlineColor = maBColorModifierStack.getModifiedColor(pTCPP->getTextlineColor());
- mpOutputDevice->SetTextLineColor( Color(aTextlineColor) );
-
- // set Overline attribute
- const FontLineStyle eFontOverline(primitive2d::mapTextLineToFontLineStyle( pTCPP->getFontOverline() ));
- if( eFontOverline != LINESTYLE_NONE )
- {
- aFont.SetOverline( eFontOverline );
- const basegfx::BColor aOverlineColor = maBColorModifierStack.getModifiedColor(pTCPP->getOverlineColor());
- mpOutputDevice->SetOverlineColor( Color(aOverlineColor) );
- if( pTCPP->getWordLineMode() )
- aFont.SetWordLineMode( true );
- }
-
- // set Underline attribute
- const FontLineStyle eFontLineStyle(primitive2d::mapTextLineToFontLineStyle( pTCPP->getFontUnderline() ));
- if( eFontLineStyle != LINESTYLE_NONE )
- {
- aFont.SetUnderline( eFontLineStyle );
- if( pTCPP->getWordLineMode() )
- aFont.SetWordLineMode( true );
- }
-
- // set Strikeout attribute
- const FontStrikeout eFontStrikeout(primitive2d::mapTextStrikeoutToFontStrikeout(pTCPP->getTextStrikeout()));
-
- if( eFontStrikeout != STRIKEOUT_NONE )
- aFont.SetStrikeout( eFontStrikeout );
-
-
- // set EmphasisMark attribute
- FontEmphasisMark eFontEmphasisMark = FontEmphasisMark::NONE;
- switch( pTCPP->getTextEmphasisMark() )
- {
- default:
- SAL_WARN("drawinglayer", "Unknown EmphasisMark style " << pTCPP->getTextEmphasisMark() );
- [[fallthrough]];
- case primitive2d::TEXT_FONT_EMPHASIS_MARK_NONE: eFontEmphasisMark = FontEmphasisMark::NONE; break;
- case primitive2d::TEXT_FONT_EMPHASIS_MARK_DOT: eFontEmphasisMark = FontEmphasisMark::Dot; break;
- case primitive2d::TEXT_FONT_EMPHASIS_MARK_CIRCLE: eFontEmphasisMark = FontEmphasisMark::Circle; break;
- case primitive2d::TEXT_FONT_EMPHASIS_MARK_DISC: eFontEmphasisMark = FontEmphasisMark::Disc; break;
- case primitive2d::TEXT_FONT_EMPHASIS_MARK_ACCENT: eFontEmphasisMark = FontEmphasisMark::Accent; break;
- }
+ aFont.SetUnderline(eFontLineStyle);
+ if (pTCPP->getWordLineMode())
+ aFont.SetWordLineMode(true);
+ }
- if( eFontEmphasisMark != FontEmphasisMark::NONE )
- {
- DBG_ASSERT( (pTCPP->getEmphasisMarkAbove() != pTCPP->getEmphasisMarkBelow()),
- "DrawingLayer: Bad EmphasisMark position!" );
- if( pTCPP->getEmphasisMarkAbove() )
- eFontEmphasisMark |= FontEmphasisMark::PosAbove;
- else
- eFontEmphasisMark |= FontEmphasisMark::PosBelow;
- aFont.SetEmphasisMark( eFontEmphasisMark );
- }
+ // set Strikeout attribute
+ const FontStrikeout eFontStrikeout(
+ primitive2d::mapTextStrikeoutToFontStrikeout(pTCPP->getTextStrikeout()));
- // set Relief attribute
- FontRelief eFontRelief = FontRelief::NONE;
- switch( pTCPP->getTextRelief() )
- {
- default:
- SAL_WARN( "drawinglayer", "Unknown Relief style " << pTCPP->getTextRelief() );
- [[fallthrough]];
... etc. - the rest is truncated
More information about the Libreoffice-commits
mailing list