summaryrefslogtreecommitdiff
path: root/drawinglayer
diff options
context:
space:
mode:
authorCaolán McNamara <caolanm@redhat.com>2018-07-31 14:20:52 +0100
committerCaolán McNamara <caolanm@redhat.com>2018-07-31 18:18:36 +0200
commit2a4b054b3685aaeca5bdcb2969bcfc25365421d9 (patch)
tree19dd2dfea163744e10395065898860236638f839 /drawinglayer
parent4f13f8ddeebca1de9fd30f0aae71e3f84383656a (diff)
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@redhat.com> Tested-by: Caolán McNamara <caolanm@redhat.com>
Diffstat (limited to 'drawinglayer')
-rw-r--r--drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx2434
-rw-r--r--drawinglayer/source/processor2d/vclmetafileprocessor2d.hxx42
2 files changed, 1288 insertions, 1188 deletions
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,1368 +761,1426 @@ 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);
+ processGraphicPrimitive2D(static_cast<const primitive2d::GraphicPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_CONTROLPRIMITIVE2D :
+ {
+ processControlPrimitive2D(static_cast<const primitive2d::ControlPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_TEXTHIERARCHYFIELDPRIMITIVE2D :
+ {
+ processTextHierarchyFieldPrimitive2D(static_cast<const primitive2d::TextHierarchyFieldPrimitive2D& >(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_TEXTHIERARCHYLINEPRIMITIVE2D :
+ {
+ processTextHierarchyLinePrimitive2D(static_cast<const primitive2d::TextHierarchyLinePrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_TEXTHIERARCHYBULLETPRIMITIVE2D :
+ {
+ processTextHierarchyBulletPrimitive2D(static_cast<const primitive2d::TextHierarchyBulletPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_TEXTHIERARCHYPARAGRAPHPRIMITIVE2D :
+ {
+ processTextHierarchyParagraphPrimitive2D(static_cast<const primitive2d::TextHierarchyParagraphPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_TEXTHIERARCHYBLOCKPRIMITIVE2D :
+ {
+ 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
+ processTextSimplePortionPrimitive2D(static_cast<const primitive2d::TextSimplePortionPrimitive2D& >(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D :
+ {
+ processPolygonHairlinePrimitive2D(static_cast<const primitive2d::PolygonHairlinePrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D :
+ {
+ processPolygonStrokePrimitive2D(static_cast<const primitive2d::PolygonStrokePrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYGONSTROKEARROWPRIMITIVE2D :
+ {
+ processPolygonStrokeArrowPrimitive2D(static_cast<const primitive2d::PolygonStrokeArrowPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_BITMAPPRIMITIVE2D :
+ {
+ // direct draw of transformed BitmapEx primitive; use default processing, but without
+ // former testing if graphic content is inside discrete local viewport; this is not
+ // setup for metafile targets (metafile renderer tries to render in logic coordinates,
+ // the mapping is kept to the OutputDevice for better Metafile recording)
+ RenderBitmapPrimitive2D(static_cast< const primitive2d::BitmapPrimitive2D& >(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYPOLYGONGRAPHICPRIMITIVE2D :
+ {
+ processPolyPolygonGraphicPrimitive2D(static_cast<const primitive2d::PolyPolygonGraphicPrimitive2D& >(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYPOLYGONHATCHPRIMITIVE2D :
+ {
+ processPolyPolygonHatchPrimitive2D(static_cast<const primitive2d::PolyPolygonHatchPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D :
+ {
+ processPolyPolygonGradientPrimitive2D(static_cast<const primitive2d::PolyPolygonGradientPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D :
+ {
+ processPolyPolygonColorPrimitive2D(static_cast<const primitive2d::PolyPolygonColorPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_MASKPRIMITIVE2D :
+ {
+ processMaskPrimitive2D(static_cast<const primitive2d::MaskPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_MODIFIEDCOLORPRIMITIVE2D :
+ {
+ // modified color group. Force output to unified color. Use default pocessing.
+ RenderModifiedColorPrimitive2D(static_cast< const primitive2d::ModifiedColorPrimitive2D& >(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_UNIFIEDTRANSPARENCEPRIMITIVE2D :
+ {
+ processUnifiedTransparencePrimitive2D(static_cast<const primitive2d::UnifiedTransparencePrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_TRANSPARENCEPRIMITIVE2D :
+ {
+ processTransparencePrimitive2D(static_cast<const primitive2d::TransparencePrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_TRANSFORMPRIMITIVE2D :
+ {
+ // use default transform group pocessing
+ RenderTransformPrimitive2D(static_cast< const primitive2d::TransformPrimitive2D& >(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_PAGEPREVIEWPRIMITIVE2D :
+ {
+ // new XDrawPage for ViewInformation2D
+ RenderPagePreviewPrimitive2D(static_cast< const primitive2d::PagePreviewPrimitive2D& >(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_MARKERARRAYPRIMITIVE2D :
+ {
+ // use default marker array pocessing
+ RenderMarkerArrayPrimitive2D(static_cast< const primitive2d::MarkerArrayPrimitive2D& >(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_POINTARRAYPRIMITIVE2D :
+ {
+ // use default point array pocessing
+ RenderPointArrayPrimitive2D(static_cast< const primitive2d::PointArrayPrimitive2D& >(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_STRUCTURETAGPRIMITIVE2D :
+ {
+ processStructureTagPrimitive2D(static_cast<const primitive2d::StructureTagPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_EPSPRIMITIVE2D :
+ {
+ RenderEpsPrimitive2D(static_cast< const primitive2d::EpsPrimitive2D& >(rCandidate));
+ break;
+ }
+ default :
+ {
+ // process recursively
+ process(rCandidate);
+ break;
+ }
+ }
+ }
- if(mpPDFExtOutDevData && !bSuppressPDFExtOutDevDataSupport)
+ 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())
{
- // emulate data handling from UnoControlPDFExportContact, original see
- // svtools/source/graphic/grfmgr.cxx
- const Graphic& rGraphic = rGraphicPrimitive.getGraphicObject().GetGraphic();
+ const basegfx::B2DHomMatrix& rTransform = rGraphicPrimitive.getTransform();
+ double fRotate, fShearX;
+ rTransform.decompose(aScale, aTranslate, fRotate, fShearX);
- if(rGraphic.IsGfxLink())
+ if( basegfx::fTools::equalZero( fRotate ) && ( aScale.getX() > 0.0 ) && ( aScale.getY() > 0.0 ) )
{
- 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();
- }
- }
+ bUsingPDFExtOutDevData = true;
+ mpPDFExtOutDevData->BeginGroup();
}
}
+ }
+ }
+
+ // process recursively and add MetaFile comment
+ process(rGraphicPrimitive);
- // 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);
- 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())
+ 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))
{
- // 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())));
+ fFactorX = aScale.getX() / fDivX;
}
- // #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);
+ if(!basegfx::fTools::equalZero(fDivY))
+ {
+ fFactorY = aScale.getY() / fDivY;
+ }
}
- break;
+ // 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())));
}
- case PRIMITIVE2D_ID_CONTROLPRIMITIVE2D :
+
+ // #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
{
- const primitive2d::ControlPrimitive2D& rControlPrimitive = static_cast< const primitive2d::ControlPrimitive2D& >(rCandidate);
- const uno::Reference< awt::XControl >& rXControl(rControlPrimitive.getXControl());
- bool bIsPrintableControl(false);
+ 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");
- // find out if control is printable
- if(rXControl.is())
+ if(xPropertyInfo.is() && xPropertyInfo->hasPropertyByName(sPrintablePropertyName))
{
- 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!");
- }
+ 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)
+ // 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())
{
- const bool bPDFExport(mpPDFExtOutDevData && mpPDFExtOutDevData->GetIsExportFormFields());
- bool bDoProcessRecursively(true);
+ // 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;
- 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.
- }
- }
+ Size aFontSize(pPDFControl->TextFont.GetFontSize());
+ aFontSize = OutputDevice::LogicToLogic(aFontSize, MapMode(MapUnit::MapPoint), mpOutputDevice->GetMapMode());
+ pPDFControl->TextFont.SetFontSize(aFontSize);
- // #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!");
- }
- }
+ mpPDFExtOutDevData->BeginStructureElement(vcl::PDFWriter::Form);
+ mpPDFExtOutDevData->CreateControl(*pPDFControl.get());
+ mpPDFExtOutDevData->EndStructureElement();
- // process recursively if not done yet to export as decomposition (bitmap)
- if(bDoProcessRecursively)
- {
- process(rControlPrimitive);
- }
+ // 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.
}
-
- 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())
+ // #i93169# used flag the wrong way; true means that nothing was done yet
+ if(bDoProcessRecursively)
+ {
+ // printer output
+ try
{
- 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 :
+ // 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())
{
- aURL = rFieldPrimitive.getValue("URL");
+ // link graphics and view
+ xControlView->setGraphics(xNewGraphics);
- if (!aURL.isEmpty())
- {
- mpMetaFile->AddAction(new MetaCommentAction(aCommentStringCommon, 0, reinterpret_cast<const sal_uInt8*>(aURL.getStr()), 2 * aURL.getLength()));
- }
+ // get position
+ const basegfx::B2DHomMatrix aObjectToDiscrete(getViewInformation2D().getObjectToViewTransformation() * rControlPrimitive.getTransform());
+ const basegfx::B2DPoint aTopLeftDiscrete(aObjectToDiscrete * basegfx::B2DPoint(0.0, 0.0));
- break;
+ // draw it
+ xControlView->draw(basegfx::fround(aTopLeftDiscrete.getX()), basegfx::fround(aTopLeftDiscrete.getY()));
+ bDoProcessRecursively = false;
+
+ // restore original graphics
+ xControlView->setGraphics(xOriginalGraphics);
}
}
-
- // 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())
+ catch( const uno::Exception& )
{
- // 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 );
+ OSL_FAIL("VclMetafileProcessor2D: Printing of Control failed, caught an exception!");
}
-
- 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));
+ // 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 PRIMITIVE2D_ID_TEXTHIERARCHYBULLETPRIMITIVE2D :
+ case drawinglayer::primitive2d::FIELD_TYPE_PAGE :
{
- // 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));
-
+ mpMetaFile->AddAction(new MetaCommentAction(aCommentStringPage));
break;
}
- case PRIMITIVE2D_ID_TEXTHIERARCHYPARAGRAPHPRIMITIVE2D :
+ case drawinglayer::primitive2d::FIELD_TYPE_URL :
{
- 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 );
- }
+ aURL = rFieldPrimitive.getValue("URL");
- // process recursively and add MetaFile comment
- process(rParagraphPrimitive);
- mpMetaFile->AddAction(new MetaCommentAction(aCommentString));
-
- if(mpPDFExtOutDevData)
+ if (!aURL.isEmpty())
{
- // emulate data handling from ImpEditEngine::Paint
- mpPDFExtOutDevData->EndStructureElement();
+ mpMetaFile->AddAction(new MetaCommentAction(aCommentStringCommon, 0, reinterpret_cast<const sal_uInt8*>(aURL.getStr()), 2 * aURL.getLength()));
}
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));
+ // process recursively
+ primitive2d::Primitive2DContainer rContent;
+ rFieldPrimitive.get2DDecomposition(rContent, getViewInformation2D());
+ process(rContent);
- 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);
+ // for the end comment the type is not relevant yet, they are all the same. Just add.
+ mpMetaFile->AddAction(new MetaCommentAction(aCommentStringEnd));
- // Adapt evtl. used special DrawMode
- const DrawModeFlags nOriginalDrawMode(mpOutputDevice->GetDrawMode());
- adaptTextToFillDrawMode();
+ 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 );
+ }
+ }
- // directdraw of text simple portion; use default processing
- RenderTextSimpleOrDecoratedPortionPrimitive2D(rTextCandidate);
+ void VclMetafileProcessor2D::processTextHierarchyLinePrimitive2D(const primitive2d::TextHierarchyLinePrimitive2D& rLinePrimitive)
+ {
+ const OString aCommentString("XTEXT_EOL");
- // restore DrawMode
- mpOutputDevice->SetDrawMode(nOriginalDrawMode);
+ // process recursively and add MetaFile comment
+ process(rLinePrimitive);
+ mpMetaFile->AddAction(new MetaCommentAction(aCommentString));
+ }
- // #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);
- }
+ 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");
- const OUString& rTxt = rTextCandidate.getText();
- const sal_Int32 nTextLength(rTextCandidate.getTextLength()); // rTxt.getLength());
+ // process recursively and add MetaFile comment
+ process(rBulletPrimitive);
+ mpMetaFile->AddAction(new MetaCommentAction(aCommentString));
+ }
- 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);
- }
- }
- }
- }
+ void VclMetafileProcessor2D::processTextHierarchyParagraphPrimitive2D(const primitive2d::TextHierarchyParagraphPrimitive2D& rParagraphPrimitive)
+ {
+ const OString aCommentString("XTEXT_EOP");
- break;
- }
- case PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D :
- {
- const primitive2d::PolygonHairlinePrimitive2D& rHairlinePrimitive = static_cast< const primitive2d::PolygonHairlinePrimitive2D& >(rCandidate);
- const basegfx::B2DPolygon& rBasePolygon = rHairlinePrimitive.getB2DPolygon();
+ if(mpPDFExtOutDevData)
+ {
+ // emulate data handling from ImpEditEngine::Paint
+ mpPDFExtOutDevData->BeginStructureElement( vcl::PDFWriter::Paragraph );
+ }
- 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;
+ // process recursively and add MetaFile comment
+ process(rParagraphPrimitive);
+ mpMetaFile->AddAction(new MetaCommentAction(aCommentString));
- // #i121267# Not needed, does not give better quality compared with
- // the MetaActionType::POLYPOLYGON written by RenderPolygonHairlinePrimitive2D
- // below
- bool bSupportSvtGraphicStroke(false);
+ if(mpPDFExtOutDevData)
+ {
+ // emulate data handling from ImpEditEngine::Paint
+ mpPDFExtOutDevData->EndStructureElement();
+ }
+ }
- if(bSupportSvtGraphicStroke)
- {
- pSvtGraphicStroke = impTryToCreateSvtGraphicStroke(
- rHairlinePrimitive.getB2DPolygon(),
- &aLineColor,
- nullptr, nullptr, nullptr, nullptr);
+ void VclMetafileProcessor2D::processTextHierarchyBlockPrimitive2D(const primitive2d::TextHierarchyBlockPrimitive2D& rBlockPrimitive)
+ {
+ const OString aCommentStringA("XTEXT_PAINTSHAPE_BEGIN");
+ const OString aCommentStringB("XTEXT_PAINTSHAPE_END");
- impStartSvtGraphicStroke(pSvtGraphicStroke);
- }
+ // add MetaFile comment, process recursively and add MetaFile comment
+ mpMetaFile->AddAction(new MetaCommentAction(aCommentStringA));
+ process(rBlockPrimitive);
+ mpMetaFile->AddAction(new MetaCommentAction(aCommentStringB));
+ }
- RenderPolygonHairlinePrimitive2D(static_cast< const primitive2d::PolygonHairlinePrimitive2D& >(rCandidate), false);
+ void VclMetafileProcessor2D::processTextSimplePortionPrimitive2D(const primitive2d::TextSimplePortionPrimitive2D& rTextCandidate)
+ {
+ // Adapt evtl. used special DrawMode
+ const DrawModeFlags nOriginalDrawMode(mpOutputDevice->GetDrawMode());
+ adaptTextToFillDrawMode();
- if(bSupportSvtGraphicStroke)
- {
- impEndSvtGraphicStroke(pSvtGraphicStroke);
- }
- }
- break;
- }
- case PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D :
- {
- const primitive2d::PolygonStrokePrimitive2D& rStrokePrimitive = static_cast< const primitive2d::PolygonStrokePrimitive2D& >(rCandidate);
- const basegfx::B2DPolygon& rBasePolygon = rStrokePrimitive.getB2DPolygon();
+ // directdraw of text simple portion; use default processing
+ RenderTextSimpleOrDecoratedPortionPrimitive2D(rTextCandidate);
- 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);
+ // restore DrawMode
+ mpOutputDevice->SetDrawMode(nOriginalDrawMode);
- // support SvtGraphicStroke MetaCommentAction
- SvtGraphicStroke* pSvtGraphicStroke = impTryToCreateSvtGraphicStroke(
- rBasePolygon, nullptr,
- &rStrokePrimitive.getLineAttribute(),
- &rStrokePrimitive.getStrokeAttribute(),
- nullptr, nullptr);
+ // #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);
+ }
- impStartSvtGraphicStroke(pSvtGraphicStroke);
- const attribute::LineAttribute& rLine = rStrokePrimitive.getLineAttribute();
+ const OUString& rTxt = rTextCandidate.getText();
+ const sal_Int32 nTextLength(rTextCandidate.getTextLength()); // rTxt.getLength());
- // create MetaPolyLineActions, but without LineStyle::Dash
- if(basegfx::fTools::more(rLine.getWidth(), 0.0))
+ 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)
{
- 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));
- }
- }
+ mpMetaFile->AddAction(new MetaCommentAction(aCommentStringB, i - nTextPosition));
+ nNextWordBoundary = mxBreakIterator->getWordBoundary(rTxt, i + 1, rLocale, css::i18n::WordType::ANY_WORD, true);
}
- else
+ if(i == nNextSentenceBreak)
{
- process(rCandidate);
+ mpMetaFile->AddAction(new MetaCommentAction(aCommentStringC, i - nTextPosition));
+ nNextSentenceBreak = mxBreakIterator->endOfSentence(rTxt, i + 1, rLocale);
}
+ }
+ }
+ }
+ }
- impEndSvtGraphicStroke(pSvtGraphicStroke);
+ void VclMetafileProcessor2D::processPolygonHairlinePrimitive2D(const primitive2d::PolygonHairlinePrimitive2D& rHairlinePrimitive)
+ {
+ const basegfx::B2DPolygon& rBasePolygon = rHairlinePrimitive.getB2DPolygon();
- mpOutputDevice->Pop();
- }
+ 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;
- break;
+ // #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);
}
- case PRIMITIVE2D_ID_POLYGONSTROKEARROWPRIMITIVE2D :
+
+ RenderPolygonHairlinePrimitive2D(rHairlinePrimitive, false);
+
+ if(bSupportSvtGraphicStroke)
+ {
+ impEndSvtGraphicStroke(pSvtGraphicStroke);
+ }
+ }
+ }
+
+ void VclMetafileProcessor2D::processPolygonStrokePrimitive2D(const primitive2d::PolygonStrokePrimitive2D& rStrokePrimitive)
+ {
+ 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 primitive2d::PolygonStrokeArrowPrimitive2D& rStrokeArrowPrimitive = static_cast< const primitive2d::PolygonStrokeArrowPrimitive2D& >(rCandidate);
- const basegfx::B2DPolygon& rBasePolygon = rStrokeArrowPrimitive.getB2DPolygon();
+ const attribute::StrokeAttribute& rStroke = rStrokePrimitive.getStrokeAttribute();
+ basegfx::B2DPolyPolygon aHairLinePolyPolygon;
- if(rBasePolygon.count() > (MAX_POLYGON_POINT_COUNT_METAFILE - 1))
+ if(0.0 == rStroke.getFullDotDashLen())
{
- // #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());
+ aHairLinePolyPolygon.append(rBasePolygon);
}
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);
- }
+ basegfx::utils::applyLineDashing(
+ rBasePolygon, rStroke.getDotDashArray(),
+ &aHairLinePolyPolygon, nullptr, rStroke.getFullDotDashLen());
+ }
- // process sub-line geometry (evtl. filled PolyPolygons)
- process(rCandidate);
+ const basegfx::BColor aHairlineColor(maBColorModifierStack.getModifiedColor(rLine.getColor()));
+ mpOutputDevice->SetLineColor(Color(aHairlineColor));
+ mpOutputDevice->SetFillColor();
+ aHairLinePolyPolygon.transform(maCurrentTransformation);
- if(bDrawmodeChange)
+ // 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)
{
- mpOutputDevice->SetDrawMode(nOldDrawMode);
- }
+ const ::tools::Polygon aToolsPolygon(aCandidate);
- // write LineGeometry end marker
- impEndSvtGraphicStroke(pSvtGraphicStroke);
+ mpMetaFile->AddAction(new MetaPolyLineAction(aToolsPolygon, aLineInfo));
+ }
}
-
- break;
}
- case PRIMITIVE2D_ID_BITMAPPRIMITIVE2D :
+ else
{
- // direct draw of transformed BitmapEx primitive; use default processing, but without
- // former testing if graphic content is inside discrete local viewport; this is not
- // setup for metafile targets (metafile renderer tries to render in logic coordinates,
- // the mapping is kept to the OutputDevice for better Metafile recording)
- RenderBitmapPrimitive2D(static_cast< const primitive2d::BitmapPrimitive2D& >(rCandidate));
- break;
+ process(rStrokePrimitive);
}
- 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);
+ impEndSvtGraphicStroke(pSvtGraphicStroke);
- SvtGraphicFill* pSvtGraphicFill = nullptr;
+ mpOutputDevice->Pop();
+ }
+ }
- if(!mnSvtGraphicFillCount && aLocalPolyPolygon.count())
- {
- // #121194# Changed implementation and checked usages fo convert to metafile,
- // presentation start (uses SvtGraphicFill) and printing.
+ void VclMetafileProcessor2D::processPolygonStrokeArrowPrimitive2D(const primitive2d::PolygonStrokeArrowPrimitive2D& rStrokeArrowPrimitive)
+ {
+ const basegfx::B2DPolygon& rBasePolygon = rStrokeArrowPrimitive.getB2DPolygon();
- // 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());
- }
+ 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);
+ }
- // Do use decomposition; encapsulate with SvtGraphicFill
- impStartSvtGraphicFill(pSvtGraphicFill);
- process(rCandidate);
- impEndSvtGraphicFill(pSvtGraphicFill);
+ // process sub-line geometry (evtl. filled PolyPolygons)
+ process(rStrokeArrowPrimitive);
- break;
- }
- case PRIMITIVE2D_ID_POLYPOLYGONHATCHPRIMITIVE2D :
+ if(bDrawmodeChange)
{
- // 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;
- }
+ mpOutputDevice->SetDrawMode(nOldDrawMode);
+ }
- // #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);
+ // write LineGeometry end marker
+ impEndSvtGraphicStroke(pSvtGraphicStroke);
+ }
+ }
- 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 });
- }
+ void VclMetafileProcessor2D::processPolyPolygonGraphicPrimitive2D(const primitive2d::PolyPolygonGraphicPrimitive2D& rBitmapCandidate)
+ {
+ // need to handle PolyPolygonGraphicPrimitive2D here to support XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END
+ basegfx::B2DPolyPolygon aLocalPolyPolygon(rBitmapCandidate.getB2DPolyPolygon());
- SvtGraphicFill* pSvtGraphicFill = nullptr;
- aLocalPolyPolygon.transform(maCurrentTransformation);
+ fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon);
- if(!mnSvtGraphicFillCount && aLocalPolyPolygon.count())
- {
- // re-create a VCL hatch as base data
- SvtGraphicFill::HatchType eHatch(SvtGraphicFill::hatchSingle);
+ SvtGraphicFill* pSvtGraphicFill = nullptr;
- 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;
- }
- }
+ 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());
+ }
- 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);
+ process(rBitmapCandidate);
+ impEndSvtGraphicFill(pSvtGraphicFill);
+ }
- // Do use decomposition; encapsulate with SvtGraphicFill
- impStartSvtGraphicFill(pSvtGraphicFill);
+ void VclMetafileProcessor2D::processPolyPolygonHatchPrimitive2D(const primitive2d::PolyPolygonHatchPrimitive2D& rHatchCandidate)
+ {
+ // need to handle PolyPolygonHatchPrimitive2D here to support XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END
+ const attribute::FillHatchAttribute& rFillHatchAttribute = rHatchCandidate.getFillHatch();
+ basegfx::B2DPolyPolygon aLocalPolyPolygon(rHatchCandidate.getB2DPolyPolygon());
- // #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);
+ 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(rHatchCandidate);
+ return;
+ }
- mpOutputDevice->DrawHatch(aToolsPolyPolygon,
- Hatch(aHatchStyle,
- Color(rFillHatchAttribute.getColor()),
- basegfx::fround(rFillHatchAttribute.getDistance()),
- basegfx::fround(rFillHatchAttribute.getAngle() / F_PI1800)));
+ // #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);
- impEndSvtGraphicFill(pSvtGraphicFill);
+ 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 });
+ }
- break;
- }
- case PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D :
- {
- basegfx::B2DVector aScale, aTranslate;
- double fRotate, fShearX;
+ SvtGraphicFill* pSvtGraphicFill = nullptr;
+ aLocalPolyPolygon.transform(maCurrentTransformation);
- maCurrentTransformation.decompose(aScale, aTranslate, fRotate, fShearX);
+ if(!mnSvtGraphicFillCount && aLocalPolyPolygon.count())
+ {
+ // re-create a VCL hatch as base data
+ SvtGraphicFill::HatchType eHatch(SvtGraphicFill::hatchSingle);
- if(!basegfx::fTools::equalZero(fRotate) || !basegfx::fTools::equalZero(fShearX))
+ switch(rFillHatchAttribute.getStyle())
+ {
+ default: // attribute::HatchStyle::Single :
{
- // #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);
+ eHatch = SvtGraphicFill::hatchSingle;
break;
}
-
- const primitive2d::PolyPolygonGradientPrimitive2D& rGradientCandidate = static_cast< const primitive2d::PolyPolygonGradientPrimitive2D& >(rCandidate);
- basegfx::B2DPolyPolygon aLocalPolyPolygon(rGradientCandidate.getB2DPolyPolygon());
-
- if(aLocalPolyPolygon.getB2DRange() != rGradientCandidate.getDefinitionRange())
+ case attribute::HatchStyle::Double :
{
- // 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);
+ eHatch = SvtGraphicFill::hatchDouble;
break;
}
+ case attribute::HatchStyle::Triple :
+ {
+ eHatch = SvtGraphicFill::hatchTriple;
+ 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);
+ 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());
+ }
- // 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);
+ // Do use decomposition; encapsulate with SvtGraphicFill
+ impStartSvtGraphicFill(pSvtGraphicFill);
- // #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)));
+ // #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)));
- // XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END support
- SvtGraphicFill* pSvtGraphicFill = nullptr;
+ impEndSvtGraphicFill(pSvtGraphicFill);
+ }
- 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());
- }
+ void VclMetafileProcessor2D::processPolyPolygonGradientPrimitive2D(const primitive2d::PolyPolygonGradientPrimitive2D& rGradientCandidate)
+ {
+ basegfx::B2DVector aScale, aTranslate;
+ double fRotate, fShearX;
- // call VCL directly; encapsulate with SvtGraphicFill
- impStartSvtGraphicFill(pSvtGraphicFill);
- mpOutputDevice->DrawGradient(aToolsPolyPolygon, aVCLGradient);
- impEndSvtGraphicFill(pSvtGraphicFill);
+ maCurrentTransformation.decompose(aScale, aTranslate, fRotate, fShearX);
- break;
- }
- case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D :
+ 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(rGradientCandidate);
+ return;
+ }
+
+ 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(rGradientCandidate);
+ return;
+ }
+
+ // #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())
{
- mpOutputDevice->Push(PushFlags::LINECOLOR | PushFlags::FILLCOLOR);
- const primitive2d::PolyPolygonColorPrimitive2D& rPolygonCandidate(static_cast< const primitive2d::PolyPolygonColorPrimitive2D& >(rCandidate));
- basegfx::B2DPolyPolygon aLocalPolyPolygon(rPolygonCandidate.getB2DPolyPolygon());
+ 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;
+ }
- // #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);
+ 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());
+ }
- const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(rPolygonCandidate.getBColor()));
- aLocalPolyPolygon.transform(maCurrentTransformation);
+ // call VCL directly; encapsulate with SvtGraphicFill
+ impStartSvtGraphicFill(pSvtGraphicFill);
+ mpOutputDevice->DrawGradient(aToolsPolyPolygon, aVCLGradient);
+ impEndSvtGraphicFill(pSvtGraphicFill);
+ }
- // XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END support
- SvtGraphicFill* pSvtGraphicFill = nullptr;
+ void VclMetafileProcessor2D::processPolyPolygonColorPrimitive2D(const primitive2d::PolyPolygonColorPrimitive2D& rPolygonCandidate)
+ {
+ mpOutputDevice->Push(PushFlags::LINECOLOR | PushFlags::FILLCOLOR);
+ basegfx::B2DPolyPolygon aLocalPolyPolygon(rPolygonCandidate.getB2DPolyPolygon());
- // #i121267# Not needed, does not give better quality compared with
- // the MetaActionType::POLYPOLYGON written by the DrawPolyPolygon command
- // below
- bool bSupportSvtGraphicFill(false);
+ // #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(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());
- }
+ const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(rPolygonCandidate.getBColor()));
+ aLocalPolyPolygon.transform(maCurrentTransformation);
- // set line and fill color
- mpOutputDevice->SetFillColor(Color(aPolygonColor));
- mpOutputDevice->SetLineColor();
+ // XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END support
+ SvtGraphicFill* pSvtGraphicFill = nullptr;
- // call VCL directly; encapsulate with SvtGraphicFill
- if(bSupportSvtGraphicFill)
- {
- impStartSvtGraphicFill(pSvtGraphicFill);
- }
+ // #i121267# Not needed, does not give better quality compared with
+ // the MetaActionType::POLYPOLYGON written by the DrawPolyPolygon command
+ // below
+ bool bSupportSvtGraphicFill(false);
- mpOutputDevice->DrawPolyPolygon(aLocalPolyPolygon);
+ 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());
+ }
- if(bSupportSvtGraphicFill)
- {
- impEndSvtGraphicFill(pSvtGraphicFill);
- }
+ // set line and fill color
+ mpOutputDevice->SetFillColor(Color(aPolygonColor));
+ mpOutputDevice->SetLineColor();
- mpOutputDevice->Pop();
- break;
- }
- case PRIMITIVE2D_ID_MASKPRIMITIVE2D :
+ // call VCL directly; encapsulate with SvtGraphicFill
+ if(bSupportSvtGraphicFill)
+ {
+ impStartSvtGraphicFill(pSvtGraphicFill);
+ }
+
+ mpOutputDevice->DrawPolyPolygon(aLocalPolyPolygon);
+
+ if(bSupportSvtGraphicFill)
+ {
+ impEndSvtGraphicFill(pSvtGraphicFill);
+ }
+
+ mpOutputDevice->Pop();
+ }
+
+ void VclMetafileProcessor2D::processMaskPrimitive2D(const primitive2d::MaskPrimitive2D& rMaskCandidate)
+ {
+ // mask group. Special handling for MetaFiles.
+ if(!rMaskCandidate.getChildren().empty())
+ {
+ basegfx::B2DPolyPolygon aMask(rMaskCandidate.getMask());
+
+ if(aMask.count())
{
- // mask group. Special handling for MetaFiles.
- const primitive2d::MaskPrimitive2D& rMaskCandidate = static_cast< const primitive2d::MaskPrimitive2D& >(rCandidate);
+ // prepare new mask polygon and rescue current one
+ aMask.transform(maCurrentTransformation);
+ const basegfx::B2DPolyPolygon aLastClipPolyPolygon(maClipPolyPolygon);
- if(!rMaskCandidate.getChildren().empty())
+ if(maClipPolyPolygon.count())
{
- basegfx::B2DPolyPolygon aMask(rMaskCandidate.getMask());
+ // 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(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());
- }
+ 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();
}
- break;
+ // restore to rescued clip polygon
+ maClipPolyPolygon = aLastClipPolyPolygon;
}
- case PRIMITIVE2D_ID_MODIFIEDCOLORPRIMITIVE2D :
+ else
{
- // modified color group. Force output to unified color. Use default pocessing.
- RenderModifiedColorPrimitive2D(static_cast< const primitive2d::ModifiedColorPrimitive2D& >(rCandidate));
- break;
+ // no mask, no clipping. recursively paint content
+ process(rMaskCandidate.getChildren());
}
- case PRIMITIVE2D_ID_UNIFIEDTRANSPARENCEPRIMITIVE2D :
+ }
+ }
+
+ void VclMetafileProcessor2D::processUnifiedTransparencePrimitive2D(const primitive2d::UnifiedTransparencePrimitive2D& rUniTransparenceCandidate)
+ {
+ 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::Primitive2DContainer& rContent = rUniTransparenceCandidate.getChildren();
+
+ if(!rContent.empty())
+ {
+ if(0.0 == rUniTransparenceCandidate.getTransparence())
{
- 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();
+ // 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(!rContent.empty())
+ if(!bForceToMetafile && 1 == rContent.size())
{
- 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);
- }
- }
+ const primitive2d::Primitive2DReference xReference(rContent[0]);
+ pPoPoColor = dynamic_cast< const primitive2d::PolyPolygonColorPrimitive2D* >(xReference.get());
}
- mpOutputDevice->Pop();
- 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())
+ // PolyPolygonGradientPrimitive2D, PolyPolygonHatchPrimitive2D and
+ // PolyPolygonGraphicPrimitive2D are derived from PolyPolygonColorPrimitive2D.
+ // Check also for correct ID to exclude derived implementations
+ if(pPoPoColor && PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D == pPoPoColor->getPrimitive2DID())
{
- // try to identify a single FillGradientPrimitive2D in the
- // transparence part of the primitive
- const primitive2d::FillGradientPrimitive2D* pFiGradient = nullptr;
- static bool bForceToBigTransparentVDev(false);
+ // 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);
- if(!bForceToBigTransparentVDev && 1 == rTransparence.size())
+ // 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())
{
- const primitive2d::Primitive2DReference xReference(rTransparence[0]);
- pFiGradient = dynamic_cast< const primitive2d::FillGradientPrimitive2D* >(xReference.get());
+ // 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());
}
- // Check also for correct ID to exclude derived implementations
- if(pFiGradient && PRIMITIVE2D_ID_FILLGRADIENTPRIMITIVE2D == pFiGradient->getPrimitive2DID())
+ // 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)
{
- // 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);
+ impStartSvtGraphicFill(pSvtGraphicFill);
}
- else
+
+ mpOutputDevice->DrawTransparent(
+ ::tools::PolyPolygon(aLocalPolyPolygon),
+ nTransPercentVcl);
+
+ if(bSupportSvtGraphicFill)
{
- // 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));
- }
+ impEndSvtGraphicFill(pSvtGraphicFill);
}
}
-
- break;
- }
- case PRIMITIVE2D_ID_TRANSFORMPRIMITIVE2D :
- {
- // use default transform group pocessing
- RenderTransformPrimitive2D(static_cast< const primitive2d::TransformPrimitive2D& >(rCandidate));
- break;
- }
- case PRIMITIVE2D_ID_PAGEPREVIEWPRIMITIVE2D :
- {
- // new XDrawPage for ViewInformation2D
- RenderPagePreviewPrimitive2D(static_cast< const primitive2d::PagePreviewPrimitive2D& >(rCandidate));
- break;
+ 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);
+ }
}
- case PRIMITIVE2D_ID_MARKERARRAYPRIMITIVE2D :
+ }
+
+ mpOutputDevice->Pop();
+ }
+
+ void VclMetafileProcessor2D::processTransparencePrimitive2D(const primitive2d::TransparencePrimitive2D& rTransparenceCandidate)
+ {
+ // 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::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())
{
- // use default marker array pocessing
- RenderMarkerArrayPrimitive2D(static_cast< const primitive2d::MarkerArrayPrimitive2D& >(rCandidate));
- break;
+ const primitive2d::Primitive2DReference xReference(rTransparence[0]);
+ pFiGradient = dynamic_cast< const primitive2d::FillGradientPrimitive2D* >(xReference.get());
}
- case PRIMITIVE2D_ID_POINTARRAYPRIMITIVE2D :
+
+ // Check also for correct ID to exclude derived implementations
+ if(pFiGradient && PRIMITIVE2D_ID_FILLGRADIENTPRIMITIVE2D == pFiGradient->getPrimitive2DID())
{
- // use default point array pocessing
- RenderPointArrayPrimitive2D(static_cast< const primitive2d::PointArrayPrimitive2D& >(rCandidate));
- break;
+ // 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);
}
- case PRIMITIVE2D_ID_STRUCTURETAGPRIMITIVE2D :
+ else
{
- // 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)
+ // 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)
{
- // write start tag
- mpPDFExtOutDevData->BeginStructureElement(rTagElement);
+ // 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));
}
- // process children normally
- process(rStructureTagCandidate.getChildren());
-
- if(mpPDFExtOutDevData && bTagUsed)
+ if(aBufferDevice->SetOutputSizePixel(aSizePixel))
{
- // write end tag
- mpPDFExtOutDevData->EndStructureElement();
- }
+ // 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);
+ }
- break;
- }
- case PRIMITIVE2D_ID_EPSPRIMITIVE2D :
- {
- RenderEpsPrimitive2D(static_cast< const primitive2d::EpsPrimitive2D& >(rCandidate));
- break;
- }
- default :
- {
- // process recursively
- process(rCandidate);
- break;
+ // 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));
+ }
}
}
}
+
+ void VclMetafileProcessor2D::processStructureTagPrimitive2D(const primitive2d::StructureTagPrimitive2D& rStructureTagCandidate)
+ {
+ // structured tag primitive
+ 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();
+ }
+ }
+
} // end of namespace processor2d
} // end of namespace drawinglayer
diff --git a/drawinglayer/source/processor2d/vclmetafileprocessor2d.hxx b/drawinglayer/source/processor2d/vclmetafileprocessor2d.hxx
index 122cafa47978..65007b487727 100644
--- a/drawinglayer/source/processor2d/vclmetafileprocessor2d.hxx
+++ b/drawinglayer/source/processor2d/vclmetafileprocessor2d.hxx
@@ -47,6 +47,28 @@ namespace drawinglayer { namespace attribute {
class LineStartEndAttribute;
}}
+namespace drawinglayer { namespace primitive2d {
+ class GraphicPrimitive2D;
+ class ControlPrimitive2D;
+ class TextHierarchyFieldPrimitive2D;
+ class TextHierarchyLinePrimitive2D;
+ class TextHierarchyBulletPrimitive2D;
+ class TextHierarchyParagraphPrimitive2D;
+ class TextHierarchyBlockPrimitive2D;
+ class TextSimplePortionPrimitive2D;
+ class PolygonHairlinePrimitive2D;
+ class PolygonStrokePrimitive2D;
+ class PolygonStrokeArrowPrimitive2D;
+ class PolyPolygonGraphicPrimitive2D;
+ class PolyPolygonHatchPrimitive2D;
+ class PolyPolygonGradientPrimitive2D;
+ class PolyPolygonColorPrimitive2D;
+ class MaskPrimitive2D;
+ class UnifiedTransparencePrimitive2D;
+ class TransparencePrimitive2D;
+ class StructureTagPrimitive2D;
+}}
+
namespace basegfx {
class BColor;
}
@@ -91,6 +113,26 @@ namespace drawinglayer
void impStartSvtGraphicStroke(SvtGraphicStroke const * pSvtGraphicStroke);
void impEndSvtGraphicStroke(SvtGraphicStroke* pSvtGraphicStroke);
+ void processGraphicPrimitive2D(const primitive2d::GraphicPrimitive2D& rGraphicPrimitive);
+ void processControlPrimitive2D(const primitive2d::ControlPrimitive2D& rControlPrimitive);
+ void processTextHierarchyFieldPrimitive2D(const primitive2d::TextHierarchyFieldPrimitive2D& rFieldPrimitive);
+ void processTextHierarchyLinePrimitive2D(const primitive2d::TextHierarchyLinePrimitive2D& rLinePrimitive);
+ void processTextHierarchyBulletPrimitive2D(const primitive2d::TextHierarchyBulletPrimitive2D& rBulletPrimitive);
+ void processTextHierarchyParagraphPrimitive2D(const primitive2d::TextHierarchyParagraphPrimitive2D& rParagraphPrimitive);
+ void processTextHierarchyBlockPrimitive2D(const primitive2d::TextHierarchyBlockPrimitive2D& rBlockPrimitive);
+ void processTextSimplePortionPrimitive2D(const primitive2d::TextSimplePortionPrimitive2D& rTextCandidate);
+ void processPolygonHairlinePrimitive2D(const primitive2d::PolygonHairlinePrimitive2D& rHairlinePrimitive);
+ void processPolygonStrokePrimitive2D(const primitive2d::PolygonStrokePrimitive2D& rStrokePrimitive);
+ void processPolygonStrokeArrowPrimitive2D(const primitive2d::PolygonStrokeArrowPrimitive2D& rStrokeArrowPrimitive);
+ void processPolyPolygonGraphicPrimitive2D(const primitive2d::PolyPolygonGraphicPrimitive2D& rBitmapCandidate);
+ void processPolyPolygonHatchPrimitive2D(const primitive2d::PolyPolygonHatchPrimitive2D& rHatchCandidate);
+ void processPolyPolygonGradientPrimitive2D(const primitive2d::PolyPolygonGradientPrimitive2D& rGradientCandidate);
+ void processPolyPolygonColorPrimitive2D(const primitive2d::PolyPolygonColorPrimitive2D& rPolygonCandidate);
+ void processMaskPrimitive2D(const primitive2d::MaskPrimitive2D& rMaskCandidate);
+ void processUnifiedTransparencePrimitive2D(const primitive2d::UnifiedTransparencePrimitive2D& rUniTransparenceCandidate);
+ void processTransparencePrimitive2D(const primitive2d::TransparencePrimitive2D& rTransparenceCandidate);
+ void processStructureTagPrimitive2D(const primitive2d::StructureTagPrimitive2D& rStructureTagCandidate);
+
/// Convert the fWidth to the same space as its coordinates.
double getTransformedLineWidth( double fWidth ) const;