From 13b4c191cb251e9218bb9c99140cff7c52fd04db Mon Sep 17 00:00:00 2001 From: Mark Hung Date: Sun, 4 Nov 2018 00:45:20 +0800 Subject: [PATCH] tdf#37636 Render textlines with colors. Create a new helepr class, TextLinesHelper, to handle textline colors and overall size. Change-Id: I8635199819443429f7be1754a298e9a21ef17f8c Reviewed-on: https://gerrit.libreoffice.org/62832 Tested-by: Jenkins Reviewed-by: Mark Hung --- cppcanvas/Library_cppcanvas.mk | 1 + cppcanvas/source/mtfrenderer/textaction.cxx | 56 +++----- .../source/mtfrenderer/textlineshelper.cxx | 127 ++++++++++++++++++ .../source/mtfrenderer/textlineshelper.hxx | 87 ++++++++++++ 4 files changed, 235 insertions(+), 36 deletions(-) create mode 100644 cppcanvas/source/mtfrenderer/textlineshelper.cxx create mode 100644 cppcanvas/source/mtfrenderer/textlineshelper.hxx diff --git a/cppcanvas/Library_cppcanvas.mk b/cppcanvas/Library_cppcanvas.mk index 4033442f0a11..8a374b58dcee 100644 --- a/cppcanvas/Library_cppcanvas.mk +++ b/cppcanvas/Library_cppcanvas.mk @@ -65,6 +65,7 @@ $(eval $(call gb_Library_add_exception_objects,cppcanvas,\ cppcanvas/source/mtfrenderer/polypolyaction \ cppcanvas/source/mtfrenderer/emfpstringformat \ cppcanvas/source/mtfrenderer/textaction \ + cppcanvas/source/mtfrenderer/textlineshelper \ cppcanvas/source/mtfrenderer/transparencygroupaction \ cppcanvas/source/tools/canvasgraphichelper \ cppcanvas/source/tools/tools \ diff --git a/cppcanvas/source/mtfrenderer/textaction.cxx b/cppcanvas/source/mtfrenderer/textaction.cxx index b43f691e931b..422a92279659 100644 --- a/cppcanvas/source/mtfrenderer/textaction.cxx +++ b/cppcanvas/source/mtfrenderer/textaction.cxx @@ -43,6 +43,7 @@ #include #include "textaction.hxx" +#include "textlineshelper.hxx" #include #include "mtftools.hxx" @@ -1261,8 +1262,7 @@ namespace cppcanvas const CanvasSharedPtr mpCanvas; rendering::RenderState maState; const tools::TextLineInfo maTextLineInfo; - ::basegfx::B2DSize maLinesOverallSize; - uno::Reference< rendering::XPolyPolygon2D > mxTextLines; + TextLinesHelper maTextLinesHelper; const ::basegfx::B2DSize maReliefOffset; const ::Color maReliefColor; const ::basegfx::B2DSize maShadowOffset; @@ -1288,8 +1288,7 @@ namespace cppcanvas mpCanvas( rCanvas ), maState(), maTextLineInfo( tools::createTextLineInfo( rVDev, rState ) ), - maLinesOverallSize(), - mxTextLines(), + maTextLinesHelper(mpCanvas, rState), maReliefOffset( rReliefOffset ), maReliefColor( rReliefColor ), maShadowOffset( rShadowOffset ), @@ -1298,11 +1297,7 @@ namespace cppcanvas { initLayoutWidth(mnLayoutWidth, rOffsets); - initEffectLinePolyPolygon( maLinesOverallSize, - mxTextLines, - rCanvas, - mnLayoutWidth, - maTextLineInfo ); + maTextLinesHelper.init(mnLayoutWidth, maTextLineInfo); initArrayAction( maState, mxTextLayout, @@ -1333,8 +1328,7 @@ namespace cppcanvas mpCanvas( rCanvas ), maState(), maTextLineInfo( tools::createTextLineInfo( rVDev, rState ) ), - maLinesOverallSize(), - mxTextLines(), + maTextLinesHelper(mpCanvas, rState), maReliefOffset( rReliefOffset ), maReliefColor( rReliefColor ), maShadowOffset( rShadowOffset ), @@ -1343,11 +1337,7 @@ namespace cppcanvas { initLayoutWidth(mnLayoutWidth, rOffsets); - initEffectLinePolyPolygon( maLinesOverallSize, - mxTextLines, - rCanvas, - mnLayoutWidth, - maTextLineInfo ); + maTextLinesHelper.init(mnLayoutWidth, maTextLineInfo); initArrayAction( maState, mxTextLayout, @@ -1369,14 +1359,12 @@ namespace cppcanvas return ::basegfx::unotools::xPolyPolygonFromB2DPolygon(rCanvas->getDevice(), aTextBoundsPoly); } - bool EffectTextArrayAction::operator()( const rendering::RenderState& rRenderState, const ::Color& rTextFillColor, bool /*bNormalText*/ ) const + bool EffectTextArrayAction::operator()( const rendering::RenderState& rRenderState, const ::Color& rTextFillColor, bool bNormalText) const { const rendering::ViewState& rViewState( mpCanvas->getViewState() ); const uno::Reference< rendering::XCanvas >& rCanvas( mpCanvas->getUNOCanvas() ); - rCanvas->fillPolyPolygon( mxTextLines, - rViewState, - rRenderState ); + maTextLinesHelper.render(rRenderState, bNormalText); //rhbz#1589029 non-transparent text fill background support if (rTextFillColor != COL_AUTO) @@ -1419,21 +1407,19 @@ namespace cppcanvas public: EffectTextArrayRenderHelper( const uno::Reference< rendering::XCanvas >& rCanvas, const uno::Reference< rendering::XTextLayout >& rTextLayout, - const uno::Reference< rendering::XPolyPolygon2D >& rLinePolygon, + const TextLinesHelper& rTextLinesHelper, const rendering::ViewState& rViewState ) : mrCanvas( rCanvas ), mrTextLayout( rTextLayout ), - mrLinePolygon( rLinePolygon ), + mrTextLinesHelper( rTextLinesHelper ), mrViewState( rViewState ) { } // TextRenderer interface - virtual bool operator()( const rendering::RenderState& rRenderState, const ::Color& rTextFillColor,bool /*bNormalText*/ ) const override + virtual bool operator()( const rendering::RenderState& rRenderState, const ::Color& rTextFillColor,bool bNormalText) const override { - mrCanvas->fillPolyPolygon( mrLinePolygon, - mrViewState, - rRenderState ); + mrTextLinesHelper.render(rRenderState, bNormalText); //rhbz#1589029 non-transparent text fill background support if (rTextFillColor != COL_AUTO) @@ -1465,7 +1451,7 @@ namespace cppcanvas const uno::Reference< rendering::XCanvas >& mrCanvas; const uno::Reference< rendering::XTextLayout >& mrTextLayout; - const uno::Reference< rendering::XPolyPolygon2D >& mrLinePolygon; + const TextLinesHelper& mrTextLinesHelper; const rendering::ViewState& mrViewState; }; @@ -1500,12 +1486,8 @@ namespace cppcanvas uno::Reference< rendering::XCanvas > xCanvas( mpCanvas->getUNOCanvas() ); const rendering::ViewState& rViewState( mpCanvas->getViewState() ); - uno::Reference< rendering::XPolyPolygon2D > xTextLines( - ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon( - xCanvas->getDevice(), - tools::createTextLinesPolyPolygon( - 0.0, nMaxPos - nMinPos, - maTextLineInfo ) ) ); + TextLinesHelper aHelper = maTextLinesHelper; + aHelper.init(nMaxPos - nMinPos, maTextLineInfo); // render everything @@ -1514,7 +1496,7 @@ namespace cppcanvas return renderEffectText( EffectTextArrayRenderHelper( xCanvas, xTextLayout, - xTextLines, + aHelper, rViewState ), aLocalState, xCanvas, @@ -1530,11 +1512,13 @@ namespace cppcanvas rendering::RenderState aLocalState( maState ); ::canvas::tools::prependToRenderState(aLocalState, rTransformation); + ::basegfx::B2DSize aSize = maTextLinesHelper.getOverallSize(); + return calcEffectTextBounds( ::basegfx::unotools::b2DRectangleFromRealRectangle2D( mxTextLayout->queryTextBounds() ), ::basegfx::B2DRange( 0,0, - maLinesOverallSize.getX(), - maLinesOverallSize.getY() ), + aSize.getX(), + aSize.getY() ), maReliefOffset, maShadowOffset, aLocalState, diff --git a/cppcanvas/source/mtfrenderer/textlineshelper.cxx b/cppcanvas/source/mtfrenderer/textlineshelper.cxx new file mode 100644 index 000000000000..db88e5cb5ee7 --- /dev/null +++ b/cppcanvas/source/mtfrenderer/textlineshelper.cxx @@ -0,0 +1,127 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include +#include +#include "textlineshelper.hxx" +#include "mtftools.hxx" + +using namespace ::com::sun::star; + +namespace +{ +void initLineStyleWaveline(sal_uInt32 nLineStyle, bool& bIsWaveline, bool& bIsBold) +{ + bIsWaveline = nLineStyle == LINESTYLE_DOUBLEWAVE || nLineStyle == LINESTYLE_SMALLWAVE + || nLineStyle == LINESTYLE_BOLDWAVE || nLineStyle == LINESTYLE_WAVE; + bIsBold = nLineStyle == LINESTYLE_BOLDWAVE; +} +} + +namespace cppcanvas +{ +namespace internal +{ +TextLinesHelper::TextLinesHelper(const CanvasSharedPtr& rCanvas, const OutDevState& rState) + : mpCanvas(rCanvas) + , mbIsOverlineColorSet(rState.isTextOverlineColorSet) + , maOverlineColor(rState.textOverlineColor) + , mbIsUnderlineColorSet(rState.isTextLineColorSet) + , maUnderlineColor(rState.textLineColor) + , mbOverlineWaveline(false) + , mbUnderlineWaveline(false) + , mbOverlineWavelineBold(false) + , mbUnderlineWavelineBold(false) +{ +} + +void TextLinesHelper::init(double nLineWidth, const tools::TextLineInfo& rLineInfo) +{ + ::basegfx::B2DRange aRange; // default is empty. + ::basegfx::B2DPolyPolygon aOverline, aUnderline, aStrikeout; + tools::createTextLinesPolyPolygon(0.0, nLineWidth, rLineInfo, aOverline, aUnderline, + aStrikeout); + + mxOverline.clear(); + mxUnderline.clear(); + mxStrikeout.clear(); + + uno::Reference xDevice = mpCanvas->getUNOCanvas()->getDevice(); + + if (aOverline.count()) + { + aRange.expand(::basegfx::utils::getRange(aOverline)); + mxOverline = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(xDevice, aOverline); + } + + if (aUnderline.count()) + { + aRange.expand(::basegfx::utils::getRange(aUnderline)); + mxUnderline = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(xDevice, aUnderline); + } + + if (aStrikeout.count()) + { + aRange.expand(::basegfx::utils::getRange(aStrikeout)); + mxStrikeout = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(xDevice, aStrikeout); + } + + maOverallSize = aRange.getRange(); + + initLineStyleWaveline(rLineInfo.mnOverlineStyle, mbOverlineWaveline, mbOverlineWavelineBold); + + initLineStyleWaveline(rLineInfo.mnUnderlineStyle, mbUnderlineWaveline, mbUnderlineWavelineBold); +} + +void TextLinesHelper::render(const rendering::RenderState& rRenderState, bool bNormalText) const +{ + const rendering::ViewState& rViewState(mpCanvas->getViewState()); + const uno::Reference& xCanvas(mpCanvas->getUNOCanvas()); + rendering::StrokeAttributes aStrokeAttributes; + aStrokeAttributes.JoinType = rendering::PathJoinType::ROUND; + + if (mxOverline.is()) + { + rendering::RenderState aLocalState(rRenderState); + if (bNormalText && mbIsOverlineColorSet) + aLocalState.DeviceColor = maOverlineColor; + + if (mbOverlineWaveline) + { + aStrokeAttributes.StrokeWidth = mbOverlineWavelineBold ? 2.0 : 1.0; + xCanvas->strokePolyPolygon(mxOverline, rViewState, aLocalState, aStrokeAttributes); + } + else + xCanvas->fillPolyPolygon(mxOverline, rViewState, aLocalState); + } + + if (mxUnderline.is()) + { + rendering::RenderState aLocalState(rRenderState); + if (bNormalText && mbIsUnderlineColorSet) + aLocalState.DeviceColor = maUnderlineColor; + if (mbUnderlineWaveline) + { + aStrokeAttributes.StrokeWidth = mbUnderlineWavelineBold ? 2.0 : 1.0; + xCanvas->strokePolyPolygon(mxUnderline, rViewState, aLocalState, aStrokeAttributes); + } + else + xCanvas->fillPolyPolygon(mxUnderline, rViewState, aLocalState); + } + + if (mxStrikeout.is()) + xCanvas->fillPolyPolygon(mxStrikeout, rViewState, rRenderState); +} +} +} +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/cppcanvas/source/mtfrenderer/textlineshelper.hxx b/cppcanvas/source/mtfrenderer/textlineshelper.hxx new file mode 100644 index 000000000000..fb06e345b64b --- /dev/null +++ b/cppcanvas/source/mtfrenderer/textlineshelper.hxx @@ -0,0 +1,87 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#ifndef INCLUDED_CPPCANVAS_SOURCE_MTFRENDERER_TEXTLINESHELPER_HXX +#define INCLUDED_CPPCANVAS_SOURCE_MTFRENDERER_TEXTLINESHELPER_HXX + +#include +#include +#include +#include + +namespace com +{ +namespace sun +{ +namespace star +{ +namespace rendering +{ +class XPolyPolygon2D; +} +} +} +} + +namespace cppcanvas +{ +namespace tools +{ +struct TextLineInfo; +} + +namespace internal +{ +struct OutDevState; + +class TextLinesHelper +{ + const CanvasSharedPtr mpCanvas; + css::uno::Reference mxOverline; + css::uno::Reference mxUnderline; + css::uno::Reference mxStrikeout; + + ::basegfx::B2DSize maOverallSize; + + bool mbIsOverlineColorSet; + const css::uno::Sequence maOverlineColor; + + bool mbIsUnderlineColorSet; + const css::uno::Sequence maUnderlineColor; + + bool mbOverlineWaveline; + bool mbUnderlineWaveline; + + bool mbOverlineWavelineBold; + bool mbUnderlineWavelineBold; + +public: + TextLinesHelper(const CanvasSharedPtr& rCanvas, const OutDevState& rState); + + ::basegfx::B2DSize getOverallSize() const { return maOverallSize; } + + /** Init textlines with specified linewdith and TextLineInfo. + */ + void init(double nLineWidth, const tools::TextLineInfo& rLineInfo); + + /** Fill the textlines with colors. + OutDevState::textUnderlineColor. + + @param rRenderState + Used to invoke XCanvas::fillPolyPolygon. + + @param bNormalText + Use overline color and underline color if the value is true, ignore those + colors otherwise ( typical case is to render the shadow ). + */ + void render(const css::rendering::RenderState& rRenderState, bool bNormalText) const; +}; +} +} +#endif // INCLUDED_CPPCANVAS_SOURCE_MTFRENDERER_TEXTLINESHELPER_HXX +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */