StripPortions: full Primitive usage for EditEngine Paint
There were three methods left that use PaintOrStrip in a mode to directly draw Text: DrawText_ToRectangle, DrawText_ToPosition and DrawText_ToEditView. I adapted all three to use PaintOrStrip in a Primitive creating mode and render using a PrmitiveRenderer. While StripPortions was already using the Primitive creating mode the others needed adaptions ranging from handling clipping over rotation to transformations. I checked these as good as I could, but since errors cannot be excluded, I added an ENV_VAR called DISBALE_EDITENGINE_ON_PRIMITIVES with which that change can be deactivated. Please use this by setting it for the office when bugs pop up whose bibisect point to this change - if it does not happen with that var set, this change is responsible. Offering this comes with a cost: Currently PaintOrStrip *still* offers both modes, but when this change causes no big problems I will be enabled to remove all direct paint and stuff done extra there. This will then allow in the future simpler changes since changes to EditEngine output will no longer have to be done in two scopes. For now this allows all remaining places that paint EditEngine content still directly to continue to work. This can in the future be extended to get the exact same context as seq<Primitives> so offers the path to potential re-use (not only paint, you can process and transform Primitives in many ways). A special case is the SD OutlinerView: It uses a set callback (PaintingFirstLineHdl) to additionally paint a PageNumber and a Graphic in that mode, but I managed to replace/extend that to Primitive usage so this is also prepared for simplifications in the future. It would also be good to change that callback from it's current form then. Change-Id: Idc9233f0ce27c3e4153851f4e45faa24d15af36d Reviewed-on: https://gerrit.libreoffice.org/c/core/+/187628 Tested-by: Jenkins Reviewed-by: Armin Le Grand <Armin.Le.Grand@me.com>
This commit is contained in:
committed by
Armin Le Grand
parent
0ad0fc985c
commit
6c8b802051
@@ -1384,6 +1384,7 @@ void VclMetafileProcessor2D::processTextHierarchyFieldPrimitive2D(
|
||||
// thus do the MetafileAction embedding stuff but just handle recursively.
|
||||
static constexpr OString aCommentStringCommon("FIELD_SEQ_BEGIN"_ostr);
|
||||
OUString aURL;
|
||||
const bool bIsExportTaggedPDF(mpPDFExtOutDevData && mpPDFExtOutDevData->GetIsExportTaggedPDF());
|
||||
|
||||
switch (rFieldPrimitive.getType())
|
||||
{
|
||||
@@ -1406,6 +1407,10 @@ void VclMetafileProcessor2D::processTextHierarchyFieldPrimitive2D(
|
||||
mpMetaFile->AddAction(new MetaCommentAction(
|
||||
aCommentStringCommon, 0, reinterpret_cast<const sal_uInt8*>(aURL.getStr()),
|
||||
2 * aURL.getLength()));
|
||||
|
||||
if (bIsExportTaggedPDF)
|
||||
mpPDFExtOutDevData->WrapBeginStructureElement(vcl::pdf::StructElement::Link,
|
||||
u"Link"_ustr);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -1436,6 +1441,13 @@ void VclMetafileProcessor2D::processTextHierarchyFieldPrimitive2D(
|
||||
aBookmark.aBookmark = aURL;
|
||||
std::vector<vcl::PDFExtOutDevBookmarkEntry>& rBookmarks = mpPDFExtOutDevData->GetBookmarks();
|
||||
rBookmarks.push_back(aBookmark);
|
||||
|
||||
if (bIsExportTaggedPDF)
|
||||
{
|
||||
mpPDFExtOutDevData->SetStructureAttributeNumerical(vcl::PDFWriter::LinkAnnotation,
|
||||
aBookmark.nLinkId);
|
||||
mpPDFExtOutDevData->EndStructureElement();
|
||||
}
|
||||
}
|
||||
|
||||
void VclMetafileProcessor2D::processTextHierarchyLinePrimitive2D(
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <editeng/escapementitem.hxx>
|
||||
#include <drawinglayer/primitive2d/texthierarchyprimitive2d.hxx>
|
||||
#include <editeng/smallcaps.hxx>
|
||||
#include <editeng/outliner.hxx>
|
||||
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
|
||||
#include <drawinglayer/primitive2d/textdecoratedprimitive2d.hxx>
|
||||
#include <drawinglayer/primitive2d/textbreakuphelper.hxx>
|
||||
@@ -648,6 +649,12 @@ void TextHierarchyBreakup::processDrawBulletInfo(const DrawBulletInfo& rDrawBull
|
||||
maTextPortionPrimitives.push_back(pNewPrimitive);
|
||||
}
|
||||
|
||||
void TextHierarchyBreakup::directlyAddB2DPrimitive(
|
||||
const drawinglayer::primitive2d::Primitive2DReference& rSource)
|
||||
{
|
||||
maTextPortionPrimitives.push_back(rSource);
|
||||
}
|
||||
|
||||
TextHierarchyBreakup::TextHierarchyBreakup()
|
||||
: maTextPortionPrimitives()
|
||||
, maLinePrimitives()
|
||||
@@ -685,4 +692,32 @@ TextHierarchyBreakup::getTextPortionPrimitives()
|
||||
return maParagraphPrimitives;
|
||||
}
|
||||
|
||||
sal_Int16 TextHierarchyBreakupOutliner::getOutlineLevelFromParagraph(sal_Int32 nPara) const
|
||||
{
|
||||
sal_Int16 nDepth(mrOutliner.GetDepth(nPara));
|
||||
EBulletInfo eInfo(mrOutliner.GetBulletInfo(nPara));
|
||||
// Pass -1 to signal VclMetafileProcessor2D that there is no active
|
||||
// bullets/numbering in this paragraph (i.e. this is normal text)
|
||||
return eInfo.bVisible ? nDepth : -1;
|
||||
}
|
||||
|
||||
sal_Int32 TextHierarchyBreakupOutliner::getParagraphCount() const
|
||||
{
|
||||
return mrOutliner.GetParagraphCount();
|
||||
}
|
||||
|
||||
TextHierarchyBreakupOutliner::TextHierarchyBreakupOutliner(Outliner& rOutliner)
|
||||
: TextHierarchyBreakup()
|
||||
, mrOutliner(rOutliner)
|
||||
{
|
||||
}
|
||||
|
||||
TextHierarchyBreakupOutliner::TextHierarchyBreakupOutliner(
|
||||
Outliner& rOutliner, const basegfx::B2DHomMatrix& rNewTransformA,
|
||||
const basegfx::B2DHomMatrix& rNewTransformB)
|
||||
: TextHierarchyBreakup(rNewTransformA, rNewTransformB)
|
||||
, mrOutliner(rOutliner)
|
||||
{
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
#include <vcl/window.hxx>
|
||||
#include <editeng/acorrcfg.hxx>
|
||||
#include <editeng/unolingu.hxx>
|
||||
#include <editeng/StripPortionsHelper.hxx>
|
||||
#include <unotools/lingucfg.hxx>
|
||||
|
||||
#include <com/sun/star/frame/XStorable.hpp>
|
||||
@@ -401,9 +402,20 @@ Point EditView::CalculateTextPaintStartPosition() const
|
||||
return getImpEditEngine().CalculateTextPaintStartPosition(getImpl());
|
||||
}
|
||||
|
||||
void EditView::DrawText_ToEditView( TextHierarchyBreakup& rHelper, const tools::Rectangle& rRect, OutputDevice* pTargetDevice )
|
||||
{
|
||||
getImpEditEngine().DrawText_ToEditView(rHelper, &getImpl(), rRect, pTargetDevice);
|
||||
}
|
||||
|
||||
void EditView::DrawText_ToEditView( const tools::Rectangle& rRect, OutputDevice* pTargetDevice )
|
||||
{
|
||||
getImpEditEngine().DrawText_ToEditView(&getImpl(), rRect, pTargetDevice);
|
||||
// use TextHierarchyBreakup to get all text embedded to the
|
||||
// TextHierarchy.*Primitive2D groupings for better processing
|
||||
TextHierarchyBreakup aHelper;
|
||||
|
||||
// hand that Helper over to DrawText_ToEditView at the EditEngine
|
||||
// for usage
|
||||
getImpEditEngine().DrawText_ToEditView(aHelper, &getImpl(), rRect, pTargetDevice);
|
||||
}
|
||||
|
||||
void EditView::setEditEngine(EditEngine& rEditEngine)
|
||||
|
||||
@@ -1003,7 +1003,7 @@ public:
|
||||
void DrawText_ToRectangle( OutputDevice& rOutDev, const tools::Rectangle& rOutRect, const Point& rStartDocPos, bool bHardClip );
|
||||
void UpdateViews( EditView* pCurView = nullptr );
|
||||
Point CalculateTextPaintStartPosition(ImpEditView& rView) const;
|
||||
void DrawText_ToEditView( ImpEditView* pView, const tools::Rectangle& rRect, OutputDevice* pTargetDevice );
|
||||
void DrawText_ToEditView( TextHierarchyBreakup& rHelper, ImpEditView* pView, const tools::Rectangle& rRect, OutputDevice* pTargetDevice );
|
||||
void PaintOrStrip( OutputDevice& rOutDev, tools::Rectangle aClipRect, Point aStartPos, Degree10 nOrientation = 0_deg10, StripPortionsHelper* pStripPortionsHelper = nullptr);
|
||||
|
||||
bool MouseButtonUp( const MouseEvent& rMouseEvent, EditView* pView );
|
||||
|
||||
@@ -88,6 +88,15 @@
|
||||
|
||||
#include <vcl/outdev/ScopedStates.hxx>
|
||||
|
||||
#include <vcl/canvastools.hxx>
|
||||
#include <drawinglayer/processor2d/processor2dtools.hxx>
|
||||
#include <drawinglayer/processor2d/baseprocessor2d.hxx>
|
||||
#include <drawinglayer/primitive2d/groupprimitive2d.hxx>
|
||||
#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
|
||||
#include <basegfx/polygon/b2dpolygontools.hxx>
|
||||
#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
|
||||
#include <basegfx/matrix/b2dhommatrixtools.hxx>
|
||||
|
||||
#include <unicode/uchar.h>
|
||||
|
||||
using namespace ::com::sun::star;
|
||||
@@ -3354,18 +3363,61 @@ Point ImpEditEngine::MoveToNextLine(
|
||||
|
||||
void ImpEditEngine::DrawText_ToPosition( OutputDevice& rOutDev, const Point& rStartPos, Degree10 nOrientation )
|
||||
{
|
||||
if( rOutDev.GetConnectMetaFile() )
|
||||
rOutDev.Push();
|
||||
|
||||
// Create with 2 points, as with positive points it will end up with
|
||||
// LONGMAX as Size, Bottom and Right in the range > LONGMAX.
|
||||
tools::Rectangle aBigRect( -0x3FFFFFFF, -0x3FFFFFFF, 0x3FFFFFFF, 0x3FFFFFFF );
|
||||
if( rOutDev.GetConnectMetaFile() )
|
||||
rOutDev.Push();
|
||||
Point aStartPos( rStartPos );
|
||||
|
||||
if ( IsEffectivelyVertical() )
|
||||
{
|
||||
aStartPos.AdjustX(GetPaperSize().Width() );
|
||||
rStartPos.RotateAround(aStartPos, nOrientation);
|
||||
}
|
||||
PaintOrStrip(rOutDev, aBigRect, aStartPos, nOrientation);
|
||||
|
||||
static bool bUsePrimitives(nullptr == std::getenv("DISBALE_EDITENGINE_ON_PRIMITIVES"));
|
||||
|
||||
if (bUsePrimitives)
|
||||
{
|
||||
// extract Primitives.
|
||||
// Do not use Orientation, that will be added below as transformation
|
||||
TextHierarchyBreakup aHelper;
|
||||
PaintOrStrip(rOutDev, aBigRect, aStartPos, 0_deg10, &aHelper);
|
||||
|
||||
if (aHelper.getTextPortionPrimitives().empty())
|
||||
// no Primitives, done
|
||||
return;
|
||||
|
||||
// create ViewInformation2D based on target OutputDevice
|
||||
drawinglayer::geometry::ViewInformation2D aViewInformation2D;
|
||||
aViewInformation2D.setViewTransformation(rOutDev.GetViewTransformation());
|
||||
|
||||
// get content
|
||||
drawinglayer::primitive2d::Primitive2DContainer aContent(aHelper.getTextPortionPrimitives());
|
||||
|
||||
if (0_deg10 != nOrientation)
|
||||
{
|
||||
// if we have an Orientation, add rotation. Note that input value is
|
||||
// 10th degree and wrong oriented for a right-hand coordinate system (sigh)
|
||||
const double fAngle(-toRadians(nOrientation));
|
||||
aContent = drawinglayer::primitive2d::Primitive2DContainer{
|
||||
new drawinglayer::primitive2d::TransformPrimitive2D(
|
||||
basegfx::utils::createRotateAroundPoint(aStartPos.X(), aStartPos.Y(), fAngle),
|
||||
std::move(aContent))};
|
||||
}
|
||||
|
||||
// create PrimitiveProcessor and render to target
|
||||
std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> xProcessor(
|
||||
drawinglayer::processor2d::createProcessor2DFromOutputDevice(rOutDev, aViewInformation2D));
|
||||
xProcessor->process(aContent);
|
||||
}
|
||||
else
|
||||
{
|
||||
PaintOrStrip(rOutDev, aBigRect, aStartPos, nOrientation);
|
||||
}
|
||||
|
||||
if (rOutDev.GetConnectMetaFile())
|
||||
rOutDev.Pop();
|
||||
}
|
||||
@@ -3394,48 +3446,92 @@ void ImpEditEngine::DrawText_ToRectangle( OutputDevice& rOutDev, const tools::Re
|
||||
aStartPos.setY( aOutRect.Top() - rStartDocPos.X() );
|
||||
}
|
||||
|
||||
bool bClipRegion = rOutDev.IsClipRegion();
|
||||
bool bMetafile = rOutDev.GetConnectMetaFile();
|
||||
vcl::Region aOldRegion = rOutDev.GetClipRegion();
|
||||
static bool bUsePrimitives(nullptr == std::getenv("DISBALE_EDITENGINE_ON_PRIMITIVES"));
|
||||
|
||||
// If one existed => intersection!
|
||||
// Use Push/pop for creating the Meta file
|
||||
if ( bMetafile )
|
||||
rOutDev.Push();
|
||||
|
||||
// Always use the Intersect method, it is a must for Metafile!
|
||||
if ( bHardClip )
|
||||
if (bUsePrimitives)
|
||||
{
|
||||
// Clip only if necessary...
|
||||
if (!IsFormatted())
|
||||
FormatDoc();
|
||||
tools::Long nTextWidth = !IsEffectivelyVertical() ? CalcTextWidth(true) : GetTextHeight();
|
||||
if ( rStartDocPos.X() || rStartDocPos.Y() ||
|
||||
( rOutRect.GetHeight() < static_cast<tools::Long>(GetTextHeight()) ) ||
|
||||
( rOutRect.GetWidth() < nTextWidth ) )
|
||||
// extract Primitives
|
||||
TextHierarchyBreakup aHelper;
|
||||
PaintOrStrip(rOutDev, aOutRect, aStartPos, 0_deg10, &aHelper);
|
||||
|
||||
if (aHelper.getTextPortionPrimitives().empty())
|
||||
// no Primitives, done
|
||||
return;
|
||||
|
||||
// create ViewInformation2D based on target OutputDevice
|
||||
drawinglayer::geometry::ViewInformation2D aViewInformation2D;
|
||||
aViewInformation2D.setViewTransformation(rOutDev.GetViewTransformation());
|
||||
const basegfx::B2DRange aClipRange(vcl::unotools::b2DRectangleFromRectangle(aOutRect));
|
||||
aViewInformation2D.setViewport(aClipRange);
|
||||
|
||||
// get content and it's range
|
||||
drawinglayer::primitive2d::Primitive2DContainer aContent(aHelper.getTextPortionPrimitives());
|
||||
const basegfx::B2DRange aContentRange(aContent.getB2DRange(aViewInformation2D));
|
||||
|
||||
if (!aContentRange.overlaps(aClipRange))
|
||||
// no overlap, nothing visible
|
||||
return;
|
||||
|
||||
if (bHardClip && !aClipRange.isInside(aContentRange))
|
||||
{
|
||||
// Some printer drivers cause problems if characters graze the
|
||||
// ClipRegion, therefore rather add a pixel more ...
|
||||
tools::Rectangle aClipRect( aOutRect );
|
||||
if ( rOutDev.GetOutDevType() == OUTDEV_PRINTER )
|
||||
{
|
||||
Size aPixSz( 1, 0 );
|
||||
aPixSz = rOutDev.PixelToLogic( aPixSz );
|
||||
aClipRect.AdjustRight(aPixSz.Width() );
|
||||
aClipRect.AdjustBottom(aPixSz.Width() );
|
||||
}
|
||||
rOutDev.IntersectClipRegion( aClipRect );
|
||||
// not completely inside aClipRange and clipping requested
|
||||
// Embed to MaskPrimitive2D
|
||||
aContent = drawinglayer::primitive2d::Primitive2DContainer{
|
||||
new drawinglayer::primitive2d::MaskPrimitive2D(
|
||||
basegfx::B2DPolyPolygon(basegfx::utils::createPolygonFromRect(aClipRange)),
|
||||
std::move(aContent))};
|
||||
}
|
||||
|
||||
// create PrimitiveProcessor and render to target
|
||||
std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> xProcessor(
|
||||
drawinglayer::processor2d::createProcessor2DFromOutputDevice(rOutDev, aViewInformation2D));
|
||||
xProcessor->process(aContent);
|
||||
}
|
||||
|
||||
PaintOrStrip(rOutDev, aOutRect, aStartPos);
|
||||
|
||||
if ( bMetafile )
|
||||
rOutDev.Pop();
|
||||
else if ( bClipRegion )
|
||||
rOutDev.SetClipRegion( aOldRegion );
|
||||
else
|
||||
rOutDev.SetClipRegion();
|
||||
{
|
||||
bool bClipRegion = rOutDev.IsClipRegion();
|
||||
bool bMetafile = rOutDev.GetConnectMetaFile();
|
||||
vcl::Region aOldRegion = rOutDev.GetClipRegion();
|
||||
|
||||
// If one existed => intersection!
|
||||
// Use Push/pop for creating the Meta file
|
||||
if ( bMetafile )
|
||||
rOutDev.Push();
|
||||
|
||||
// Always use the Intersect method, it is a must for Metafile!
|
||||
if ( bHardClip )
|
||||
{
|
||||
// Clip only if necessary...
|
||||
if (!IsFormatted())
|
||||
FormatDoc();
|
||||
tools::Long nTextWidth = !IsEffectivelyVertical() ? CalcTextWidth(true) : GetTextHeight();
|
||||
if ( rStartDocPos.X() || rStartDocPos.Y() ||
|
||||
( rOutRect.GetHeight() < static_cast<tools::Long>(GetTextHeight()) ) ||
|
||||
( rOutRect.GetWidth() < nTextWidth ) )
|
||||
{
|
||||
// Some printer drivers cause problems if characters graze the
|
||||
// ClipRegion, therefore rather add a pixel more ...
|
||||
tools::Rectangle aClipRect( aOutRect );
|
||||
if ( rOutDev.GetOutDevType() == OUTDEV_PRINTER )
|
||||
{
|
||||
Size aPixSz( 1, 0 );
|
||||
aPixSz = rOutDev.PixelToLogic( aPixSz );
|
||||
aClipRect.AdjustRight(aPixSz.Width() );
|
||||
aClipRect.AdjustBottom(aPixSz.Width() );
|
||||
}
|
||||
rOutDev.IntersectClipRegion( aClipRect );
|
||||
}
|
||||
}
|
||||
|
||||
PaintOrStrip(rOutDev, aOutRect, aStartPos);
|
||||
|
||||
if ( bMetafile )
|
||||
rOutDev.Pop();
|
||||
else if ( bClipRegion )
|
||||
rOutDev.SetClipRegion( aOldRegion );
|
||||
else
|
||||
rOutDev.SetClipRegion();
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: use IterateLineAreas in ImpEditEngine::Paint, to avoid algorithm duplication
|
||||
@@ -3822,7 +3918,7 @@ void ImpEditEngine::PaintOrStrip( OutputDevice& rOutDev, tools::Rectangle aClipR
|
||||
pDXArray = KernArraySpan(aTmpDXArray);
|
||||
|
||||
// add a meta file comment if we record to a metafile
|
||||
if( bMetafileValid )
|
||||
if( !pStripPortionsHelper && bMetafileValid )
|
||||
{
|
||||
const SvxFieldItem* pFieldItem = dynamic_cast<const SvxFieldItem*>(pAttr->GetItem());
|
||||
if( pFieldItem )
|
||||
@@ -4132,7 +4228,7 @@ void ImpEditEngine::PaintOrStrip( OutputDevice& rOutDev, tools::Rectangle aClipR
|
||||
if ( rTextPortion.GetKind() == PortionKind::FIELD )
|
||||
{
|
||||
// add a meta file comment if we record to a metafile
|
||||
if( bMetafileValid )
|
||||
if( !pStripPortionsHelper && bMetafileValid )
|
||||
{
|
||||
const EditCharAttrib* pAttr = rParaPortion.GetNode()->GetCharAttribs().FindFeature(nIndex);
|
||||
assert( pAttr && "Field not found" );
|
||||
@@ -4311,7 +4407,7 @@ Point ImpEditEngine::CalculateTextPaintStartPosition(ImpEditView& rView) const
|
||||
return aStartPos;
|
||||
}
|
||||
|
||||
void ImpEditEngine::DrawText_ToEditView( ImpEditView* pView, const tools::Rectangle& rRect, OutputDevice* pTargetDevice )
|
||||
void ImpEditEngine::DrawText_ToEditView( TextHierarchyBreakup& rHelper, ImpEditView* pView, const tools::Rectangle& rRect, OutputDevice* pTargetDevice )
|
||||
{
|
||||
if ( !IsUpdateLayout() || IsInUndo() )
|
||||
return;
|
||||
@@ -4339,16 +4435,59 @@ void ImpEditEngine::DrawText_ToEditView( ImpEditView* pView, const tools::Rectan
|
||||
aClipRect.SetRight( nMaxX );
|
||||
}
|
||||
|
||||
bool bClipRegion = rTarget.IsClipRegion();
|
||||
vcl::Region aOldRegion = rTarget.GetClipRegion();
|
||||
rTarget.IntersectClipRegion( aClipRect );
|
||||
static bool bUsePrimitives(nullptr == std::getenv("DISBALE_EDITENGINE_ON_PRIMITIVES"));
|
||||
|
||||
PaintOrStrip(rTarget, aClipRect, aStartPos);
|
||||
if (bUsePrimitives)
|
||||
{
|
||||
// extract Primitives
|
||||
PaintOrStrip(rTarget, aClipRect, aStartPos, 0_deg10, &rHelper);
|
||||
|
||||
if ( bClipRegion )
|
||||
rTarget.SetClipRegion( aOldRegion );
|
||||
if (rHelper.getTextPortionPrimitives().empty())
|
||||
// no Primitives, done
|
||||
return;
|
||||
|
||||
// create ViewInformation2D based on target OutputDevice
|
||||
drawinglayer::geometry::ViewInformation2D aViewInformation2D;
|
||||
aViewInformation2D.setViewTransformation(rTarget.GetViewTransformation());
|
||||
const basegfx::B2DRange aClipRange(vcl::unotools::b2DRectangleFromRectangle(aClipRect));
|
||||
aViewInformation2D.setViewport(aClipRange);
|
||||
|
||||
// get content and it's range
|
||||
drawinglayer::primitive2d::Primitive2DContainer aContent(rHelper.getTextPortionPrimitives());
|
||||
const basegfx::B2DRange aContentRange(aContent.getB2DRange(aViewInformation2D));
|
||||
|
||||
if (!aContentRange.overlaps(aClipRange))
|
||||
// no overlap, nothing visible
|
||||
return;
|
||||
|
||||
if (!aClipRange.isInside(aContentRange))
|
||||
{
|
||||
// not completely inside aClipRange, clipping needed.
|
||||
// Embed to MaskPrimitive2D
|
||||
aContent = drawinglayer::primitive2d::Primitive2DContainer{
|
||||
new drawinglayer::primitive2d::MaskPrimitive2D(
|
||||
basegfx::B2DPolyPolygon(basegfx::utils::createPolygonFromRect(aClipRange)),
|
||||
std::move(aContent))};
|
||||
}
|
||||
|
||||
// create PrimitiveProcessor and render to target
|
||||
std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> xProcessor(
|
||||
drawinglayer::processor2d::createProcessor2DFromOutputDevice(rTarget, aViewInformation2D));
|
||||
xProcessor->process(aContent);
|
||||
}
|
||||
else
|
||||
rTarget.SetClipRegion();
|
||||
{
|
||||
bool bClipRegion = rTarget.IsClipRegion();
|
||||
vcl::Region aOldRegion = rTarget.GetClipRegion();
|
||||
rTarget.IntersectClipRegion( aClipRect );
|
||||
|
||||
PaintOrStrip(rTarget, aClipRect, aStartPos);
|
||||
|
||||
if ( bClipRegion )
|
||||
rTarget.SetClipRegion( aOldRegion );
|
||||
else
|
||||
rTarget.SetClipRegion();
|
||||
}
|
||||
|
||||
pView->DrawSelectionXOR(pView->GetEditSelection(), nullptr, &rTarget);
|
||||
}
|
||||
|
||||
@@ -39,11 +39,11 @@ OutlinerEditEng::~OutlinerEditEng()
|
||||
{
|
||||
}
|
||||
|
||||
void OutlinerEditEng::ProcessFirstLineOfParagraph(sal_Int32 nPara, const Point& rStartPos, const Point& rOrigin, Degree10 nOrientation, OutputDevice& rOutDev, StripPortionsHelper* pStripPortionsHelper)//,
|
||||
void OutlinerEditEng::ProcessFirstLineOfParagraph(sal_Int32 nPara, const Point& rStartPos, const Point& rOrigin, Degree10 nOrientation, OutputDevice& rOutDev, StripPortionsHelper* pStripPortionsHelper)
|
||||
{
|
||||
if( GetControlWord() & EEControlBits::OUTLINER )
|
||||
{
|
||||
PaintFirstLineInfo aInfo(nPara, rStartPos, &rOutDev);
|
||||
PaintFirstLineInfo aInfo(nPara, rStartPos, &rOutDev, pStripPortionsHelper);
|
||||
pOwner->maPaintFirstLineHdl.Call( &aInfo );
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <editeng/editeng.hxx>
|
||||
#include <editeng/editview.hxx>
|
||||
#include <editeng/editdata.hxx>
|
||||
#include <editeng/StripPortionsHelper.hxx>
|
||||
|
||||
#include <svl/style.hxx>
|
||||
#include <svl/languageoptions.hxx>
|
||||
@@ -66,7 +67,14 @@ void OutlinerView::DrawText_ToEditView( const tools::Rectangle& rRect, OutputDev
|
||||
if( rOwner.bFirstParaIsEmpty )
|
||||
rOwner.Insert( OUString() );
|
||||
|
||||
pEditView->DrawText_ToEditView( rRect, pTargetDevice );
|
||||
// use TextHierarchyBreakupOutliner to get all text embedded to the
|
||||
// TextHierarchy.*Primitive2D groupings for better processing, plus
|
||||
// the correct paragtaph countings
|
||||
TextHierarchyBreakupOutliner aHelper(rOwner);
|
||||
|
||||
// hand that Helper over to DrawText_ToEditView at the EditEngine
|
||||
// for usage
|
||||
pEditView->DrawText_ToEditView( aHelper, rRect, pTargetDevice );
|
||||
}
|
||||
|
||||
bool OutlinerView::PostKeyEvent( const KeyEvent& rKEvt, vcl::Window const * pFrameWin )
|
||||
|
||||
@@ -38,6 +38,8 @@ namespace com::sun::star::lang
|
||||
struct Locale;
|
||||
}
|
||||
|
||||
class Outliner;
|
||||
|
||||
class EDITENG_DLLPUBLIC DrawPortionInfo
|
||||
{
|
||||
public:
|
||||
@@ -110,6 +112,8 @@ class EDITENG_DLLPUBLIC StripPortionsHelper
|
||||
public:
|
||||
virtual void processDrawPortionInfo(const DrawPortionInfo&) = 0;
|
||||
virtual void processDrawBulletInfo(const DrawBulletInfo&) = 0;
|
||||
virtual void directlyAddB2DPrimitive(const drawinglayer::primitive2d::Primitive2DReference&)
|
||||
= 0;
|
||||
};
|
||||
|
||||
class EDITENG_DLLPUBLIC TextHierarchyBreakup : public StripPortionsHelper
|
||||
@@ -127,8 +131,10 @@ protected:
|
||||
void flushLinePrimitivesToParagraphPrimitives(sal_Int32 nPara);
|
||||
|
||||
public:
|
||||
virtual void processDrawPortionInfo(const DrawPortionInfo& rDrawPortionInfo);
|
||||
virtual void processDrawBulletInfo(const DrawBulletInfo& rDrawBulletInfo);
|
||||
virtual void processDrawPortionInfo(const DrawPortionInfo& rDrawPortionInfo) override;
|
||||
virtual void processDrawBulletInfo(const DrawBulletInfo& rDrawBulletInfo) override;
|
||||
virtual void
|
||||
directlyAddB2DPrimitive(const drawinglayer::primitive2d::Primitive2DReference&) override;
|
||||
|
||||
TextHierarchyBreakup();
|
||||
TextHierarchyBreakup(const basegfx::B2DHomMatrix& rNewTransformA,
|
||||
@@ -137,6 +143,20 @@ public:
|
||||
const drawinglayer::primitive2d::Primitive2DContainer& getTextPortionPrimitives();
|
||||
};
|
||||
|
||||
class EDITENG_DLLPUBLIC TextHierarchyBreakupOutliner : public TextHierarchyBreakup
|
||||
{
|
||||
Outliner& mrOutliner;
|
||||
|
||||
protected:
|
||||
virtual sal_Int16 getOutlineLevelFromParagraph(sal_Int32 nPara) const override;
|
||||
virtual sal_Int32 getParagraphCount() const override;
|
||||
|
||||
public:
|
||||
TextHierarchyBreakupOutliner(Outliner& rOutliner);
|
||||
TextHierarchyBreakupOutliner(Outliner& rOutliner, const basegfx::B2DHomMatrix& rNewTransformA,
|
||||
const basegfx::B2DHomMatrix& rNewTransformB);
|
||||
};
|
||||
|
||||
#endif // INCLUDED_EDITENG_STRIPPORTIONSHELPER_HXX
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
|
||||
@@ -69,6 +69,7 @@ class InputContext;
|
||||
class OutputDevice;
|
||||
enum class TransliterationFlags;
|
||||
enum class PointerStyle;
|
||||
class TextHierarchyBreakup;
|
||||
|
||||
namespace com {
|
||||
namespace sun {
|
||||
@@ -204,6 +205,7 @@ public:
|
||||
|
||||
Point CalculateTextPaintStartPosition() const;
|
||||
void DrawText_ToEditView( const tools::Rectangle& rRect, OutputDevice* pTargetDevice = nullptr );
|
||||
void DrawText_ToEditView( TextHierarchyBreakup& rHelper, const tools::Rectangle& rRect, OutputDevice* pTargetDevice = nullptr );
|
||||
tools::Rectangle GetInvalidateRect() const;
|
||||
SAL_DLLPRIVATE void InvalidateWindow(const tools::Rectangle& rClipRect);
|
||||
void InvalidateOtherViewWindows( const tools::Rectangle& rInvRect );
|
||||
|
||||
@@ -407,9 +407,10 @@ struct EDITENG_DLLPUBLIC PaintFirstLineInfo
|
||||
sal_Int32 mnPara;
|
||||
const Point& mrStartPos;
|
||||
VclPtr<OutputDevice> mpOutDev;
|
||||
StripPortionsHelper* mpStripPortionsHelper;
|
||||
|
||||
PaintFirstLineInfo( sal_Int32 nPara, const Point& rStartPos, OutputDevice* pOutDev )
|
||||
: mnPara( nPara ), mrStartPos( rStartPos ), mpOutDev( pOutDev )
|
||||
PaintFirstLineInfo( sal_Int32 nPara, const Point& rStartPos, OutputDevice* pOutDev, StripPortionsHelper* pStripPortionsHelper )
|
||||
: mnPara( nPara ), mrStartPos( rStartPos ), mpOutDev( pOutDev ), mpStripPortionsHelper( pStripPortionsHelper )
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
+2
-17
@@ -52,21 +52,6 @@ public:
|
||||
virtual std::optional<bool> GetCompatFlag(SdrCompatibilityFlag eFlag) const override;
|
||||
};
|
||||
|
||||
class TextHierarchyBreakupOutliner : public TextHierarchyBreakup
|
||||
{
|
||||
SdrOutliner& mrOutliner;
|
||||
|
||||
protected:
|
||||
virtual sal_Int16 getOutlineLevelFromParagraph(sal_Int32 nPara) const;
|
||||
virtual sal_Int32 getParagraphCount() const;
|
||||
|
||||
public:
|
||||
TextHierarchyBreakupOutliner(
|
||||
SdrOutliner& rOutliner,
|
||||
const basegfx::B2DHomMatrix& rNewTransformA,
|
||||
const basegfx::B2DHomMatrix& rNewTransformB);
|
||||
};
|
||||
|
||||
class TextHierarchyBreakupBlockText : public TextHierarchyBreakupOutliner
|
||||
{
|
||||
// ClipRange for BlockText decomposition; only text portions completely
|
||||
@@ -75,7 +60,7 @@ class TextHierarchyBreakupBlockText : public TextHierarchyBreakupOutliner
|
||||
const basegfx::B2DRange& mrClipRange;
|
||||
|
||||
public:
|
||||
virtual void processDrawPortionInfo(const DrawPortionInfo& rDrawPortionInfo);
|
||||
virtual void processDrawPortionInfo(const DrawPortionInfo& rDrawPortionInfo) override;
|
||||
|
||||
TextHierarchyBreakupBlockText(
|
||||
SdrOutliner& rOutliner,
|
||||
@@ -90,7 +75,7 @@ class TextHierarchyBreakupContourText : public TextHierarchyBreakupOutliner
|
||||
basegfx::B2DVector maScale;
|
||||
|
||||
public:
|
||||
virtual void processDrawPortionInfo(const DrawPortionInfo& rDrawPortionInfo);
|
||||
virtual void processDrawPortionInfo(const DrawPortionInfo& rDrawPortionInfo) override;
|
||||
|
||||
TextHierarchyBreakupContourText(
|
||||
SdrOutliner& rOutliner,
|
||||
|
||||
@@ -44,6 +44,13 @@
|
||||
|
||||
#include <com/sun/star/frame/XFrame.hpp>
|
||||
|
||||
#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
|
||||
#include <basegfx/matrix/b2dhommatrixtools.hxx>
|
||||
#include <drawinglayer/attribute/fontattribute.hxx>
|
||||
#include <drawinglayer/primitive2d/textlayoutdevice.hxx>
|
||||
#include <drawinglayer/primitive2d/textprimitive2d.hxx>
|
||||
#include <vcl/metric.hxx>
|
||||
|
||||
#include <DrawDocShell.hxx>
|
||||
#include <drawdoc.hxx>
|
||||
#include <Window.hxx>
|
||||
@@ -1576,8 +1583,23 @@ IMPL_LINK(OutlineView, PaintingFirstLineHdl, PaintFirstLineInfo*, pInfo, void)
|
||||
Point aImagePos( pInfo->mrStartPos );
|
||||
aImagePos.AdjustX(aOutSize.Width() - aImageSize.Width() - aOffset.Width() ) ;
|
||||
aImagePos.AdjustY((aOutSize.Height() - aImageSize.Height()) / 2 );
|
||||
static bool bUsePrimitives(nullptr == std::getenv("DISBALE_EDITENGINE_ON_PRIMITIVES"));
|
||||
|
||||
pInfo->mpOutDev->DrawImage( aImagePos, aImageSize, maSlideImage );
|
||||
if (bUsePrimitives && pInfo->mpStripPortionsHelper)
|
||||
{
|
||||
// create BitmapPrimitive2D and add directly
|
||||
const drawinglayer::primitive2d::Primitive2DReference xBitmap(
|
||||
new drawinglayer::primitive2d::BitmapPrimitive2D(
|
||||
maSlideImage.GetBitmapEx(),
|
||||
basegfx::utils::createScaleTranslateB2DHomMatrix(
|
||||
aImageSize.Width(), aImageSize.Height(),
|
||||
aImagePos.X(), aImagePos.Y())));
|
||||
pInfo->mpStripPortionsHelper->directlyAddB2DPrimitive(xBitmap);
|
||||
}
|
||||
else
|
||||
{
|
||||
pInfo->mpOutDev->DrawImage( aImagePos, aImageSize, maSlideImage );
|
||||
}
|
||||
|
||||
const bool bVertical = mrOutliner.IsVertical();
|
||||
const bool bRightToLeftPara = rEditEngine.IsRightToLeft( pInfo->mnPara );
|
||||
@@ -1612,7 +1634,38 @@ IMPL_LINK(OutlineView, PaintingFirstLineHdl, PaintFirstLineInfo*, pInfo, void)
|
||||
aTextPos.AdjustY( -(aTextSz.Width()) );
|
||||
aTextPos.AdjustX(nBulletHeight / 2 );
|
||||
}
|
||||
pInfo->mpOutDev->DrawText( aTextPos, aPageText );
|
||||
|
||||
if (bUsePrimitives && pInfo->mpStripPortionsHelper)
|
||||
{
|
||||
// create TextSimplePortionPrimitive2D and add directly
|
||||
basegfx::B2DVector aFontSize;
|
||||
const vcl::Font& rFont(pInfo->mpOutDev->GetFont());
|
||||
drawinglayer::attribute::FontAttribute aFontAttr(
|
||||
drawinglayer::primitive2d::getFontAttributeFromVclFont(aFontSize, rFont, false, false));
|
||||
const FontMetric aFontMetric(pInfo->mpOutDev->GetFontMetric(rFont));
|
||||
const double fTextOffsetY(aFontMetric.GetAscent());
|
||||
const basegfx::B2DHomMatrix aTextTransform(
|
||||
basegfx::utils::createScaleTranslateB2DHomMatrix(
|
||||
aFontSize.getX(), aFontSize.getY(),
|
||||
aTextPos.X(), aTextPos.Y() + fTextOffsetY));
|
||||
|
||||
const drawinglayer::primitive2d::Primitive2DReference xText(
|
||||
new drawinglayer::primitive2d::TextSimplePortionPrimitive2D(
|
||||
aTextTransform,
|
||||
aPageText,
|
||||
0,
|
||||
aPageText.getLength(),
|
||||
std::vector<double>(),
|
||||
{},
|
||||
std::move(aFontAttr),
|
||||
css::lang::Locale(),
|
||||
pInfo->mpOutDev->GetTextColor().getBColor()));
|
||||
pInfo->mpStripPortionsHelper->directlyAddB2DPrimitive(xText);
|
||||
}
|
||||
else
|
||||
{
|
||||
pInfo->mpOutDev->DrawText( aTextPos, aPageText );
|
||||
}
|
||||
}
|
||||
|
||||
void OutlineView::UpdateParagraph( sal_Int32 nPara )
|
||||
|
||||
@@ -154,17 +154,22 @@ namespace
|
||||
::std::vector< impPathTextPortion > maPathTextPortions;
|
||||
|
||||
public:
|
||||
virtual void processDrawPortionInfo(const DrawPortionInfo& rDrawPortionInfo)
|
||||
virtual void processDrawPortionInfo(const DrawPortionInfo& rDrawPortionInfo) override
|
||||
{
|
||||
// extract and add data for TextOnPath further processing
|
||||
maPathTextPortions.emplace_back(rDrawPortionInfo);
|
||||
}
|
||||
|
||||
virtual void processDrawBulletInfo(const DrawBulletInfo&)
|
||||
virtual void processDrawBulletInfo(const DrawBulletInfo&) override
|
||||
{
|
||||
// nothing to do here, bullets are for now ignored for TextOnLine
|
||||
}
|
||||
|
||||
virtual void directlyAddB2DPrimitive(const drawinglayer::primitive2d::Primitive2DReference&) override
|
||||
{
|
||||
// nothing to do here, no support for directly adding Primitives
|
||||
}
|
||||
|
||||
const ::std::vector< impPathTextPortion >& sortAndGetPathTextPortions()
|
||||
{
|
||||
if(!maPathTextPortions.empty())
|
||||
|
||||
@@ -122,31 +122,6 @@ std::optional<bool> SdrOutliner::GetCompatFlag(SdrCompatibilityFlag eFlag) const
|
||||
return {};
|
||||
}
|
||||
|
||||
sal_Int16 TextHierarchyBreakupOutliner::getOutlineLevelFromParagraph(sal_Int32 nPara) const
|
||||
{
|
||||
sal_Int16 nDepth(mrOutliner.GetDepth(nPara));
|
||||
EBulletInfo eInfo(mrOutliner.GetBulletInfo(nPara));
|
||||
// Pass -1 to signal VclMetafileProcessor2D that there is no active
|
||||
// bullets/numbering in this paragraph (i.e. this is normal text)
|
||||
return eInfo.bVisible ? nDepth : -1;
|
||||
}
|
||||
|
||||
sal_Int32 TextHierarchyBreakupOutliner::getParagraphCount() const
|
||||
{
|
||||
return mrOutliner.GetParagraphCount();
|
||||
}
|
||||
|
||||
TextHierarchyBreakupOutliner::TextHierarchyBreakupOutliner(
|
||||
SdrOutliner& rOutliner,
|
||||
const basegfx::B2DHomMatrix& rNewTransformA,
|
||||
const basegfx::B2DHomMatrix& rNewTransformB)
|
||||
: TextHierarchyBreakup(
|
||||
rNewTransformA,
|
||||
rNewTransformB)
|
||||
, mrOutliner(rOutliner)
|
||||
{
|
||||
}
|
||||
|
||||
void TextHierarchyBreakupBlockText::processDrawPortionInfo(const DrawPortionInfo& rDrawPortionInfo)
|
||||
{
|
||||
// Is clipping wanted? This is text clipping; only accept a portion
|
||||
|
||||
Reference in New Issue
Block a user