[Libreoffice-commits] core.git: drawinglayer/source
Libreoffice Gerrit user
logerrit at kemper.freedesktop.org
Tue Jul 31 16:19:00 UTC 2018
drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx | 2526 ++++++-------
drawinglayer/source/processor2d/vclmetafileprocessor2d.hxx | 42
2 files changed, 1334 insertions(+), 1234 deletions(-)
New commits:
commit 2a4b054b3685aaeca5bdcb2969bcfc25365421d9
Author: Caolán McNamara <caolanm at redhat.com>
AuthorDate: Tue Jul 31 14:20:52 2018 +0100
Commit: Caolán McNamara <caolanm at redhat.com>
CommitDate: Tue Jul 31 18:18:36 2018 +0200
crashtesting: stack exhaustion exporting moz943243-4.svg to odg
happens on the crashtesting box, but not locally, comparing the stack frames its clear
that the stack used on the crashtester for VclMetafileProcessor2D::processBasePrimitive2D is
over double that used locally...
comparison on
> objdump -S workdir/CxxObject/drawinglayer/source/processor2d/vclmetafileprocessor2d.o |less
gives...
void VclMetafileProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate)
gcc-4.8.2-3.2.mga4 has... sub $0x11e8,%rsp
vs...
gcc-8.1.1-5.fc28.x86_64 has... sub $0x4c0,%rsp
lets split up this method
Change-Id: I73ef1eb0280224988176986918a2d025344197d0
Reviewed-on: https://gerrit.libreoffice.org/58362
Reviewed-by: Caolán McNamara <caolanm at redhat.com>
Tested-by: Caolán McNamara <caolanm at redhat.com>
diff --git a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
index bcd18d2d1f26..a7228338c689 100644
--- a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
@@ -761,600 +761,59 @@ namespace drawinglayer
}
case PRIMITIVE2D_ID_GRAPHICPRIMITIVE2D :
{
- const primitive2d::GraphicPrimitive2D& rGraphicPrimitive = static_cast< const primitive2d::GraphicPrimitive2D& >(rCandidate);
- bool bUsingPDFExtOutDevData(false);
- basegfx::B2DVector aTranslate, aScale;
- static bool bSuppressPDFExtOutDevDataSupport(false);
-
- if(mpPDFExtOutDevData && !bSuppressPDFExtOutDevDataSupport)
- {
- // emulate data handling from UnoControlPDFExportContact, original see
- // svtools/source/graphic/grfmgr.cxx
- const Graphic& rGraphic = rGraphicPrimitive.getGraphicObject().GetGraphic();
-
- if(rGraphic.IsGfxLink())
- {
- const GraphicAttr& rAttr = rGraphicPrimitive.getGraphicAttr();
-
- if(!rAttr.IsSpecialDrawMode() && !rAttr.IsAdjusted())
- {
- const basegfx::B2DHomMatrix& rTransform = rGraphicPrimitive.getTransform();
- double fRotate, fShearX;
- rTransform.decompose(aScale, aTranslate, fRotate, fShearX);
-
- if( basegfx::fTools::equalZero( fRotate ) && ( aScale.getX() > 0.0 ) && ( aScale.getY() > 0.0 ) )
- {
- bUsingPDFExtOutDevData = true;
- mpPDFExtOutDevData->BeginGroup();
- }
- }
- }
- }
-
- // process recursively and add MetaFile comment
- process(rGraphicPrimitive);
-
- if(bUsingPDFExtOutDevData)
- {
- // emulate data handling from UnoControlPDFExportContact, original see
- // svtools/source/graphic/grfmgr.cxx
- const basegfx::B2DRange aCurrentRange(
- aTranslate.getX(), aTranslate.getY(),
- aTranslate.getX() + aScale.getX(), aTranslate.getY() + aScale.getY());
- const ::tools::Rectangle aCurrentRect(
- sal_Int32(floor(aCurrentRange.getMinX())), sal_Int32(floor(aCurrentRange.getMinY())),
- sal_Int32(ceil(aCurrentRange.getMaxX())), sal_Int32(ceil(aCurrentRange.getMaxY())));
- const GraphicAttr& rAttr = rGraphicPrimitive.getGraphicAttr();
- // fdo#72530 don't pass empty Rectangle to EndGroup
- ::tools::Rectangle aCropRect(aCurrentRect);
-
- if(rAttr.IsCropped())
- {
- // calculate scalings between real image size and logic object size. This
- // is necessary since the crop values are relative to original bitmap size
- double fFactorX(1.0);
- double fFactorY(1.0);
-
- {
- const MapMode aMapMode100thmm(MapUnit::Map100thMM);
- const Size aBitmapSize(OutputDevice::LogicToLogic(
- rGraphicPrimitive.getGraphicObject().GetPrefSize(),
- rGraphicPrimitive.getGraphicObject().GetPrefMapMode(), aMapMode100thmm));
- const double fDivX(aBitmapSize.Width() - rAttr.GetLeftCrop() - rAttr.GetRightCrop());
- const double fDivY(aBitmapSize.Height() - rAttr.GetTopCrop() - rAttr.GetBottomCrop());
-
- if(!basegfx::fTools::equalZero(fDivX))
- {
- fFactorX = aScale.getX() / fDivX;
- }
-
- if(!basegfx::fTools::equalZero(fDivY))
- {
- fFactorY = aScale.getY() / fDivY;
- }
- }
-
- // calculate crop range and rect
- basegfx::B2DRange aCropRange;
- aCropRange.expand(aCurrentRange.getMinimum() - basegfx::B2DPoint(rAttr.GetLeftCrop() * fFactorX, rAttr.GetTopCrop() * fFactorY));
- aCropRange.expand(aCurrentRange.getMaximum() + basegfx::B2DPoint(rAttr.GetRightCrop() * fFactorX, rAttr.GetBottomCrop() * fFactorY));
-
- aCropRect = ::tools::Rectangle(
- sal_Int32(floor(aCropRange.getMinX())), sal_Int32(floor(aCropRange.getMinY())),
- sal_Int32(ceil(aCropRange.getMaxX())), sal_Int32(ceil(aCropRange.getMaxY())));
- }
-
- // #i123295# 3rd param is uncropped rect, 4th is cropped. The primitive has the cropped
- // object transformation, thus aCurrentRect *is* the clip region while aCropRect is the expanded,
- // uncropped region. Thus, correct order is aCropRect, aCurrentRect
- mpPDFExtOutDevData->EndGroup(rGraphicPrimitive.getGraphicObject().GetGraphic(),
- rAttr.GetTransparency(),
- aCropRect,
- aCurrentRect);
- }
-
+ processGraphicPrimitive2D(static_cast<const primitive2d::GraphicPrimitive2D&>(rCandidate));
break;
}
case PRIMITIVE2D_ID_CONTROLPRIMITIVE2D :
{
- const primitive2d::ControlPrimitive2D& rControlPrimitive = static_cast< const primitive2d::ControlPrimitive2D& >(rCandidate);
- const uno::Reference< awt::XControl >& rXControl(rControlPrimitive.getXControl());
- bool bIsPrintableControl(false);
-
- // find out if control is printable
- if(rXControl.is())
- {
- try
- {
- uno::Reference< beans::XPropertySet > xModelProperties(rXControl->getModel(), uno::UNO_QUERY);
- uno::Reference< beans::XPropertySetInfo > xPropertyInfo(xModelProperties.is()
- ? xModelProperties->getPropertySetInfo()
- : uno::Reference< beans::XPropertySetInfo >());
- const OUString sPrintablePropertyName("Printable");
-
- if(xPropertyInfo.is() && xPropertyInfo->hasPropertyByName(sPrintablePropertyName))
- {
- OSL_VERIFY(xModelProperties->getPropertyValue(sPrintablePropertyName) >>= bIsPrintableControl);
- }
- }
- catch(const uno::Exception&)
- {
- OSL_FAIL("VclMetafileProcessor2D: No access to printable flag of Control, caught an exception!");
- }
- }
-
- // PDF export and printing only for printable controls
- if(bIsPrintableControl)
- {
- const bool bPDFExport(mpPDFExtOutDevData && mpPDFExtOutDevData->GetIsExportFormFields());
- bool bDoProcessRecursively(true);
-
- if(bPDFExport)
- {
- // PDF export. Emulate data handling from UnoControlPDFExportContact
- // I have now moved describePDFControl to toolkit, thus i can implement the PDF
- // form control support now as follows
- std::unique_ptr< vcl::PDFWriter::AnyWidget > pPDFControl(
- ::toolkitform::describePDFControl( rXControl, *mpPDFExtOutDevData ) );
-
- if(pPDFControl.get())
- {
- // still need to fill in the location (is a class Rectangle)
- const basegfx::B2DRange aRangeLogic(rControlPrimitive.getB2DRange(getViewInformation2D()));
- const ::tools::Rectangle aRectLogic(
- static_cast<sal_Int32>(floor(aRangeLogic.getMinX())), static_cast<sal_Int32>(floor(aRangeLogic.getMinY())),
- static_cast<sal_Int32>(ceil(aRangeLogic.getMaxX())), static_cast<sal_Int32>(ceil(aRangeLogic.getMaxY())));
- pPDFControl->Location = aRectLogic;
-
- Size aFontSize(pPDFControl->TextFont.GetFontSize());
- aFontSize = OutputDevice::LogicToLogic(aFontSize, MapMode(MapUnit::MapPoint), mpOutputDevice->GetMapMode());
- pPDFControl->TextFont.SetFontSize(aFontSize);
-
- mpPDFExtOutDevData->BeginStructureElement(vcl::PDFWriter::Form);
- mpPDFExtOutDevData->CreateControl(*pPDFControl.get());
- mpPDFExtOutDevData->EndStructureElement();
-
- // no normal paint needed (see original UnoControlPDFExportContact::do_PaintObject);
- // do not process recursively
- bDoProcessRecursively = false;
- }
- else
- {
- // PDF export did not work, try simple output.
- // Fallback to printer output by not setting bDoProcessRecursively
- // to false.
- }
- }
-
- // #i93169# used flag the wrong way; true means that nothing was done yet
- if(bDoProcessRecursively)
- {
- // printer output
- 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 aObjectToDiscrete(getViewInformation2D().getObjectToViewTransformation() * rControlPrimitive.getTransform());
- const basegfx::B2DPoint aTopLeftDiscrete(aObjectToDiscrete * basegfx::B2DPoint(0.0, 0.0));
-
- // draw it
- xControlView->draw(basegfx::fround(aTopLeftDiscrete.getX()), basegfx::fround(aTopLeftDiscrete.getY()));
- bDoProcessRecursively = false;
-
- // restore original graphics
- xControlView->setGraphics(xOriginalGraphics);
- }
- }
- catch( const uno::Exception& )
- {
- OSL_FAIL("VclMetafileProcessor2D: Printing of Control failed, caught an exception!");
- }
- }
-
- // process recursively if not done yet to export as decomposition (bitmap)
- if(bDoProcessRecursively)
- {
- process(rControlPrimitive);
- }
- }
-
+ processControlPrimitive2D(static_cast<const primitive2d::ControlPrimitive2D&>(rCandidate));
break;
}
case PRIMITIVE2D_ID_TEXTHIERARCHYFIELDPRIMITIVE2D :
{
- // support for FIELD_SEQ_BEGIN, FIELD_SEQ_END and URL. It wraps text primitives (but is not limited to)
- // thus do the MetafileAction embedding stuff but just handle recursively.
- const primitive2d::TextHierarchyFieldPrimitive2D& rFieldPrimitive = static_cast< const primitive2d::TextHierarchyFieldPrimitive2D& >(rCandidate);
- const OString aCommentStringCommon("FIELD_SEQ_BEGIN");
- const OString aCommentStringPage("FIELD_SEQ_BEGIN;PageField");
- const OString aCommentStringEnd("FIELD_SEQ_END");
- OUString aURL;
-
- switch(rFieldPrimitive.getType())
- {
- default : // case drawinglayer::primitive2d::FIELD_TYPE_COMMON :
- {
- mpMetaFile->AddAction(new MetaCommentAction(aCommentStringCommon));
- break;
- }
- case drawinglayer::primitive2d::FIELD_TYPE_PAGE :
- {
- mpMetaFile->AddAction(new MetaCommentAction(aCommentStringPage));
- break;
- }
- case drawinglayer::primitive2d::FIELD_TYPE_URL :
- {
- aURL = rFieldPrimitive.getValue("URL");
-
- if (!aURL.isEmpty())
- {
- mpMetaFile->AddAction(new MetaCommentAction(aCommentStringCommon, 0, reinterpret_cast<const sal_uInt8*>(aURL.getStr()), 2 * aURL.getLength()));
- }
-
- break;
- }
- }
-
- // process recursively
- primitive2d::Primitive2DContainer rContent;
- rFieldPrimitive.get2DDecomposition(rContent, getViewInformation2D());
- process(rContent);
-
- // for the end comment the type is not relevant yet, they are all the same. Just add.
- mpMetaFile->AddAction(new MetaCommentAction(aCommentStringEnd));
-
- if(mpPDFExtOutDevData && drawinglayer::primitive2d::FIELD_TYPE_URL == rFieldPrimitive.getType())
- {
- // emulate data handling from ImpEditEngine::Paint
- const basegfx::B2DRange aViewRange(rContent.getB2DRange(getViewInformation2D()));
- const ::tools::Rectangle aRectLogic(
- static_cast<sal_Int32>(floor(aViewRange.getMinX())), static_cast<sal_Int32>(floor(aViewRange.getMinY())),
- static_cast<sal_Int32>(ceil(aViewRange.getMaxX())), static_cast<sal_Int32>(ceil(aViewRange.getMaxY())));
- vcl::PDFExtOutDevBookmarkEntry aBookmark;
- aBookmark.nLinkId = mpPDFExtOutDevData->CreateLink(aRectLogic);
- aBookmark.aBookmark = aURL;
- std::vector< vcl::PDFExtOutDevBookmarkEntry >& rBookmarks = mpPDFExtOutDevData->GetBookmarks();
- rBookmarks.push_back( aBookmark );
- }
-
+ processTextHierarchyFieldPrimitive2D(static_cast<const primitive2d::TextHierarchyFieldPrimitive2D& >(rCandidate));
break;
}
case PRIMITIVE2D_ID_TEXTHIERARCHYLINEPRIMITIVE2D :
{
- const primitive2d::TextHierarchyLinePrimitive2D& rLinePrimitive = static_cast< const primitive2d::TextHierarchyLinePrimitive2D& >(rCandidate);
- const OString aCommentString("XTEXT_EOL");
-
- // process recursively and add MetaFile comment
- process(rLinePrimitive);
- mpMetaFile->AddAction(new MetaCommentAction(aCommentString));
-
+ processTextHierarchyLinePrimitive2D(static_cast<const primitive2d::TextHierarchyLinePrimitive2D&>(rCandidate));
break;
}
case PRIMITIVE2D_ID_TEXTHIERARCHYBULLETPRIMITIVE2D :
{
- // in Outliner::PaintBullet(), a MetafileComment for bullets is added, too. The
- // "XTEXT_EOC" is used, use here, too.
- const primitive2d::TextHierarchyBulletPrimitive2D& rBulletPrimitive = static_cast< const primitive2d::TextHierarchyBulletPrimitive2D& >(rCandidate);
- const OString aCommentString("XTEXT_EOC");
-
- // process recursively and add MetaFile comment
- process(rBulletPrimitive);
- mpMetaFile->AddAction(new MetaCommentAction(aCommentString));
-
+ processTextHierarchyBulletPrimitive2D(static_cast<const primitive2d::TextHierarchyBulletPrimitive2D&>(rCandidate));
break;
}
case PRIMITIVE2D_ID_TEXTHIERARCHYPARAGRAPHPRIMITIVE2D :
{
- const primitive2d::TextHierarchyParagraphPrimitive2D& rParagraphPrimitive = static_cast< const primitive2d::TextHierarchyParagraphPrimitive2D& >(rCandidate);
- const OString aCommentString("XTEXT_EOP");
-
- if(mpPDFExtOutDevData)
- {
- // emulate data handling from ImpEditEngine::Paint
- mpPDFExtOutDevData->BeginStructureElement( vcl::PDFWriter::Paragraph );
- }
-
- // process recursively and add MetaFile comment
- process(rParagraphPrimitive);
- mpMetaFile->AddAction(new MetaCommentAction(aCommentString));
-
- if(mpPDFExtOutDevData)
- {
- // emulate data handling from ImpEditEngine::Paint
- mpPDFExtOutDevData->EndStructureElement();
- }
-
+ processTextHierarchyParagraphPrimitive2D(static_cast<const primitive2d::TextHierarchyParagraphPrimitive2D&>(rCandidate));
break;
}
case PRIMITIVE2D_ID_TEXTHIERARCHYBLOCKPRIMITIVE2D :
{
- const primitive2d::TextHierarchyBlockPrimitive2D& rBlockPrimitive = static_cast< const primitive2d::TextHierarchyBlockPrimitive2D& >(rCandidate);
- const OString aCommentStringA("XTEXT_PAINTSHAPE_BEGIN");
- const OString aCommentStringB("XTEXT_PAINTSHAPE_END");
-
- // add MetaFile comment, process recursively and add MetaFile comment
- mpMetaFile->AddAction(new MetaCommentAction(aCommentStringA));
- process(rBlockPrimitive);
- mpMetaFile->AddAction(new MetaCommentAction(aCommentStringB));
-
+ processTextHierarchyBlockPrimitive2D(static_cast<const primitive2d::TextHierarchyBlockPrimitive2D&>(rCandidate));
break;
}
case PRIMITIVE2D_ID_TEXTSIMPLEPORTIONPRIMITIVE2D :
case PRIMITIVE2D_ID_TEXTDECORATEDPORTIONPRIMITIVE2D :
{
// for supporting TEXT_ MetaFile actions there is more to do here; get the candidate
- const primitive2d::TextSimplePortionPrimitive2D& rTextCandidate = static_cast< const primitive2d::TextSimplePortionPrimitive2D& >(rCandidate);
- // const primitive2d::TextDecoratedPortionPrimitive2D* pTextDecoratedCandidate = dynamic_cast< const primitive2d::TextDecoratedPortionPrimitive2D* >(&rCandidate);
-
- // Adapt evtl. used special DrawMode
- const DrawModeFlags nOriginalDrawMode(mpOutputDevice->GetDrawMode());
- adaptTextToFillDrawMode();
-
- // directdraw of text simple portion; use default processing
- RenderTextSimpleOrDecoratedPortionPrimitive2D(rTextCandidate);
-
- // restore DrawMode
- mpOutputDevice->SetDrawMode(nOriginalDrawMode);
-
- // #i101169# if(pTextDecoratedCandidate)
- {
- // support for TEXT_ MetaFile actions only for decorated texts
- if(!mxBreakIterator.is())
- {
- uno::Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
- mxBreakIterator = i18n::BreakIterator::create(xContext);
- }
-
- const OUString& rTxt = rTextCandidate.getText();
- const sal_Int32 nTextLength(rTextCandidate.getTextLength()); // rTxt.getLength());
-
- if(nTextLength)
- {
- const css::lang::Locale& rLocale = rTextCandidate.getLocale();
- const sal_Int32 nTextPosition(rTextCandidate.getTextPosition());
-
- sal_Int32 nDone;
- sal_Int32 nNextCellBreak(mxBreakIterator->nextCharacters(rTxt, nTextPosition, rLocale, css::i18n::CharacterIteratorMode::SKIPCELL, 0, nDone));
- css::i18n::Boundary nNextWordBoundary(mxBreakIterator->getWordBoundary(rTxt, nTextPosition, rLocale, css::i18n::WordType::ANY_WORD, true));
- sal_Int32 nNextSentenceBreak(mxBreakIterator->endOfSentence(rTxt, nTextPosition, rLocale));
- const OString aCommentStringA("XTEXT_EOC");
- const OString aCommentStringB("XTEXT_EOW");
- const OString aCommentStringC("XTEXT_EOS");
-
- for(sal_Int32 i(nTextPosition); i < nTextPosition + nTextLength; i++)
- {
- // create the entries for the respective break positions
- if(i == nNextCellBreak)
- {
- mpMetaFile->AddAction(new MetaCommentAction(aCommentStringA, i - nTextPosition));
- nNextCellBreak = mxBreakIterator->nextCharacters(rTxt, i, rLocale, css::i18n::CharacterIteratorMode::SKIPCELL, 1, nDone);
- }
- if(i == nNextWordBoundary.endPos)
- {
- mpMetaFile->AddAction(new MetaCommentAction(aCommentStringB, i - nTextPosition));
- nNextWordBoundary = mxBreakIterator->getWordBoundary(rTxt, i + 1, rLocale, css::i18n::WordType::ANY_WORD, true);
- }
- if(i == nNextSentenceBreak)
- {
- mpMetaFile->AddAction(new MetaCommentAction(aCommentStringC, i - nTextPosition));
- nNextSentenceBreak = mxBreakIterator->endOfSentence(rTxt, i + 1, rLocale);
- }
- }
- }
- }
-
+ processTextSimplePortionPrimitive2D(static_cast<const primitive2d::TextSimplePortionPrimitive2D& >(rCandidate));
break;
}
case PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D :
{
- const primitive2d::PolygonHairlinePrimitive2D& rHairlinePrimitive = static_cast< const primitive2d::PolygonHairlinePrimitive2D& >(rCandidate);
- const basegfx::B2DPolygon& rBasePolygon = rHairlinePrimitive.getB2DPolygon();
-
- if(rBasePolygon.count() > (MAX_POLYGON_POINT_COUNT_METAFILE - 1))
- {
- // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
- // per polygon. If there are more, split the polygon in half and call recursively
- basegfx::B2DPolygon aLeft, aRight;
- splitLinePolygon(rBasePolygon, aLeft, aRight);
- rtl::Reference< primitive2d::PolygonHairlinePrimitive2D > xPLeft(new primitive2d::PolygonHairlinePrimitive2D(aLeft, rHairlinePrimitive.getBColor()));
- rtl::Reference< primitive2d::PolygonHairlinePrimitive2D > xPRight(new primitive2d::PolygonHairlinePrimitive2D(aRight, rHairlinePrimitive.getBColor()));
-
- processBasePrimitive2D(*xPLeft.get());
- processBasePrimitive2D(*xPRight.get());
- }
- else
- {
- // direct draw of hairline; use default processing
- // support SvtGraphicStroke MetaCommentAction
- const basegfx::BColor aLineColor(maBColorModifierStack.getModifiedColor(rHairlinePrimitive.getBColor()));
- SvtGraphicStroke* pSvtGraphicStroke = nullptr;
-
- // #i121267# Not needed, does not give better quality compared with
- // the MetaActionType::POLYPOLYGON written by RenderPolygonHairlinePrimitive2D
- // below
- bool bSupportSvtGraphicStroke(false);
-
- if(bSupportSvtGraphicStroke)
- {
- pSvtGraphicStroke = impTryToCreateSvtGraphicStroke(
- rHairlinePrimitive.getB2DPolygon(),
- &aLineColor,
- nullptr, nullptr, nullptr, nullptr);
-
- impStartSvtGraphicStroke(pSvtGraphicStroke);
- }
-
- RenderPolygonHairlinePrimitive2D(static_cast< const primitive2d::PolygonHairlinePrimitive2D& >(rCandidate), false);
-
- if(bSupportSvtGraphicStroke)
- {
- impEndSvtGraphicStroke(pSvtGraphicStroke);
- }
- }
+ processPolygonHairlinePrimitive2D(static_cast<const primitive2d::PolygonHairlinePrimitive2D&>(rCandidate));
break;
}
case PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D :
{
- const primitive2d::PolygonStrokePrimitive2D& rStrokePrimitive = static_cast< const primitive2d::PolygonStrokePrimitive2D& >(rCandidate);
- const basegfx::B2DPolygon& rBasePolygon = rStrokePrimitive.getB2DPolygon();
-
- if(rBasePolygon.count() > (MAX_POLYGON_POINT_COUNT_METAFILE - 1))
- {
- // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
- // per polygon. If there are more, split the polygon in half and call recursively
- basegfx::B2DPolygon aLeft, aRight;
- splitLinePolygon(rBasePolygon, aLeft, aRight);
- rtl::Reference< primitive2d::PolygonStrokePrimitive2D > xPLeft(new primitive2d::PolygonStrokePrimitive2D(
- aLeft, rStrokePrimitive.getLineAttribute(), rStrokePrimitive.getStrokeAttribute()));
- rtl::Reference< primitive2d::PolygonStrokePrimitive2D > xPRight(new primitive2d::PolygonStrokePrimitive2D(
- aRight, rStrokePrimitive.getLineAttribute(), rStrokePrimitive.getStrokeAttribute()));
-
- processBasePrimitive2D(*xPLeft.get());
- processBasePrimitive2D(*xPRight.get());
- }
- else
- {
- mpOutputDevice->Push(PushFlags::LINECOLOR | PushFlags::FILLCOLOR);
-
- // support SvtGraphicStroke MetaCommentAction
- SvtGraphicStroke* pSvtGraphicStroke = impTryToCreateSvtGraphicStroke(
- rBasePolygon, nullptr,
- &rStrokePrimitive.getLineAttribute(),
- &rStrokePrimitive.getStrokeAttribute(),
- nullptr, nullptr);
-
- impStartSvtGraphicStroke(pSvtGraphicStroke);
- const attribute::LineAttribute& rLine = rStrokePrimitive.getLineAttribute();
-
- // create MetaPolyLineActions, but without LineStyle::Dash
- if(basegfx::fTools::more(rLine.getWidth(), 0.0))
- {
- const attribute::StrokeAttribute& rStroke = rStrokePrimitive.getStrokeAttribute();
- basegfx::B2DPolyPolygon aHairLinePolyPolygon;
-
- if(0.0 == rStroke.getFullDotDashLen())
- {
- aHairLinePolyPolygon.append(rBasePolygon);
- }
- else
- {
- basegfx::utils::applyLineDashing(
- rBasePolygon, rStroke.getDotDashArray(),
- &aHairLinePolyPolygon, nullptr, rStroke.getFullDotDashLen());
- }
-
- const basegfx::BColor aHairlineColor(maBColorModifierStack.getModifiedColor(rLine.getColor()));
- mpOutputDevice->SetLineColor(Color(aHairlineColor));
- mpOutputDevice->SetFillColor();
- aHairLinePolyPolygon.transform(maCurrentTransformation);
-
- // use the transformed line width
- LineInfo aLineInfo(LineStyle::Solid, basegfx::fround(getTransformedLineWidth(rLine.getWidth())));
- aLineInfo.SetLineJoin(rLine.getLineJoin());
- aLineInfo.SetLineCap(rLine.getLineCap());
-
- for(sal_uInt32 a(0); a < aHairLinePolyPolygon.count(); a++)
- {
- const basegfx::B2DPolygon aCandidate(aHairLinePolyPolygon.getB2DPolygon(a));
-
- if(aCandidate.count() > 1)
- {
- const ::tools::Polygon aToolsPolygon(aCandidate);
-
- mpMetaFile->AddAction(new MetaPolyLineAction(aToolsPolygon, aLineInfo));
- }
- }
- }
- else
- {
- process(rCandidate);
- }
-
- impEndSvtGraphicStroke(pSvtGraphicStroke);
-
- mpOutputDevice->Pop();
- }
-
+ processPolygonStrokePrimitive2D(static_cast<const primitive2d::PolygonStrokePrimitive2D&>(rCandidate));
break;
}
case PRIMITIVE2D_ID_POLYGONSTROKEARROWPRIMITIVE2D :
{
- const primitive2d::PolygonStrokeArrowPrimitive2D& rStrokeArrowPrimitive = static_cast< const primitive2d::PolygonStrokeArrowPrimitive2D& >(rCandidate);
- const basegfx::B2DPolygon& rBasePolygon = rStrokeArrowPrimitive.getB2DPolygon();
-
- if(rBasePolygon.count() > (MAX_POLYGON_POINT_COUNT_METAFILE - 1))
- {
- // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
- // per polygon. If there are more, split the polygon in half and call recursively
- basegfx::B2DPolygon aLeft, aRight;
- splitLinePolygon(rBasePolygon, aLeft, aRight);
- const attribute::LineStartEndAttribute aEmpty;
- rtl::Reference< primitive2d::PolygonStrokeArrowPrimitive2D > xPLeft(new primitive2d::PolygonStrokeArrowPrimitive2D(
- aLeft,
- rStrokeArrowPrimitive.getLineAttribute(),
- rStrokeArrowPrimitive.getStrokeAttribute(),
- rStrokeArrowPrimitive.getStart(),
- aEmpty));
- rtl::Reference< primitive2d::PolygonStrokeArrowPrimitive2D > xPRight(new primitive2d::PolygonStrokeArrowPrimitive2D(
- aRight,
- rStrokeArrowPrimitive.getLineAttribute(),
- rStrokeArrowPrimitive.getStrokeAttribute(),
- aEmpty,
- rStrokeArrowPrimitive.getEnd()));
-
- processBasePrimitive2D(*xPLeft.get());
- processBasePrimitive2D(*xPRight.get());
- }
- else
- {
- // support SvtGraphicStroke MetaCommentAction
- SvtGraphicStroke* pSvtGraphicStroke = impTryToCreateSvtGraphicStroke(
- rBasePolygon, nullptr,
- &rStrokeArrowPrimitive.getLineAttribute(),
- &rStrokeArrowPrimitive.getStrokeAttribute(),
- &rStrokeArrowPrimitive.getStart(),
- &rStrokeArrowPrimitive.getEnd());
-
- // write LineGeometry start marker
- impStartSvtGraphicStroke(pSvtGraphicStroke);
-
- // #i116162# When B&W is set as DrawMode, DrawModeFlags::WhiteFill is used
- // to let all fills be just white; for lines DrawModeFlags::BlackLine is used
- // so all line geometry is supposed to get black. Since in the in-between
- // stages of line geometry drawing filled polygons are used (e.g. line
- // start/ends) it is necessary to change these drawmodes to preserve
- // that lines shall be black; thus change DrawModeFlags::WhiteFill to
- // DrawModeFlags::BlackFill during line geometry processing to have line geometry
- // parts filled black.
- const DrawModeFlags nOldDrawMode(mpOutputDevice->GetDrawMode());
- const bool bDrawmodeChange(nOldDrawMode & DrawModeFlags::WhiteFill && mnSvtGraphicStrokeCount);
-
- if(bDrawmodeChange)
- {
- mpOutputDevice->SetDrawMode((nOldDrawMode & ~DrawModeFlags::WhiteFill) | DrawModeFlags::BlackFill);
- }
-
- // process sub-line geometry (evtl. filled PolyPolygons)
- process(rCandidate);
-
- if(bDrawmodeChange)
- {
- mpOutputDevice->SetDrawMode(nOldDrawMode);
- }
-
- // write LineGeometry end marker
- impEndSvtGraphicStroke(pSvtGraphicStroke);
- }
-
+ processPolygonStrokeArrowPrimitive2D(static_cast<const primitive2d::PolygonStrokeArrowPrimitive2D&>(rCandidate));
break;
}
case PRIMITIVE2D_ID_BITMAPPRIMITIVE2D :
@@ -1368,416 +827,27 @@ namespace drawinglayer
}
case PRIMITIVE2D_ID_POLYPOLYGONGRAPHICPRIMITIVE2D :
{
- // need to handle PolyPolygonGraphicPrimitive2D here to support XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END
- const primitive2d::PolyPolygonGraphicPrimitive2D& rBitmapCandidate = static_cast< const primitive2d::PolyPolygonGraphicPrimitive2D& >(rCandidate);
- basegfx::B2DPolyPolygon aLocalPolyPolygon(rBitmapCandidate.getB2DPolyPolygon());
-
- fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon);
-
- SvtGraphicFill* pSvtGraphicFill = nullptr;
-
- if(!mnSvtGraphicFillCount && aLocalPolyPolygon.count())
- {
- // #121194# Changed implementation and checked usages fo convert to metafile,
- // presentation start (uses SvtGraphicFill) and printing.
-
- // calculate transformation. Get real object size, all values in FillGraphicAttribute
- // are relative to the unified object
- aLocalPolyPolygon.transform(maCurrentTransformation);
- const basegfx::B2DVector aOutlineSize(aLocalPolyPolygon.getB2DRange().getRange());
-
- // the scaling needs scale from pixel to logic coordinate system
- const attribute::FillGraphicAttribute& rFillGraphicAttribute = rBitmapCandidate.getFillGraphic();
- const Size aBmpSizePixel(rFillGraphicAttribute.getGraphic().GetSizePixel());
-
- // setup transformation like in impgrfll. Multiply with aOutlineSize
- // to get from unit coordinates in rFillGraphicAttribute.getGraphicRange()
- // to object coordinates with object's top left being at (0,0). Divide
- // by pixel size so that scale from pixel to logic will work in SvtGraphicFill.
- const basegfx::B2DVector aTransformScale(
- rFillGraphicAttribute.getGraphicRange().getRange() /
- basegfx::B2DVector(
- std::max(1.0, double(aBmpSizePixel.Width())),
- std::max(1.0, double(aBmpSizePixel.Height()))) *
- aOutlineSize);
- const basegfx::B2DPoint aTransformPosition(
- rFillGraphicAttribute.getGraphicRange().getMinimum() * aOutlineSize);
-
- // setup transformation like in impgrfll
- SvtGraphicFill::Transform aTransform;
-
- // scale values are divided by bitmap pixel sizes
- aTransform.matrix[0] = aTransformScale.getX();
- aTransform.matrix[4] = aTransformScale.getY();
-
- // translates are absolute
- aTransform.matrix[2] = aTransformPosition.getX();
- aTransform.matrix[5] = aTransformPosition.getY();
-
- pSvtGraphicFill = new SvtGraphicFill(
- getFillPolyPolygon(aLocalPolyPolygon),
- Color(),
- 0.0,
- SvtGraphicFill::fillEvenOdd,
- SvtGraphicFill::fillTexture,
- aTransform,
- rFillGraphicAttribute.getTiling(),
- SvtGraphicFill::hatchSingle,
- Color(),
- SvtGraphicFill::GradientType::Linear,
- Color(),
- Color(),
- 0,
- rFillGraphicAttribute.getGraphic());
- }
-
- // Do use decomposition; encapsulate with SvtGraphicFill
- impStartSvtGraphicFill(pSvtGraphicFill);
- process(rCandidate);
- impEndSvtGraphicFill(pSvtGraphicFill);
-
+ processPolyPolygonGraphicPrimitive2D(static_cast<const primitive2d::PolyPolygonGraphicPrimitive2D& >(rCandidate));
break;
}
case PRIMITIVE2D_ID_POLYPOLYGONHATCHPRIMITIVE2D :
{
- // need to handle PolyPolygonHatchPrimitive2D here to support XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END
- const primitive2d::PolyPolygonHatchPrimitive2D& rHatchCandidate = static_cast< const primitive2d::PolyPolygonHatchPrimitive2D& >(rCandidate);
- const attribute::FillHatchAttribute& rFillHatchAttribute = rHatchCandidate.getFillHatch();
- basegfx::B2DPolyPolygon aLocalPolyPolygon(rHatchCandidate.getB2DPolyPolygon());
-
- if(aLocalPolyPolygon.getB2DRange() != rHatchCandidate.getDefinitionRange())
- {
- // the range which defines the hatch is different from the range of the
- // geometry (used for writer frames). This cannot be done calling vcl, thus use
- // decomposition here
- process(rCandidate);
- break;
- }
-
- // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
- // per polygon. Split polygon until there are less than that
- fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon);
-
- if(rFillHatchAttribute.isFillBackground())
- {
- // with fixing #i111954# (see below) the possible background
- // fill of a hatched object was lost.Generate a background fill
- // primitive and render it
- const primitive2d::Primitive2DReference xBackground(
- new primitive2d::PolyPolygonColorPrimitive2D(
- aLocalPolyPolygon,
- rHatchCandidate.getBackgroundColor()));
-
- process(primitive2d::Primitive2DContainer { xBackground });
- }
-
- SvtGraphicFill* pSvtGraphicFill = nullptr;
- aLocalPolyPolygon.transform(maCurrentTransformation);
-
- if(!mnSvtGraphicFillCount && aLocalPolyPolygon.count())
- {
- // re-create a VCL hatch as base data
- SvtGraphicFill::HatchType eHatch(SvtGraphicFill::hatchSingle);
-
- switch(rFillHatchAttribute.getStyle())
- {
- default: // attribute::HatchStyle::Single :
- {
- eHatch = SvtGraphicFill::hatchSingle;
- break;
- }
- case attribute::HatchStyle::Double :
- {
- eHatch = SvtGraphicFill::hatchDouble;
- break;
- }
- case attribute::HatchStyle::Triple :
- {
- eHatch = SvtGraphicFill::hatchTriple;
- break;
- }
- }
-
- SvtGraphicFill::Transform aTransform;
-
- // scale
- aTransform.matrix[0] *= rFillHatchAttribute.getDistance();
- aTransform.matrix[4] *= rFillHatchAttribute.getDistance();
-
- // rotate (was never correct in impgrfll anyways, use correct angle now)
- aTransform.matrix[0] *= cos(rFillHatchAttribute.getAngle());
- aTransform.matrix[1] *= -sin(rFillHatchAttribute.getAngle());
- aTransform.matrix[3] *= sin(rFillHatchAttribute.getAngle());
- aTransform.matrix[4] *= cos(rFillHatchAttribute.getAngle());
-
- pSvtGraphicFill = new SvtGraphicFill(
- getFillPolyPolygon(aLocalPolyPolygon),
- Color(),
- 0.0,
- SvtGraphicFill::fillEvenOdd,
- SvtGraphicFill::fillHatch,
- aTransform,
- false,
- eHatch,
- Color(rFillHatchAttribute.getColor()),
- SvtGraphicFill::GradientType::Linear,
- Color(),
- Color(),
- 0,
- Graphic());
- }
-
- // Do use decomposition; encapsulate with SvtGraphicFill
- impStartSvtGraphicFill(pSvtGraphicFill);
-
- // #i111954# do NOT use decomposition, but use direct VCL-command
- // process(rCandidate.get2DDecomposition(getViewInformation2D()));
- const ::tools::PolyPolygon aToolsPolyPolygon(basegfx::utils::adaptiveSubdivideByAngle(aLocalPolyPolygon));
- const HatchStyle aHatchStyle(
- attribute::HatchStyle::Single == rFillHatchAttribute.getStyle() ? HatchStyle::Single :
- attribute::HatchStyle::Double == rFillHatchAttribute.getStyle() ? HatchStyle::Double :
- HatchStyle::Triple);
-
- mpOutputDevice->DrawHatch(aToolsPolyPolygon,
- Hatch(aHatchStyle,
- Color(rFillHatchAttribute.getColor()),
- basegfx::fround(rFillHatchAttribute.getDistance()),
- basegfx::fround(rFillHatchAttribute.getAngle() / F_PI1800)));
-
- impEndSvtGraphicFill(pSvtGraphicFill);
-
+ processPolyPolygonHatchPrimitive2D(static_cast<const primitive2d::PolyPolygonHatchPrimitive2D&>(rCandidate));
break;
}
case PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D :
{
- basegfx::B2DVector aScale, aTranslate;
- double fRotate, fShearX;
-
- maCurrentTransformation.decompose(aScale, aTranslate, fRotate, fShearX);
-
- if(!basegfx::fTools::equalZero(fRotate) || !basegfx::fTools::equalZero(fShearX))
- {
- // #i121185# When rotation or shear is used, a VCL Gradient cannot be used directly.
- // This is because VCL Gradient mechanism does *not* support to rotate the gradient
- // with objects and this case is not expressable in a Metafile (and cannot be added
- // since the FileFormats used, e.g. *.wmf, do not support it either).
- // Such cases happen when a graphic object uses a Metafile as graphic information or
- // a fill style definition uses a Metafile. In this cases the graphic content is
- // rotated with the graphic or filled object; this is not supported by the target
- // format of this conversion renderer - Metafiles.
- // To solve this, not a Gradient is written, but the decomposition of this object
- // is written to the Metafile. This is the PolyPolygons building the gradient fill.
- // These will need more space and time, but the result will be as if the Gradient
- // was rotated with the object.
- // This mechanism is used by all exporters still not using Primtives (e.g. Print,
- // Slideshow, Export rto PDF, export to Picture, ...) but relying on Metafile
- // transfers. One more reason to *change* these to primitives.
- // BTW: One more example how useful the principles of primitives are; the decomposition
- // is by definition a simpler, maybe more expensive representation of the same content.
- process(rCandidate);
- break;
- }
-
- const primitive2d::PolyPolygonGradientPrimitive2D& rGradientCandidate = static_cast< const primitive2d::PolyPolygonGradientPrimitive2D& >(rCandidate);
- basegfx::B2DPolyPolygon aLocalPolyPolygon(rGradientCandidate.getB2DPolyPolygon());
-
- if(aLocalPolyPolygon.getB2DRange() != rGradientCandidate.getDefinitionRange())
- {
- // the range which defines the gradient is different from the range of the
- // geometry (used for writer frames). This cannot be done calling vcl, thus use
- // decomposition here
- process(rCandidate);
- break;
- }
-
- // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
- // per polygon. Split polygon until there are less than that
- fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon);
-
- // for support of MetaCommentActions of the form XGRAD_SEQ_BEGIN, XGRAD_SEQ_END
- // it is safest to use the VCL OutputDevice::DrawGradient method which creates those.
- // re-create a VCL-gradient from FillGradientPrimitive2D and the needed tools PolyPolygon
- Gradient aVCLGradient;
- impConvertFillGradientAttributeToVCLGradient(aVCLGradient, rGradientCandidate.getFillGradient(), false);
- aLocalPolyPolygon.transform(maCurrentTransformation);
-
- // #i82145# ATM VCL printing of gradients using curved shapes does not work,
- // i submitted the bug with the given ID to THB. When that task is fixed it is
- // necessary to again remove this subdivision since it decreases possible
- // printing quality (not even resolution-dependent for now). THB will tell
- // me when that task is fixed in the master
- const ::tools::PolyPolygon aToolsPolyPolygon(
- getFillPolyPolygon(
- basegfx::utils::adaptiveSubdivideByAngle(aLocalPolyPolygon)));
-
-
- // XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END support
- SvtGraphicFill* pSvtGraphicFill = nullptr;
-
- if(!mnSvtGraphicFillCount && aLocalPolyPolygon.count())
- {
- // setup gradient stuff like in impgrfll
- SvtGraphicFill::GradientType eGrad(SvtGraphicFill::GradientType::Linear);
-
- switch(aVCLGradient.GetStyle())
- {
- default : // GradientStyle::Linear:
- case GradientStyle::Axial:
- eGrad = SvtGraphicFill::GradientType::Linear;
- break;
- case GradientStyle::Radial:
- case GradientStyle::Elliptical:
- eGrad = SvtGraphicFill::GradientType::Radial;
- break;
- case GradientStyle::Square:
- case GradientStyle::Rect:
- eGrad = SvtGraphicFill::GradientType::Rectangular;
- break;
- }
-
- pSvtGraphicFill = new SvtGraphicFill(
- aToolsPolyPolygon,
- Color(),
- 0.0,
- SvtGraphicFill::fillEvenOdd,
- SvtGraphicFill::fillGradient,
- SvtGraphicFill::Transform(),
- false,
- SvtGraphicFill::hatchSingle,
- Color(),
- eGrad,
- aVCLGradient.GetStartColor(),
- aVCLGradient.GetEndColor(),
- aVCLGradient.GetSteps(),
- Graphic());
- }
-
- // call VCL directly; encapsulate with SvtGraphicFill
- impStartSvtGraphicFill(pSvtGraphicFill);
- mpOutputDevice->DrawGradient(aToolsPolyPolygon, aVCLGradient);
- impEndSvtGraphicFill(pSvtGraphicFill);
-
+ processPolyPolygonGradientPrimitive2D(static_cast<const primitive2d::PolyPolygonGradientPrimitive2D&>(rCandidate));
break;
}
case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D :
{
- mpOutputDevice->Push(PushFlags::LINECOLOR | PushFlags::FILLCOLOR);
- const primitive2d::PolyPolygonColorPrimitive2D& rPolygonCandidate(static_cast< const primitive2d::PolyPolygonColorPrimitive2D& >(rCandidate));
- basegfx::B2DPolyPolygon aLocalPolyPolygon(rPolygonCandidate.getB2DPolyPolygon());
-
- // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
- // per polygon. Split polygon until there are less than that
- fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon);
-
- const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(rPolygonCandidate.getBColor()));
- aLocalPolyPolygon.transform(maCurrentTransformation);
-
- // XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END support
- SvtGraphicFill* pSvtGraphicFill = nullptr;
-
- // #i121267# Not needed, does not give better quality compared with
- // the MetaActionType::POLYPOLYGON written by the DrawPolyPolygon command
- // below
- bool bSupportSvtGraphicFill(false);
-
- if(bSupportSvtGraphicFill && !mnSvtGraphicFillCount && aLocalPolyPolygon.count())
- {
- // setup simple color fill stuff like in impgrfll
- pSvtGraphicFill = new SvtGraphicFill(
- getFillPolyPolygon(aLocalPolyPolygon),
- Color(aPolygonColor),
- 0.0,
- SvtGraphicFill::fillEvenOdd,
- SvtGraphicFill::fillSolid,
- SvtGraphicFill::Transform(),
- false,
- SvtGraphicFill::hatchSingle,
- Color(),
- SvtGraphicFill::GradientType::Linear,
- Color(),
- Color(),
- 0,
- Graphic());
- }
-
- // set line and fill color
- mpOutputDevice->SetFillColor(Color(aPolygonColor));
- mpOutputDevice->SetLineColor();
-
- // call VCL directly; encapsulate with SvtGraphicFill
- if(bSupportSvtGraphicFill)
- {
- impStartSvtGraphicFill(pSvtGraphicFill);
- }
-
- mpOutputDevice->DrawPolyPolygon(aLocalPolyPolygon);
-
- if(bSupportSvtGraphicFill)
- {
- impEndSvtGraphicFill(pSvtGraphicFill);
- }
-
- mpOutputDevice->Pop();
+ processPolyPolygonColorPrimitive2D(static_cast<const primitive2d::PolyPolygonColorPrimitive2D&>(rCandidate));
break;
}
case PRIMITIVE2D_ID_MASKPRIMITIVE2D :
{
- // mask group. Special handling for MetaFiles.
- const primitive2d::MaskPrimitive2D& rMaskCandidate = static_cast< const primitive2d::MaskPrimitive2D& >(rCandidate);
-
- if(!rMaskCandidate.getChildren().empty())
- {
- basegfx::B2DPolyPolygon aMask(rMaskCandidate.getMask());
-
- if(aMask.count())
- {
- // prepare new mask polygon and rescue current one
- aMask.transform(maCurrentTransformation);
- const basegfx::B2DPolyPolygon aLastClipPolyPolygon(maClipPolyPolygon);
-
- if(maClipPolyPolygon.count())
- {
- // there is already a clip polygon set; build clipped union of
- // current mask polygon and new one
- maClipPolyPolygon = basegfx::utils::clipPolyPolygonOnPolyPolygon(
- aMask,
- maClipPolyPolygon,
- true, // #i106516# we want the inside of aMask, not the outside
- false);
- }
- else
- {
- // use mask directly
- maClipPolyPolygon = aMask;
- }
-
- if(maClipPolyPolygon.count())
- {
- // set VCL clip region; subdivide before conversion to tools polygon. Subdivision necessary (!)
- // Removed subdivision and fixed in vcl::Region::ImplPolyPolyRegionToBandRegionFunc() in VCL where
- // the ClipRegion is built from the Polygon. A AdaptiveSubdivide on the source polygon was missing there
- mpOutputDevice->Push(PushFlags::CLIPREGION);
- mpOutputDevice->SetClipRegion(vcl::Region(maClipPolyPolygon));
-
- // recursively paint content
- // #i121267# Only need to process sub-content when clip polygon is *not* empty.
- // If it is empty, the clip is empty and there can be nothing inside.
- process(rMaskCandidate.getChildren());
-
- // restore VCL clip region
- mpOutputDevice->Pop();
- }
-
- // restore to rescued clip polygon
- maClipPolyPolygon = aLastClipPolyPolygon;
- }
- else
- {
- // no mask, no clipping. recursively paint content
- process(rMaskCandidate.getChildren());
- }
- }
-
+ processMaskPrimitive2D(static_cast<const primitive2d::MaskPrimitive2D&>(rCandidate));
break;
}
case PRIMITIVE2D_ID_MODIFIEDCOLORPRIMITIVE2D :
@@ -1788,278 +858,12 @@ namespace drawinglayer
}
case PRIMITIVE2D_ID_UNIFIEDTRANSPARENCEPRIMITIVE2D :
{
- mpOutputDevice->Push(PushFlags::LINECOLOR | PushFlags::FILLCOLOR);
- // for metafile: Need to examine what the pure vcl version is doing here actually
- // - uses DrawTransparent with metafile for content and a gradient
- // - uses DrawTransparent for single PolyPolygons directly. Can be detected by
- // checking the content for single PolyPolygonColorPrimitive2D
- const primitive2d::UnifiedTransparencePrimitive2D& rUniTransparenceCandidate = static_cast< const primitive2d::UnifiedTransparencePrimitive2D& >(rCandidate);
- const primitive2d::Primitive2DContainer& rContent = rUniTransparenceCandidate.getChildren();
-
- if(!rContent.empty())
- {
- if(0.0 == rUniTransparenceCandidate.getTransparence())
- {
- // not transparent at all, use content
- process(rUniTransparenceCandidate.getChildren());
- }
- else if(rUniTransparenceCandidate.getTransparence() > 0.0 && rUniTransparenceCandidate.getTransparence() < 1.0)
- {
- // try to identify a single PolyPolygonColorPrimitive2D in the
- // content part of the transparence primitive
- const primitive2d::PolyPolygonColorPrimitive2D* pPoPoColor = nullptr;
- static bool bForceToMetafile(false);
-
- if(!bForceToMetafile && 1 == rContent.size())
- {
- const primitive2d::Primitive2DReference xReference(rContent[0]);
- pPoPoColor = dynamic_cast< const primitive2d::PolyPolygonColorPrimitive2D* >(xReference.get());
- }
-
- // PolyPolygonGradientPrimitive2D, PolyPolygonHatchPrimitive2D and
- // PolyPolygonGraphicPrimitive2D are derived from PolyPolygonColorPrimitive2D.
- // Check also for correct ID to exclude derived implementations
- if(pPoPoColor && PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D == pPoPoColor->getPrimitive2DID())
- {
- // single transparent tools::PolyPolygon identified, use directly
- const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(pPoPoColor->getBColor()));
- basegfx::B2DPolyPolygon aLocalPolyPolygon(pPoPoColor->getB2DPolyPolygon());
-
- // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
- // per polygon. Split polygon until there are less than that
- fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon);
-
- // now transform
- aLocalPolyPolygon.transform(maCurrentTransformation);
-
- // XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END support
- SvtGraphicFill* pSvtGraphicFill = nullptr;
-
- // #i121267# Not needed, does not give better quality compared with
- // the MetaActionType::POLYPOLYGON written by the DrawPolyPolygon command
- // below
- bool bSupportSvtGraphicFill(false);
-
- if(bSupportSvtGraphicFill && !mnSvtGraphicFillCount && aLocalPolyPolygon.count())
- {
- // setup simple color with transparence fill stuff like in impgrfll
- pSvtGraphicFill = new SvtGraphicFill(
- getFillPolyPolygon(aLocalPolyPolygon),
- Color(aPolygonColor),
- rUniTransparenceCandidate.getTransparence(),
- SvtGraphicFill::fillEvenOdd,
- SvtGraphicFill::fillSolid,
- SvtGraphicFill::Transform(),
- false,
- SvtGraphicFill::hatchSingle,
- Color(),
- SvtGraphicFill::GradientType::Linear,
- Color(),
- Color(),
- 0,
- Graphic());
- }
-
- // set line and fill color
- const sal_uInt16 nTransPercentVcl(static_cast<sal_uInt16>(basegfx::fround(rUniTransparenceCandidate.getTransparence() * 100.0)));
- mpOutputDevice->SetFillColor(Color(aPolygonColor));
- mpOutputDevice->SetLineColor();
-
- // call VCL directly; encapsulate with SvtGraphicFill
- if(bSupportSvtGraphicFill)
- {
- impStartSvtGraphicFill(pSvtGraphicFill);
- }
-
- mpOutputDevice->DrawTransparent(
- ::tools::PolyPolygon(aLocalPolyPolygon),
- nTransPercentVcl);
-
- if(bSupportSvtGraphicFill)
- {
- impEndSvtGraphicFill(pSvtGraphicFill);
- }
- }
- else
- {
- // save old mfCurrentUnifiedTransparence and set new one
- // so that contained SvtGraphicStroke may use the current one
- const double fLastCurrentUnifiedTransparence(mfCurrentUnifiedTransparence);
- // #i105377# paint the content metafile opaque as the transparency gets
- // split of into the gradient below
- // mfCurrentUnifiedTransparence = rUniTransparenceCandidate.getTransparence();
- mfCurrentUnifiedTransparence = 0;
-
- // various content, create content-metafile
- GDIMetaFile aContentMetafile;
- const ::tools::Rectangle aPrimitiveRectangle(impDumpToMetaFile(rContent, aContentMetafile));
-
- // restore mfCurrentUnifiedTransparence; it may have been used
- // while processing the sub-content in impDumpToMetaFile
- mfCurrentUnifiedTransparence = fLastCurrentUnifiedTransparence;
-
- // create uniform VCL gradient for uniform transparency
- Gradient aVCLGradient;
- const sal_uInt8 nTransPercentVcl(static_cast<sal_uInt8>(basegfx::fround(rUniTransparenceCandidate.getTransparence() * 255.0)));
- const Color aTransColor(nTransPercentVcl, nTransPercentVcl, nTransPercentVcl);
-
- aVCLGradient.SetStyle(GradientStyle::Linear);
- aVCLGradient.SetStartColor(aTransColor);
- aVCLGradient.SetEndColor(aTransColor);
- aVCLGradient.SetAngle(0);
- aVCLGradient.SetBorder(0);
- aVCLGradient.SetOfsX(0);
- aVCLGradient.SetOfsY(0);
- aVCLGradient.SetStartIntensity(100);
- aVCLGradient.SetEndIntensity(100);
- aVCLGradient.SetSteps(2);
-
- // render it to VCL
- mpOutputDevice->DrawTransparent(
- aContentMetafile, aPrimitiveRectangle.TopLeft(),
- aPrimitiveRectangle.GetSize(), aVCLGradient);
- }
- }
- }
-
- mpOutputDevice->Pop();
+ processUnifiedTransparencePrimitive2D(static_cast<const primitive2d::UnifiedTransparencePrimitive2D&>(rCandidate));
break;
}
case PRIMITIVE2D_ID_TRANSPARENCEPRIMITIVE2D :
{
- // for metafile: Need to examine what the pure vcl version is doing here actually
- // - uses DrawTransparent with metafile for content and a gradient
- // i can detect this here with checking the gradient part for a single
- // FillGradientPrimitive2D and reconstruct the gradient.
- // If that detection goes wrong, I have to create an transparence-blended bitmap. Eventually
- // do that in stripes, else RenderTransparencePrimitive2D may just be used
- const primitive2d::TransparencePrimitive2D& rTransparenceCandidate = static_cast< const primitive2d::TransparencePrimitive2D& >(rCandidate);
- const primitive2d::Primitive2DContainer& rContent = rTransparenceCandidate.getChildren();
- const primitive2d::Primitive2DContainer& rTransparence = rTransparenceCandidate.getTransparence();
-
- if(!rContent.empty() && !rTransparence.empty())
- {
- // try to identify a single FillGradientPrimitive2D in the
- // transparence part of the primitive
- const primitive2d::FillGradientPrimitive2D* pFiGradient = nullptr;
- static bool bForceToBigTransparentVDev(false);
-
- if(!bForceToBigTransparentVDev && 1 == rTransparence.size())
- {
- const primitive2d::Primitive2DReference xReference(rTransparence[0]);
- pFiGradient = dynamic_cast< const primitive2d::FillGradientPrimitive2D* >(xReference.get());
- }
-
- // Check also for correct ID to exclude derived implementations
- if(pFiGradient && PRIMITIVE2D_ID_FILLGRADIENTPRIMITIVE2D == pFiGradient->getPrimitive2DID())
- {
- // various content, create content-metafile
- GDIMetaFile aContentMetafile;
- const ::tools::Rectangle aPrimitiveRectangle(impDumpToMetaFile(rContent, aContentMetafile));
-
- // re-create a VCL-gradient from FillGradientPrimitive2D
- Gradient aVCLGradient;
- impConvertFillGradientAttributeToVCLGradient(aVCLGradient, pFiGradient->getFillGradient(), true);
-
- // render it to VCL
- mpOutputDevice->DrawTransparent(
- aContentMetafile, aPrimitiveRectangle.TopLeft(),
- aPrimitiveRectangle.GetSize(), aVCLGradient);
- }
- else
- {
- // sub-transparence group. Draw to VDev first.
- // this may get refined to tiling when resolution is too big here
-
- // need to avoid switching off MapMode stuff here; maybe need another
- // tooling class, cannot just do the same as with the pixel renderer.
- // Need to experiment...
-
- // Okay, basic implementation finished and tested. The DPI stuff was hard
- // and not easy to find out that it's needed.
- // Since this will not yet happen normally (as long as no one constructs
- // transparence primitives with non-trivial transparence content) i will for now not
- // refine to tiling here.
-
- basegfx::B2DRange aViewRange(rContent.getB2DRange(getViewInformation2D()));
- aViewRange.transform(maCurrentTransformation);
- const ::tools::Rectangle aRectLogic(
- static_cast<sal_Int32>(floor(aViewRange.getMinX())), static_cast<sal_Int32>(floor(aViewRange.getMinY())),
- static_cast<sal_Int32>(ceil(aViewRange.getMaxX())), static_cast<sal_Int32>(ceil(aViewRange.getMaxY())));
- const ::tools::Rectangle aRectPixel(mpOutputDevice->LogicToPixel(aRectLogic));
- Size aSizePixel(aRectPixel.GetSize());
- const Point aEmptyPoint;
- ScopedVclPtrInstance< VirtualDevice > aBufferDevice;
- const sal_uInt32 nMaxQuadratPixels(500000);
- const sal_uInt32 nViewVisibleArea(aSizePixel.getWidth() * aSizePixel.getHeight());
- double fReduceFactor(1.0);
-
- if(nViewVisibleArea > nMaxQuadratPixels)
- {
- // reduce render size
- fReduceFactor = sqrt(double(nMaxQuadratPixels) / static_cast<double>(nViewVisibleArea));
- aSizePixel = Size(basegfx::fround(static_cast<double>(aSizePixel.getWidth()) * fReduceFactor),
- basegfx::fround(static_cast<double>(aSizePixel.getHeight()) * fReduceFactor));
- }
-
- if(aBufferDevice->SetOutputSizePixel(aSizePixel))
- {
- // create and set MapModes for target devices
- MapMode aNewMapMode(mpOutputDevice->GetMapMode());
- aNewMapMode.SetOrigin(Point(-aRectLogic.Left(), -aRectLogic.Top()));
- aBufferDevice->SetMapMode(aNewMapMode);
-
- // prepare view transformation for target renderers
- // ATTENTION! Need to apply another scaling because of the potential DPI differences
- // between Printer and VDev (mpOutputDevice and aBufferDevice here).
- // To get the DPI, LogicToPixel from (1,1) from MapUnit::MapInch needs to be used.
- basegfx::B2DHomMatrix aViewTransform(aBufferDevice->GetViewTransformation());
- const Size aDPIOld(mpOutputDevice->LogicToPixel(Size(1, 1), MapMode(MapUnit::MapInch)));
- const Size aDPINew(aBufferDevice->LogicToPixel(Size(1, 1), MapMode(MapUnit::MapInch)));
- const double fDPIXChange(static_cast<double>(aDPIOld.getWidth()) / static_cast<double>(aDPINew.getWidth()));
- const double fDPIYChange(static_cast<double>(aDPIOld.getHeight()) / static_cast<double>(aDPINew.getHeight()));
-
- if(!basegfx::fTools::equal(fDPIXChange, 1.0) || !basegfx::fTools::equal(fDPIYChange, 1.0))
- {
- aViewTransform.scale(fDPIXChange, fDPIYChange);
- }
-
- // also take scaling from Size reduction into account
- if(!basegfx::fTools::equal(fReduceFactor, 1.0))
- {
- aViewTransform.scale(fReduceFactor, fReduceFactor);
- }
-
- // create view information and pixel renderer. Reuse known ViewInformation
- // except new transformation and range
- const geometry::ViewInformation2D aViewInfo(
- getViewInformation2D().getObjectTransformation(),
- aViewTransform,
- aViewRange,
- getViewInformation2D().getVisualizedPage(),
- getViewInformation2D().getViewTime(),
- getViewInformation2D().getExtendedInformationSequence());
-
- VclPixelProcessor2D aBufferProcessor(aViewInfo, *aBufferDevice.get());
-
- // draw content using pixel renderer
- aBufferProcessor.process(rContent);
- const Bitmap aBmContent(aBufferDevice->GetBitmap(aEmptyPoint, aSizePixel));
-
- // draw transparence using pixel renderer
- aBufferDevice->Erase();
- aBufferProcessor.process(rTransparence);
- const AlphaMask aBmAlpha(aBufferDevice->GetBitmap(aEmptyPoint, aSizePixel));
-
- // paint
- mpOutputDevice->DrawBitmapEx(
- aRectLogic.TopLeft(),
- aRectLogic.GetSize(),
- BitmapEx(aBmContent, aBmAlpha));
- }
- }
- }
-
+ processTransparencePrimitive2D(static_cast<const primitive2d::TransparencePrimitive2D&>(rCandidate));
break;
}
case PRIMITIVE2D_ID_TRANSFORMPRIMITIVE2D :
@@ -2088,26 +892,7 @@ namespace drawinglayer
}
case PRIMITIVE2D_ID_STRUCTURETAGPRIMITIVE2D :
{
- // structured tag primitive
- const primitive2d::StructureTagPrimitive2D& rStructureTagCandidate = static_cast< const primitive2d::StructureTagPrimitive2D& >(rCandidate);
- const vcl::PDFWriter::StructElement& rTagElement(rStructureTagCandidate.getStructureElement());
- const bool bTagUsed(vcl::PDFWriter::NonStructElement != rTagElement);
-
- if(mpPDFExtOutDevData && bTagUsed)
- {
- // write start tag
- mpPDFExtOutDevData->BeginStructureElement(rTagElement);
- }
-
- // process children normally
- process(rStructureTagCandidate.getChildren());
-
- if(mpPDFExtOutDevData && bTagUsed)
- {
- // write end tag
- mpPDFExtOutDevData->EndStructureElement();
- }
-
+ processStructureTagPrimitive2D(static_cast<const primitive2d::StructureTagPrimitive2D&>(rCandidate));
break;
}
case PRIMITIVE2D_ID_EPSPRIMITIVE2D :
@@ -2123,6 +908,1279 @@ namespace drawinglayer
}
}
}
+
+ void VclMetafileProcessor2D::processGraphicPrimitive2D(const primitive2d::GraphicPrimitive2D& rGraphicPrimitive)
+ {
+ bool bUsingPDFExtOutDevData(false);
+ basegfx::B2DVector aTranslate, aScale;
+ static bool bSuppressPDFExtOutDevDataSupport(false);
+
+ if(mpPDFExtOutDevData && !bSuppressPDFExtOutDevDataSupport)
+ {
+ // emulate data handling from UnoControlPDFExportContact, original see
+ // svtools/source/graphic/grfmgr.cxx
+ const Graphic& rGraphic = rGraphicPrimitive.getGraphicObject().GetGraphic();
+
+ if(rGraphic.IsGfxLink())
+ {
+ const GraphicAttr& rAttr = rGraphicPrimitive.getGraphicAttr();
+
+ if(!rAttr.IsSpecialDrawMode() && !rAttr.IsAdjusted())
+ {
+ const basegfx::B2DHomMatrix& rTransform = rGraphicPrimitive.getTransform();
+ double fRotate, fShearX;
+ rTransform.decompose(aScale, aTranslate, fRotate, fShearX);
+
+ if( basegfx::fTools::equalZero( fRotate ) && ( aScale.getX() > 0.0 ) && ( aScale.getY() > 0.0 ) )
+ {
+ bUsingPDFExtOutDevData = true;
+ mpPDFExtOutDevData->BeginGroup();
+ }
+ }
+ }
+ }
+
+ // process recursively and add MetaFile comment
+ process(rGraphicPrimitive);
+
+ if(bUsingPDFExtOutDevData)
+ {
+ // emulate data handling from UnoControlPDFExportContact, original see
+ // svtools/source/graphic/grfmgr.cxx
+ const basegfx::B2DRange aCurrentRange(
+ aTranslate.getX(), aTranslate.getY(),
+ aTranslate.getX() + aScale.getX(), aTranslate.getY() + aScale.getY());
+ const ::tools::Rectangle aCurrentRect(
+ sal_Int32(floor(aCurrentRange.getMinX())), sal_Int32(floor(aCurrentRange.getMinY())),
+ sal_Int32(ceil(aCurrentRange.getMaxX())), sal_Int32(ceil(aCurrentRange.getMaxY())));
+ const GraphicAttr& rAttr = rGraphicPrimitive.getGraphicAttr();
+ // fdo#72530 don't pass empty Rectangle to EndGroup
+ ::tools::Rectangle aCropRect(aCurrentRect);
+
+ if(rAttr.IsCropped())
+ {
+ // calculate scalings between real image size and logic object size. This
+ // is necessary since the crop values are relative to original bitmap size
+ double fFactorX(1.0);
+ double fFactorY(1.0);
+
+ {
+ const MapMode aMapMode100thmm(MapUnit::Map100thMM);
+ const Size aBitmapSize(OutputDevice::LogicToLogic(
+ rGraphicPrimitive.getGraphicObject().GetPrefSize(),
+ rGraphicPrimitive.getGraphicObject().GetPrefMapMode(), aMapMode100thmm));
+ const double fDivX(aBitmapSize.Width() - rAttr.GetLeftCrop() - rAttr.GetRightCrop());
+ const double fDivY(aBitmapSize.Height() - rAttr.GetTopCrop() - rAttr.GetBottomCrop());
+
+ if(!basegfx::fTools::equalZero(fDivX))
+ {
+ fFactorX = aScale.getX() / fDivX;
+ }
+
+ if(!basegfx::fTools::equalZero(fDivY))
+ {
+ fFactorY = aScale.getY() / fDivY;
+ }
+ }
+
+ // calculate crop range and rect
+ basegfx::B2DRange aCropRange;
+ aCropRange.expand(aCurrentRange.getMinimum() - basegfx::B2DPoint(rAttr.GetLeftCrop() * fFactorX, rAttr.GetTopCrop() * fFactorY));
+ aCropRange.expand(aCurrentRange.getMaximum() + basegfx::B2DPoint(rAttr.GetRightCrop() * fFactorX, rAttr.GetBottomCrop() * fFactorY));
+
+ aCropRect = ::tools::Rectangle(
+ sal_Int32(floor(aCropRange.getMinX())), sal_Int32(floor(aCropRange.getMinY())),
+ sal_Int32(ceil(aCropRange.getMaxX())), sal_Int32(ceil(aCropRange.getMaxY())));
+ }
+
+ // #i123295# 3rd param is uncropped rect, 4th is cropped. The primitive has the cropped
+ // object transformation, thus aCurrentRect *is* the clip region while aCropRect is the expanded,
+ // uncropped region. Thus, correct order is aCropRect, aCurrentRect
+ mpPDFExtOutDevData->EndGroup(rGraphicPrimitive.getGraphicObject().GetGraphic(),
+ rAttr.GetTransparency(),
+ aCropRect,
+ aCurrentRect);
+ }
+ }
+
+ void VclMetafileProcessor2D::processControlPrimitive2D(const primitive2d::ControlPrimitive2D& rControlPrimitive)
+ {
+ const uno::Reference< awt::XControl >& rXControl(rControlPrimitive.getXControl());
+ bool bIsPrintableControl(false);
+
+ // find out if control is printable
+ if(rXControl.is())
+ {
+ try
+ {
+ uno::Reference< beans::XPropertySet > xModelProperties(rXControl->getModel(), uno::UNO_QUERY);
+ uno::Reference< beans::XPropertySetInfo > xPropertyInfo(xModelProperties.is()
+ ? xModelProperties->getPropertySetInfo()
+ : uno::Reference< beans::XPropertySetInfo >());
+ const OUString sPrintablePropertyName("Printable");
+
+ if(xPropertyInfo.is() && xPropertyInfo->hasPropertyByName(sPrintablePropertyName))
+ {
+ OSL_VERIFY(xModelProperties->getPropertyValue(sPrintablePropertyName) >>= bIsPrintableControl);
+ }
+ }
+ catch(const uno::Exception&)
+ {
+ OSL_FAIL("VclMetafileProcessor2D: No access to printable flag of Control, caught an exception!");
+ }
+ }
+
+ // PDF export and printing only for printable controls
+ if(bIsPrintableControl)
+ {
+ const bool bPDFExport(mpPDFExtOutDevData && mpPDFExtOutDevData->GetIsExportFormFields());
+ bool bDoProcessRecursively(true);
+
+ if(bPDFExport)
+ {
+ // PDF export. Emulate data handling from UnoControlPDFExportContact
+ // I have now moved describePDFControl to toolkit, thus i can implement the PDF
+ // form control support now as follows
+ std::unique_ptr< vcl::PDFWriter::AnyWidget > pPDFControl(
+ ::toolkitform::describePDFControl( rXControl, *mpPDFExtOutDevData ) );
+
+ if(pPDFControl.get())
+ {
+ // still need to fill in the location (is a class Rectangle)
+ const basegfx::B2DRange aRangeLogic(rControlPrimitive.getB2DRange(getViewInformation2D()));
+ const ::tools::Rectangle aRectLogic(
+ static_cast<sal_Int32>(floor(aRangeLogic.getMinX())), static_cast<sal_Int32>(floor(aRangeLogic.getMinY())),
+ static_cast<sal_Int32>(ceil(aRangeLogic.getMaxX())), static_cast<sal_Int32>(ceil(aRangeLogic.getMaxY())));
+ pPDFControl->Location = aRectLogic;
+
+ Size aFontSize(pPDFControl->TextFont.GetFontSize());
+ aFontSize = OutputDevice::LogicToLogic(aFontSize, MapMode(MapUnit::MapPoint), mpOutputDevice->GetMapMode());
+ pPDFControl->TextFont.SetFontSize(aFontSize);
+
+ mpPDFExtOutDevData->BeginStructureElement(vcl::PDFWriter::Form);
+ mpPDFExtOutDevData->CreateControl(*pPDFControl.get());
+ mpPDFExtOutDevData->EndStructureElement();
+
+ // no normal paint needed (see original UnoControlPDFExportContact::do_PaintObject);
+ // do not process recursively
+ bDoProcessRecursively = false;
+ }
+ else
+ {
+ // PDF export did not work, try simple output.
+ // Fallback to printer output by not setting bDoProcessRecursively
+ // to false.
+ }
+ }
+
+ // #i93169# used flag the wrong way; true means that nothing was done yet
+ if(bDoProcessRecursively)
+ {
+ // printer output
+ 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 aObjectToDiscrete(getViewInformation2D().getObjectToViewTransformation() * rControlPrimitive.getTransform());
+ const basegfx::B2DPoint aTopLeftDiscrete(aObjectToDiscrete * basegfx::B2DPoint(0.0, 0.0));
+
+ // draw it
+ xControlView->draw(basegfx::fround(aTopLeftDiscrete.getX()), basegfx::fround(aTopLeftDiscrete.getY()));
+ bDoProcessRecursively = false;
+
+ // restore original graphics
+ xControlView->setGraphics(xOriginalGraphics);
+ }
+ }
+ catch( const uno::Exception& )
+ {
+ OSL_FAIL("VclMetafileProcessor2D: Printing of Control failed, caught an exception!");
+ }
+ }
+
+ // process recursively if not done yet to export as decomposition (bitmap)
+ if(bDoProcessRecursively)
+ {
+ process(rControlPrimitive);
+ }
+ }
+ }
+
+ void VclMetafileProcessor2D::processTextHierarchyFieldPrimitive2D(const primitive2d::TextHierarchyFieldPrimitive2D& rFieldPrimitive)
+ {
+ // support for FIELD_SEQ_BEGIN, FIELD_SEQ_END and URL. It wraps text primitives (but is not limited to)
+ // thus do the MetafileAction embedding stuff but just handle recursively.
+ const OString aCommentStringCommon("FIELD_SEQ_BEGIN");
+ const OString aCommentStringPage("FIELD_SEQ_BEGIN;PageField");
+ const OString aCommentStringEnd("FIELD_SEQ_END");
+ OUString aURL;
+
+ switch(rFieldPrimitive.getType())
+ {
+ default : // case drawinglayer::primitive2d::FIELD_TYPE_COMMON :
+ {
+ mpMetaFile->AddAction(new MetaCommentAction(aCommentStringCommon));
+ break;
+ }
+ case drawinglayer::primitive2d::FIELD_TYPE_PAGE :
+ {
+ mpMetaFile->AddAction(new MetaCommentAction(aCommentStringPage));
+ break;
+ }
+ case drawinglayer::primitive2d::FIELD_TYPE_URL :
+ {
+ aURL = rFieldPrimitive.getValue("URL");
+
+ if (!aURL.isEmpty())
+ {
+ mpMetaFile->AddAction(new MetaCommentAction(aCommentStringCommon, 0, reinterpret_cast<const sal_uInt8*>(aURL.getStr()), 2 * aURL.getLength()));
+ }
+
+ break;
+ }
+ }
+
+ // process recursively
+ primitive2d::Primitive2DContainer rContent;
+ rFieldPrimitive.get2DDecomposition(rContent, getViewInformation2D());
+ process(rContent);
+
+ // for the end comment the type is not relevant yet, they are all the same. Just add.
+ mpMetaFile->AddAction(new MetaCommentAction(aCommentStringEnd));
+
+ if(mpPDFExtOutDevData && drawinglayer::primitive2d::FIELD_TYPE_URL == rFieldPrimitive.getType())
+ {
+ // emulate data handling from ImpEditEngine::Paint
+ const basegfx::B2DRange aViewRange(rContent.getB2DRange(getViewInformation2D()));
+ const ::tools::Rectangle aRectLogic(
+ static_cast<sal_Int32>(floor(aViewRange.getMinX())), static_cast<sal_Int32>(floor(aViewRange.getMinY())),
+ static_cast<sal_Int32>(ceil(aViewRange.getMaxX())), static_cast<sal_Int32>(ceil(aViewRange.getMaxY())));
+ vcl::PDFExtOutDevBookmarkEntry aBookmark;
+ aBookmark.nLinkId = mpPDFExtOutDevData->CreateLink(aRectLogic);
+ aBookmark.aBookmark = aURL;
+ std::vector< vcl::PDFExtOutDevBookmarkEntry >& rBookmarks = mpPDFExtOutDevData->GetBookmarks();
+ rBookmarks.push_back( aBookmark );
+ }
+ }
+
+ void VclMetafileProcessor2D::processTextHierarchyLinePrimitive2D(const primitive2d::TextHierarchyLinePrimitive2D& rLinePrimitive)
+ {
+ const OString aCommentString("XTEXT_EOL");
+
+ // process recursively and add MetaFile comment
+ process(rLinePrimitive);
+ mpMetaFile->AddAction(new MetaCommentAction(aCommentString));
+ }
+
+ void VclMetafileProcessor2D::processTextHierarchyBulletPrimitive2D(const primitive2d::TextHierarchyBulletPrimitive2D& rBulletPrimitive)
+ {
+ // in Outliner::PaintBullet(), a MetafileComment for bullets is added, too. The
+ // "XTEXT_EOC" is used, use here, too.
+ const OString aCommentString("XTEXT_EOC");
+
+ // process recursively and add MetaFile comment
+ process(rBulletPrimitive);
+ mpMetaFile->AddAction(new MetaCommentAction(aCommentString));
+ }
+
+ void VclMetafileProcessor2D::processTextHierarchyParagraphPrimitive2D(const primitive2d::TextHierarchyParagraphPrimitive2D& rParagraphPrimitive)
+ {
+ const OString aCommentString("XTEXT_EOP");
+
+ if(mpPDFExtOutDevData)
+ {
+ // emulate data handling from ImpEditEngine::Paint
+ mpPDFExtOutDevData->BeginStructureElement( vcl::PDFWriter::Paragraph );
+ }
+
+ // process recursively and add MetaFile comment
+ process(rParagraphPrimitive);
+ mpMetaFile->AddAction(new MetaCommentAction(aCommentString));
+
+ if(mpPDFExtOutDevData)
+ {
+ // emulate data handling from ImpEditEngine::Paint
+ mpPDFExtOutDevData->EndStructureElement();
+ }
+ }
+
+ void VclMetafileProcessor2D::processTextHierarchyBlockPrimitive2D(const primitive2d::TextHierarchyBlockPrimitive2D& rBlockPrimitive)
+ {
+ const OString aCommentStringA("XTEXT_PAINTSHAPE_BEGIN");
+ const OString aCommentStringB("XTEXT_PAINTSHAPE_END");
+
+ // add MetaFile comment, process recursively and add MetaFile comment
+ mpMetaFile->AddAction(new MetaCommentAction(aCommentStringA));
+ process(rBlockPrimitive);
+ mpMetaFile->AddAction(new MetaCommentAction(aCommentStringB));
+ }
+
+ void VclMetafileProcessor2D::processTextSimplePortionPrimitive2D(const primitive2d::TextSimplePortionPrimitive2D& rTextCandidate)
+ {
+ // Adapt evtl. used special DrawMode
+ const DrawModeFlags nOriginalDrawMode(mpOutputDevice->GetDrawMode());
+ adaptTextToFillDrawMode();
+
+ // directdraw of text simple portion; use default processing
+ RenderTextSimpleOrDecoratedPortionPrimitive2D(rTextCandidate);
+
+ // restore DrawMode
+ mpOutputDevice->SetDrawMode(nOriginalDrawMode);
+
+ // #i101169# if(pTextDecoratedCandidate)
+ {
+ // support for TEXT_ MetaFile actions only for decorated texts
+ if(!mxBreakIterator.is())
+ {
+ uno::Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
+ mxBreakIterator = i18n::BreakIterator::create(xContext);
+ }
+
+ const OUString& rTxt = rTextCandidate.getText();
+ const sal_Int32 nTextLength(rTextCandidate.getTextLength()); // rTxt.getLength());
+
... etc. - the rest is truncated
More information about the Libreoffice-commits
mailing list